Show More
@@ -20,6 +20,7 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 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 = |
|
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 = |
|
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 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 = |
|
136 | meta, offset = storageutil.parsemeta(text) | |
136 | if offset: |
|
137 | if offset: | |
137 | textlen -= offset |
|
138 | textlen -= offset | |
138 |
|
139 |
@@ -14,6 +14,7 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 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 = |
|
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 = |
|
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 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 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 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 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 class ifiledatatests(basetestcase): | |||||
882 | def testcensored(self): |
|
885 | def testcensored(self): | |
883 | f = self._makefilefn() |
|
886 | f = self._makefilefn() | |
884 |
|
887 | |||
885 |
stored1 = |
|
888 | stored1 = storageutil.packmeta({ | |
886 | b'censored': b'tombstone', |
|
889 | b'censored': b'tombstone', | |
887 | }, b'') |
|
890 | }, b'') | |
888 |
|
891 |
@@ -8,6 +8,7 | |||||
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 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 class filestorage(object): | |||||
326 | return False |
|
326 | return False | |
327 |
|
327 | |||
328 | fulltext = self.revision(node) |
|
328 | fulltext = self.revision(node) | |
329 |
m = |
|
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 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 = |
|
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