Show More
@@ -538,9 +538,6 b" coreconfigitem('experimental', 'hook-tra" | |||||
538 | coreconfigitem('experimental', 'httppostargs', |
|
538 | coreconfigitem('experimental', 'httppostargs', | |
539 | default=False, |
|
539 | default=False, | |
540 | ) |
|
540 | ) | |
541 | coreconfigitem('experimental', 'manifestv2', |
|
|||
542 | default=False, |
|
|||
543 | ) |
|
|||
544 | coreconfigitem('experimental', 'mergedriver', |
|
541 | coreconfigitem('experimental', 'mergedriver', | |
545 | default=None, |
|
542 | default=None, | |
546 | ) |
|
543 | ) |
@@ -1,4 +1,3 b'' | |||||
1 |
|
||||
2 | Repositories contain a file (``.hg/requires``) containing a list of |
|
1 | Repositories contain a file (``.hg/requires``) containing a list of | |
3 | features/capabilities that are *required* for clients to interface |
|
2 | features/capabilities that are *required* for clients to interface | |
4 | with the repository. This file has been present in Mercurial since |
|
3 | with the repository. This file has been present in Mercurial since | |
@@ -105,8 +104,10 b' manifestv2' | |||||
105 | Denotes that version 2 of manifests are being used. |
|
104 | Denotes that version 2 of manifests are being used. | |
106 |
|
105 | |||
107 | Support for this requirement was added in Mercurial 3.4 (released |
|
106 | Support for this requirement was added in Mercurial 3.4 (released | |
108 | May 2015). The requirement is currently experimental and is disabled |
|
107 | May 2015). The new format failed to meet expectations and support | |
109 | by default. |
|
108 | for the format and requirement were removed in Mercurial 4.6 | |
|
109 | (released May 2018) since the feature never graduated frome experiment | |||
|
110 | status. | |||
110 |
|
111 | |||
111 | treemanifest |
|
112 | treemanifest | |
112 | ============ |
|
113 | ============ |
@@ -303,11 +303,15 b" REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'" | |||||
303 |
|
303 | |||
304 | class localrepository(object): |
|
304 | class localrepository(object): | |
305 |
|
305 | |||
|
306 | # obsolete experimental requirements: | |||
|
307 | # - manifestv2: An experimental new manifest format that allowed | |||
|
308 | # for stem compression of long paths. Experiment ended up not | |||
|
309 | # being successful (repository sizes went up due to worse delta | |||
|
310 | # chains), and the code was deleted in 4.6. | |||
306 | supportedformats = { |
|
311 | supportedformats = { | |
307 | 'revlogv1', |
|
312 | 'revlogv1', | |
308 | 'generaldelta', |
|
313 | 'generaldelta', | |
309 | 'treemanifest', |
|
314 | 'treemanifest', | |
310 | 'manifestv2', |
|
|||
311 | REVLOGV2_REQUIREMENT, |
|
315 | REVLOGV2_REQUIREMENT, | |
312 | } |
|
316 | } | |
313 | _basesupported = supportedformats | { |
|
317 | _basesupported = supportedformats | { | |
@@ -322,7 +326,6 b' class localrepository(object):' | |||||
322 | 'revlogv1', |
|
326 | 'revlogv1', | |
323 | 'generaldelta', |
|
327 | 'generaldelta', | |
324 | 'treemanifest', |
|
328 | 'treemanifest', | |
325 | 'manifestv2', |
|
|||
326 | } |
|
329 | } | |
327 |
|
330 | |||
328 | # a list of (ui, featureset) functions. |
|
331 | # a list of (ui, featureset) functions. | |
@@ -2261,8 +2264,6 b' def newreporequirements(repo):' | |||||
2261 | requirements.add('generaldelta') |
|
2264 | requirements.add('generaldelta') | |
2262 | if ui.configbool('experimental', 'treemanifest'): |
|
2265 | if ui.configbool('experimental', 'treemanifest'): | |
2263 | requirements.add('treemanifest') |
|
2266 | requirements.add('treemanifest') | |
2264 | if ui.configbool('experimental', 'manifestv2'): |
|
|||
2265 | requirements.add('manifestv2') |
|
|||
2266 |
|
2267 | |||
2267 | revlogv2 = ui.config('experimental', 'revlogv2') |
|
2268 | revlogv2 = ui.config('experimental', 'revlogv2') | |
2268 | if revlogv2 == 'enable-unstable-format-and-corrupt-my-data': |
|
2269 | if revlogv2 == 'enable-unstable-format-and-corrupt-my-data': |
@@ -9,7 +9,6 b' from __future__ import absolute_import' | |||||
9 |
|
9 | |||
10 | import heapq |
|
10 | import heapq | |
11 | import itertools |
|
11 | import itertools | |
12 | import os |
|
|||
13 | import struct |
|
12 | import struct | |
14 |
|
13 | |||
15 | from .i18n import _ |
|
14 | from .i18n import _ | |
@@ -28,7 +27,7 b' from . import (' | |||||
28 | parsers = policy.importmod(r'parsers') |
|
27 | parsers = policy.importmod(r'parsers') | |
29 | propertycache = util.propertycache |
|
28 | propertycache = util.propertycache | |
30 |
|
29 | |||
31 |
def _parse |
|
30 | def _parse(data): | |
32 | # This method does a little bit of excessive-looking |
|
31 | # This method does a little bit of excessive-looking | |
33 | # precondition checking. This is so that the behavior of this |
|
32 | # precondition checking. This is so that the behavior of this | |
34 | # class exactly matches its C counterpart to try and help |
|
33 | # class exactly matches its C counterpart to try and help | |
@@ -47,43 +46,7 b' def _parsev1(data):' | |||||
47 | else: |
|
46 | else: | |
48 | yield f, bin(n), '' |
|
47 | yield f, bin(n), '' | |
49 |
|
48 | |||
50 |
def _ |
|
49 | def _text(it): | |
51 | metadataend = data.find('\n') |
|
|||
52 | # Just ignore metadata for now |
|
|||
53 | pos = metadataend + 1 |
|
|||
54 | prevf = '' |
|
|||
55 | while pos < len(data): |
|
|||
56 | end = data.find('\n', pos + 1) # +1 to skip stem length byte |
|
|||
57 | if end == -1: |
|
|||
58 | raise ValueError('Manifest ended with incomplete file entry.') |
|
|||
59 | stemlen = ord(data[pos:pos + 1]) |
|
|||
60 | items = data[pos + 1:end].split('\0') |
|
|||
61 | f = prevf[:stemlen] + items[0] |
|
|||
62 | if prevf > f: |
|
|||
63 | raise ValueError('Manifest entries not in sorted order.') |
|
|||
64 | fl = items[1] |
|
|||
65 | # Just ignore metadata (items[2:] for now) |
|
|||
66 | n = data[end + 1:end + 21] |
|
|||
67 | yield f, n, fl |
|
|||
68 | pos = end + 22 |
|
|||
69 | prevf = f |
|
|||
70 |
|
||||
71 | def _parse(data): |
|
|||
72 | """Generates (path, node, flags) tuples from a manifest text""" |
|
|||
73 | if data.startswith('\0'): |
|
|||
74 | return iter(_parsev2(data)) |
|
|||
75 | else: |
|
|||
76 | return iter(_parsev1(data)) |
|
|||
77 |
|
||||
78 | def _text(it, usemanifestv2): |
|
|||
79 | """Given an iterator over (path, node, flags) tuples, returns a manifest |
|
|||
80 | text""" |
|
|||
81 | if usemanifestv2: |
|
|||
82 | return _textv2(it) |
|
|||
83 | else: |
|
|||
84 | return _textv1(it) |
|
|||
85 |
|
||||
86 | def _textv1(it): |
|
|||
87 | files = [] |
|
50 | files = [] | |
88 | lines = [] |
|
51 | lines = [] | |
89 | _hex = revlog.hex |
|
52 | _hex = revlog.hex | |
@@ -96,19 +59,6 b' def _textv1(it):' | |||||
96 | _checkforbidden(files) |
|
59 | _checkforbidden(files) | |
97 | return ''.join(lines) |
|
60 | return ''.join(lines) | |
98 |
|
61 | |||
99 | def _textv2(it): |
|
|||
100 | files = [] |
|
|||
101 | lines = ['\0\n'] |
|
|||
102 | prevf = '' |
|
|||
103 | for f, n, fl in it: |
|
|||
104 | files.append(f) |
|
|||
105 | stem = os.path.commonprefix([prevf, f]) |
|
|||
106 | stemlen = min(len(stem), 255) |
|
|||
107 | lines.append("%c%s\0%s\n%s\n" % (stemlen, f[stemlen:], fl, n)) |
|
|||
108 | prevf = f |
|
|||
109 | _checkforbidden(files) |
|
|||
110 | return ''.join(lines) |
|
|||
111 |
|
||||
112 | class lazymanifestiter(object): |
|
62 | class lazymanifestiter(object): | |
113 | def __init__(self, lm): |
|
63 | def __init__(self, lm): | |
114 | self.pos = 0 |
|
64 | self.pos = 0 | |
@@ -414,13 +364,7 b' except AttributeError:' | |||||
414 |
|
364 | |||
415 | class manifestdict(object): |
|
365 | class manifestdict(object): | |
416 | def __init__(self, data=''): |
|
366 | def __init__(self, data=''): | |
417 | if data.startswith('\0'): |
|
367 | self._lm = _lazymanifest(data) | |
418 | #_lazymanifest can not parse v2 |
|
|||
419 | self._lm = _lazymanifest('') |
|
|||
420 | for f, n, fl in _parsev2(data): |
|
|||
421 | self._lm[f] = n, fl |
|
|||
422 | else: |
|
|||
423 | self._lm = _lazymanifest(data) |
|
|||
424 |
|
368 | |||
425 | def __getitem__(self, key): |
|
369 | def __getitem__(self, key): | |
426 | return self._lm[key][0] |
|
370 | return self._lm[key][0] | |
@@ -589,12 +533,9 b' class manifestdict(object):' | |||||
589 | def iterentries(self): |
|
533 | def iterentries(self): | |
590 | return self._lm.iterentries() |
|
534 | return self._lm.iterentries() | |
591 |
|
535 | |||
592 |
def text(self |
|
536 | def text(self): | |
593 | if usemanifestv2: |
|
537 | # most likely uses native version | |
594 |
|
|
538 | return self._lm.text() | |
595 | else: |
|
|||
596 | # use (probably) native version for v1 |
|
|||
597 | return self._lm.text() |
|
|||
598 |
|
539 | |||
599 | def fastdelta(self, base, changes): |
|
540 | def fastdelta(self, base, changes): | |
600 | """Given a base manifest text as a bytearray and a list of changes |
|
541 | """Given a base manifest text as a bytearray and a list of changes | |
@@ -1138,12 +1079,12 b' class treemanifest(object):' | |||||
1138 | if fl: |
|
1079 | if fl: | |
1139 | self._flags[f] = fl |
|
1080 | self._flags[f] = fl | |
1140 |
|
1081 | |||
1141 |
def text(self |
|
1082 | def text(self): | |
1142 | """Get the full data of this manifest as a bytestring.""" |
|
1083 | """Get the full data of this manifest as a bytestring.""" | |
1143 | self._load() |
|
1084 | self._load() | |
1144 |
return _text(self.iterentries() |
|
1085 | return _text(self.iterentries()) | |
1145 |
|
1086 | |||
1146 |
def dirtext(self |
|
1087 | def dirtext(self): | |
1147 | """Get the full data of this directory as a bytestring. Make sure that |
|
1088 | """Get the full data of this directory as a bytestring. Make sure that | |
1148 | any submanifests have been written first, so their nodeids are correct. |
|
1089 | any submanifests have been written first, so their nodeids are correct. | |
1149 | """ |
|
1090 | """ | |
@@ -1151,7 +1092,7 b' class treemanifest(object):' | |||||
1151 | flags = self.flags |
|
1092 | flags = self.flags | |
1152 | dirs = [(d[:-1], self._dirs[d]._node, 't') for d in self._dirs] |
|
1093 | dirs = [(d[:-1], self._dirs[d]._node, 't') for d in self._dirs] | |
1153 | files = [(f, self._files[f], flags(f)) for f in self._files] |
|
1094 | files = [(f, self._files[f], flags(f)) for f in self._files] | |
1154 |
return _text(sorted(dirs + files) |
|
1095 | return _text(sorted(dirs + files)) | |
1155 |
|
1096 | |||
1156 | def read(self, gettext, readsubtree): |
|
1097 | def read(self, gettext, readsubtree): | |
1157 | def _load_for_read(s): |
|
1098 | def _load_for_read(s): | |
@@ -1208,15 +1149,12 b' class manifestrevlog(revlog.revlog):' | |||||
1208 | # stacks of commits, the number can go up, hence the config knob below. |
|
1149 | # stacks of commits, the number can go up, hence the config knob below. | |
1209 | cachesize = 4 |
|
1150 | cachesize = 4 | |
1210 | optiontreemanifest = False |
|
1151 | optiontreemanifest = False | |
1211 | usemanifestv2 = False |
|
|||
1212 | opts = getattr(opener, 'options', None) |
|
1152 | opts = getattr(opener, 'options', None) | |
1213 | if opts is not None: |
|
1153 | if opts is not None: | |
1214 | cachesize = opts.get('manifestcachesize', cachesize) |
|
1154 | cachesize = opts.get('manifestcachesize', cachesize) | |
1215 | optiontreemanifest = opts.get('treemanifest', False) |
|
1155 | optiontreemanifest = opts.get('treemanifest', False) | |
1216 | usemanifestv2 = opts.get('manifestv2', usemanifestv2) |
|
|||
1217 |
|
1156 | |||
1218 | self._treeondisk = optiontreemanifest or treemanifest |
|
1157 | self._treeondisk = optiontreemanifest or treemanifest | |
1219 | self._usemanifestv2 = usemanifestv2 |
|
|||
1220 |
|
1158 | |||
1221 | self._fulltextcache = util.lrucachedict(cachesize) |
|
1159 | self._fulltextcache = util.lrucachedict(cachesize) | |
1222 |
|
1160 | |||
@@ -1262,8 +1200,7 b' class manifestrevlog(revlog.revlog):' | |||||
1262 | return self._dirlogcache[d] |
|
1200 | return self._dirlogcache[d] | |
1263 |
|
1201 | |||
1264 | def add(self, m, transaction, link, p1, p2, added, removed, readtree=None): |
|
1202 | def add(self, m, transaction, link, p1, p2, added, removed, readtree=None): | |
1265 |
if |
|
1203 | if p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta'): | |
1266 | and not self._usemanifestv2): |
|
|||
1267 | # If our first parent is in the manifest cache, we can |
|
1204 | # If our first parent is in the manifest cache, we can | |
1268 | # compute a delta here using properties we know about the |
|
1205 | # compute a delta here using properties we know about the | |
1269 | # manifest up-front, which may save time later for the |
|
1206 | # manifest up-front, which may save time later for the | |
@@ -1290,7 +1227,7 b' class manifestrevlog(revlog.revlog):' | |||||
1290 | n = self._addtree(m, transaction, link, m1, m2, readtree) |
|
1227 | n = self._addtree(m, transaction, link, m1, m2, readtree) | |
1291 | arraytext = None |
|
1228 | arraytext = None | |
1292 | else: |
|
1229 | else: | |
1293 |
text = m.text( |
|
1230 | text = m.text() | |
1294 | n = self.addrevision(text, transaction, link, p1, p2) |
|
1231 | n = self.addrevision(text, transaction, link, p1, p2) | |
1295 | arraytext = bytearray(text) |
|
1232 | arraytext = bytearray(text) | |
1296 |
|
1233 | |||
@@ -1309,13 +1246,13 b' class manifestrevlog(revlog.revlog):' | |||||
1309 | sublog.add(subm, transaction, link, subp1, subp2, None, None, |
|
1246 | sublog.add(subm, transaction, link, subp1, subp2, None, None, | |
1310 | readtree=readtree) |
|
1247 | readtree=readtree) | |
1311 | m.writesubtrees(m1, m2, writesubtree) |
|
1248 | m.writesubtrees(m1, m2, writesubtree) | |
1312 |
text = m.dirtext( |
|
1249 | text = m.dirtext() | |
1313 | n = None |
|
1250 | n = None | |
1314 | if self._dir != '': |
|
1251 | if self._dir != '': | |
1315 | # Double-check whether contents are unchanged to one parent |
|
1252 | # Double-check whether contents are unchanged to one parent | |
1316 |
if text == m1.dirtext( |
|
1253 | if text == m1.dirtext(): | |
1317 | n = m1.node() |
|
1254 | n = m1.node() | |
1318 |
elif text == m2.dirtext( |
|
1255 | elif text == m2.dirtext(): | |
1319 | n = m2.node() |
|
1256 | n = m2.node() | |
1320 |
|
1257 | |||
1321 | if not n: |
|
1258 | if not n: | |
@@ -1493,19 +1430,6 b' class manifestctx(object):' | |||||
1493 | Changing the value of `shallow` has no effect on flat manifests. |
|
1430 | Changing the value of `shallow` has no effect on flat manifests. | |
1494 | ''' |
|
1431 | ''' | |
1495 | revlog = self._revlog() |
|
1432 | revlog = self._revlog() | |
1496 | if revlog._usemanifestv2: |
|
|||
1497 | # Need to perform a slow delta |
|
|||
1498 | r0 = revlog.deltaparent(revlog.rev(self._node)) |
|
|||
1499 | m0 = self._manifestlog[revlog.node(r0)].read() |
|
|||
1500 | m1 = self.read() |
|
|||
1501 | md = manifestdict() |
|
|||
1502 | for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).iteritems(): |
|
|||
1503 | if n1: |
|
|||
1504 | md[f] = n1 |
|
|||
1505 | if fl1: |
|
|||
1506 | md.setflag(f, fl1) |
|
|||
1507 | return md |
|
|||
1508 |
|
||||
1509 | r = revlog.rev(self._node) |
|
1433 | r = revlog.rev(self._node) | |
1510 | d = mdiff.patchtext(revlog.revdiff(revlog.deltaparent(r), r)) |
|
1434 | d = mdiff.patchtext(revlog.revdiff(revlog.deltaparent(r), r)) | |
1511 | return manifestdict(d) |
|
1435 | return manifestdict(d) | |
@@ -1608,7 +1532,7 b' class treemanifestctx(object):' | |||||
1608 | its 't' flag. |
|
1532 | its 't' flag. | |
1609 | ''' |
|
1533 | ''' | |
1610 | revlog = self._revlog() |
|
1534 | revlog = self._revlog() | |
1611 | if shallow and not revlog._usemanifestv2: |
|
1535 | if shallow: | |
1612 | r = revlog.rev(self._node) |
|
1536 | r = revlog.rev(self._node) | |
1613 | d = mdiff.patchtext(revlog.revdiff(revlog.deltaparent(r), r)) |
|
1537 | d = mdiff.patchtext(revlog.revdiff(revlog.deltaparent(r), r)) | |
1614 | return manifestdict(d) |
|
1538 | return manifestdict(d) |
@@ -46,7 +46,6 b' def blocksourcerequirements(repo):' | |||||
46 | return { |
|
46 | return { | |
47 | # The upgrade code does not yet support these experimental features. |
|
47 | # The upgrade code does not yet support these experimental features. | |
48 | # This is an artificial limitation. |
|
48 | # This is an artificial limitation. | |
49 | 'manifestv2', |
|
|||
50 | 'treemanifest', |
|
49 | 'treemanifest', | |
51 | # This was a precursor to generaldelta and was never enabled by default. |
|
50 | # This was a precursor to generaldelta and was never enabled by default. | |
52 | # It should (hopefully) not exist in the wild. |
|
51 | # It should (hopefully) not exist in the wild. |
@@ -11,7 +11,6 b' from mercurial import (' | |||||
11 | ) |
|
11 | ) | |
12 |
|
12 | |||
13 | EMTPY_MANIFEST = b'' |
|
13 | EMTPY_MANIFEST = b'' | |
14 | EMTPY_MANIFEST_V2 = b'\0\n' |
|
|||
15 |
|
14 | |||
16 | HASH_1 = b'1' * 40 |
|
15 | HASH_1 = b'1' * 40 | |
17 | BIN_HASH_1 = binascii.unhexlify(HASH_1) |
|
16 | BIN_HASH_1 = binascii.unhexlify(HASH_1) | |
@@ -28,42 +27,6 b' A_SHORT_MANIFEST = (' | |||||
28 | b'flag2': b'l', |
|
27 | b'flag2': b'l', | |
29 | } |
|
28 | } | |
30 |
|
29 | |||
31 | # Same data as A_SHORT_MANIFEST |
|
|||
32 | A_SHORT_MANIFEST_V2 = ( |
|
|||
33 | b'\0\n' |
|
|||
34 | b'\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' |
|
|||
35 | b'\x00foo\0%(flag1)s\n%(hash1)s\n' |
|
|||
36 | ) % {b'hash1': BIN_HASH_1, |
|
|||
37 | b'flag1': b'', |
|
|||
38 | b'hash2': BIN_HASH_2, |
|
|||
39 | b'flag2': b'l', |
|
|||
40 | } |
|
|||
41 |
|
||||
42 | # Same data as A_SHORT_MANIFEST |
|
|||
43 | A_METADATA_MANIFEST = ( |
|
|||
44 | b'\0foo\0bar\n' |
|
|||
45 | b'\x00bar/baz/qux.py\0%(flag2)s\0foo\0bar\n%(hash2)s\n' # flag and metadata |
|
|||
46 | b'\x00foo\0%(flag1)s\0foo\n%(hash1)s\n' # no flag, but metadata |
|
|||
47 | ) % {b'hash1': BIN_HASH_1, |
|
|||
48 | b'flag1': b'', |
|
|||
49 | b'hash2': BIN_HASH_2, |
|
|||
50 | b'flag2': b'l', |
|
|||
51 | } |
|
|||
52 |
|
||||
53 | A_STEM_COMPRESSED_MANIFEST = ( |
|
|||
54 | b'\0\n' |
|
|||
55 | b'\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' |
|
|||
56 | b'\x04qux/foo.py\0%(flag1)s\n%(hash1)s\n' # simple case of 4 stem chars |
|
|||
57 | b'\x0az.py\0%(flag1)s\n%(hash1)s\n' # tricky newline = 10 stem characters |
|
|||
58 | b'\x00%(verylongdir)sx/x\0\n%(hash1)s\n' |
|
|||
59 | b'\xffx/y\0\n%(hash2)s\n' # more than 255 stem chars |
|
|||
60 | ) % {b'hash1': BIN_HASH_1, |
|
|||
61 | b'flag1': b'', |
|
|||
62 | b'hash2': BIN_HASH_2, |
|
|||
63 | b'flag2': b'l', |
|
|||
64 | b'verylongdir': 255 * b'x', |
|
|||
65 | } |
|
|||
66 |
|
||||
67 | A_DEEPER_MANIFEST = ( |
|
30 | A_DEEPER_MANIFEST = ( | |
68 | b'a/b/c/bar.py\0%(hash3)s%(flag1)s\n' |
|
31 | b'a/b/c/bar.py\0%(hash3)s%(flag1)s\n' | |
69 | b'a/b/c/bar.txt\0%(hash1)s%(flag1)s\n' |
|
32 | b'a/b/c/bar.txt\0%(hash1)s%(flag1)s\n' | |
@@ -111,11 +74,6 b' class basemanifesttests(object):' | |||||
111 | self.assertEqual(0, len(m)) |
|
74 | self.assertEqual(0, len(m)) | |
112 | self.assertEqual([], list(m)) |
|
75 | self.assertEqual([], list(m)) | |
113 |
|
76 | |||
114 | def testEmptyManifestv2(self): |
|
|||
115 | m = self.parsemanifest(EMTPY_MANIFEST_V2) |
|
|||
116 | self.assertEqual(0, len(m)) |
|
|||
117 | self.assertEqual([], list(m)) |
|
|||
118 |
|
||||
119 | def testManifest(self): |
|
77 | def testManifest(self): | |
120 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
78 | m = self.parsemanifest(A_SHORT_MANIFEST) | |
121 | self.assertEqual([b'bar/baz/qux.py', b'foo'], list(m)) |
|
79 | self.assertEqual([b'bar/baz/qux.py', b'foo'], list(m)) | |
@@ -126,31 +84,6 b' class basemanifesttests(object):' | |||||
126 | with self.assertRaises(KeyError): |
|
84 | with self.assertRaises(KeyError): | |
127 | m[b'wat'] |
|
85 | m[b'wat'] | |
128 |
|
86 | |||
129 | def testParseManifestV2(self): |
|
|||
130 | m1 = self.parsemanifest(A_SHORT_MANIFEST) |
|
|||
131 | m2 = self.parsemanifest(A_SHORT_MANIFEST_V2) |
|
|||
132 | # Should have same content as A_SHORT_MANIFEST |
|
|||
133 | self.assertEqual(m1.text(), m2.text()) |
|
|||
134 |
|
||||
135 | def testParseManifestMetadata(self): |
|
|||
136 | # Metadata is for future-proofing and should be accepted but ignored |
|
|||
137 | m = self.parsemanifest(A_METADATA_MANIFEST) |
|
|||
138 | self.assertEqual(A_SHORT_MANIFEST, m.text()) |
|
|||
139 |
|
||||
140 | def testParseManifestStemCompression(self): |
|
|||
141 | m = self.parsemanifest(A_STEM_COMPRESSED_MANIFEST) |
|
|||
142 | self.assertIn(b'bar/baz/qux.py', m) |
|
|||
143 | self.assertIn(b'bar/qux/foo.py', m) |
|
|||
144 | self.assertIn(b'bar/qux/foz.py', m) |
|
|||
145 | self.assertIn(256 * b'x' + b'/x', m) |
|
|||
146 | self.assertIn(256 * b'x' + b'/y', m) |
|
|||
147 | self.assertEqual(A_STEM_COMPRESSED_MANIFEST, m.text(usemanifestv2=True)) |
|
|||
148 |
|
||||
149 | def testTextV2(self): |
|
|||
150 | m1 = self.parsemanifest(A_SHORT_MANIFEST) |
|
|||
151 | v2text = m1.text(usemanifestv2=True) |
|
|||
152 | self.assertEqual(A_SHORT_MANIFEST_V2, v2text) |
|
|||
153 |
|
||||
154 | def testSetItem(self): |
|
87 | def testSetItem(self): | |
155 | want = BIN_HASH_1 |
|
88 | want = BIN_HASH_1 | |
156 |
|
89 |
@@ -31,23 +31,18 b' Cannot upgrade shared repositories' | |||||
31 | abort: cannot upgrade repository; unsupported source requirement: shared |
|
31 | abort: cannot upgrade repository; unsupported source requirement: shared | |
32 | [255] |
|
32 | [255] | |
33 |
|
33 | |||
34 |
Do not yet support upgrading |
|
34 | Do not yet support upgrading treemanifest repos | |
35 |
|
||||
36 | $ hg --config experimental.manifestv2=true init manifestv2 |
|
|||
37 | $ hg -R manifestv2 debugupgraderepo |
|
|||
38 | abort: cannot upgrade repository; unsupported source requirement: manifestv2 |
|
|||
39 | [255] |
|
|||
40 |
|
35 | |||
41 |
$ |
|
36 | $ hg --config experimental.treemanifest=true init treemanifest | |
42 | $ hg -R treemanifest debugupgraderepo |
|
37 | $ hg -R treemanifest debugupgraderepo | |
43 | abort: cannot upgrade repository; unsupported source requirement: treemanifest |
|
38 | abort: cannot upgrade repository; unsupported source requirement: treemanifest | |
44 | [255] |
|
39 | [255] | |
45 |
|
40 | |||
46 |
Cannot add |
|
41 | Cannot add treemanifest requirement during upgrade | |
47 |
|
42 | |||
48 | $ hg init disallowaddedreq |
|
43 | $ hg init disallowaddedreq | |
49 |
$ hg -R disallowaddedreq --config experimental. |
|
44 | $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo | |
50 |
abort: cannot upgrade repository; do not support adding requirement: |
|
45 | abort: cannot upgrade repository; do not support adding requirement: treemanifest | |
51 | [255] |
|
46 | [255] | |
52 |
|
47 | |||
53 | An upgrade of a repository created with recommended settings only suggests optimizations |
|
48 | An upgrade of a repository created with recommended settings only suggests optimizations |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now