Show More
@@ -1,829 +1,834 b'' | |||||
1 | # store.py - repository store handling for Mercurial |
|
1 | # store.py - repository store handling for Mercurial | |
2 | # |
|
2 | # | |
3 | # Copyright 2008 Olivia Mackall <olivia@selenic.com> |
|
3 | # Copyright 2008 Olivia Mackall <olivia@selenic.com> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | import errno |
|
10 | import errno | |
11 | import functools |
|
11 | import functools | |
12 | import os |
|
12 | import os | |
13 | import re |
|
13 | import re | |
14 | import stat |
|
14 | import stat | |
15 |
|
15 | |||
16 | from .i18n import _ |
|
16 | from .i18n import _ | |
17 | from .pycompat import getattr |
|
17 | from .pycompat import getattr | |
18 | from .node import hex |
|
18 | from .node import hex | |
19 | from . import ( |
|
19 | from . import ( | |
20 | changelog, |
|
20 | changelog, | |
21 | error, |
|
21 | error, | |
22 | manifest, |
|
22 | manifest, | |
23 | policy, |
|
23 | policy, | |
24 | pycompat, |
|
24 | pycompat, | |
25 | util, |
|
25 | util, | |
26 | vfs as vfsmod, |
|
26 | vfs as vfsmod, | |
27 | ) |
|
27 | ) | |
28 | from .utils import hashutil |
|
28 | from .utils import hashutil | |
29 |
|
29 | |||
30 | parsers = policy.importmod('parsers') |
|
30 | parsers = policy.importmod('parsers') | |
31 | # how much bytes should be read from fncache in one read |
|
31 | # how much bytes should be read from fncache in one read | |
32 | # It is done to prevent loading large fncache files into memory |
|
32 | # It is done to prevent loading large fncache files into memory | |
33 | fncache_chunksize = 10 ** 6 |
|
33 | fncache_chunksize = 10 ** 6 | |
34 |
|
34 | |||
35 |
|
35 | |||
36 | def _matchtrackedpath(path, matcher): |
|
36 | def _matchtrackedpath(path, matcher): | |
37 | """parses a fncache entry and returns whether the entry is tracking a path |
|
37 | """parses a fncache entry and returns whether the entry is tracking a path | |
38 | matched by matcher or not. |
|
38 | matched by matcher or not. | |
39 |
|
39 | |||
40 | If matcher is None, returns True""" |
|
40 | If matcher is None, returns True""" | |
41 |
|
41 | |||
42 | if matcher is None: |
|
42 | if matcher is None: | |
43 | return True |
|
43 | return True | |
44 | path = decodedir(path) |
|
44 | path = decodedir(path) | |
45 | if path.startswith(b'data/'): |
|
45 | if path.startswith(b'data/'): | |
46 | return matcher(path[len(b'data/') : -len(b'.i')]) |
|
46 | return matcher(path[len(b'data/') : -len(b'.i')]) | |
47 | elif path.startswith(b'meta/'): |
|
47 | elif path.startswith(b'meta/'): | |
48 | return matcher.visitdir(path[len(b'meta/') : -len(b'/00manifest.i')]) |
|
48 | return matcher.visitdir(path[len(b'meta/') : -len(b'/00manifest.i')]) | |
49 |
|
49 | |||
50 | raise error.ProgrammingError(b"cannot decode path %s" % path) |
|
50 | raise error.ProgrammingError(b"cannot decode path %s" % path) | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | # This avoids a collision between a file named foo and a dir named |
|
53 | # This avoids a collision between a file named foo and a dir named | |
54 | # foo.i or foo.d |
|
54 | # foo.i or foo.d | |
55 | def _encodedir(path): |
|
55 | def _encodedir(path): | |
56 | """ |
|
56 | """ | |
57 | >>> _encodedir(b'data/foo.i') |
|
57 | >>> _encodedir(b'data/foo.i') | |
58 | 'data/foo.i' |
|
58 | 'data/foo.i' | |
59 | >>> _encodedir(b'data/foo.i/bla.i') |
|
59 | >>> _encodedir(b'data/foo.i/bla.i') | |
60 | 'data/foo.i.hg/bla.i' |
|
60 | 'data/foo.i.hg/bla.i' | |
61 | >>> _encodedir(b'data/foo.i.hg/bla.i') |
|
61 | >>> _encodedir(b'data/foo.i.hg/bla.i') | |
62 | 'data/foo.i.hg.hg/bla.i' |
|
62 | 'data/foo.i.hg.hg/bla.i' | |
63 | >>> _encodedir(b'data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n') |
|
63 | >>> _encodedir(b'data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n') | |
64 | 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n' |
|
64 | 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n' | |
65 | """ |
|
65 | """ | |
66 | return ( |
|
66 | return ( | |
67 | path.replace(b".hg/", b".hg.hg/") |
|
67 | path.replace(b".hg/", b".hg.hg/") | |
68 | .replace(b".i/", b".i.hg/") |
|
68 | .replace(b".i/", b".i.hg/") | |
69 | .replace(b".d/", b".d.hg/") |
|
69 | .replace(b".d/", b".d.hg/") | |
70 | ) |
|
70 | ) | |
71 |
|
71 | |||
72 |
|
72 | |||
73 | encodedir = getattr(parsers, 'encodedir', _encodedir) |
|
73 | encodedir = getattr(parsers, 'encodedir', _encodedir) | |
74 |
|
74 | |||
75 |
|
75 | |||
76 | def decodedir(path): |
|
76 | def decodedir(path): | |
77 | """ |
|
77 | """ | |
78 | >>> decodedir(b'data/foo.i') |
|
78 | >>> decodedir(b'data/foo.i') | |
79 | 'data/foo.i' |
|
79 | 'data/foo.i' | |
80 | >>> decodedir(b'data/foo.i.hg/bla.i') |
|
80 | >>> decodedir(b'data/foo.i.hg/bla.i') | |
81 | 'data/foo.i/bla.i' |
|
81 | 'data/foo.i/bla.i' | |
82 | >>> decodedir(b'data/foo.i.hg.hg/bla.i') |
|
82 | >>> decodedir(b'data/foo.i.hg.hg/bla.i') | |
83 | 'data/foo.i.hg/bla.i' |
|
83 | 'data/foo.i.hg/bla.i' | |
84 | """ |
|
84 | """ | |
85 | if b".hg/" not in path: |
|
85 | if b".hg/" not in path: | |
86 | return path |
|
86 | return path | |
87 | return ( |
|
87 | return ( | |
88 | path.replace(b".d.hg/", b".d/") |
|
88 | path.replace(b".d.hg/", b".d/") | |
89 | .replace(b".i.hg/", b".i/") |
|
89 | .replace(b".i.hg/", b".i/") | |
90 | .replace(b".hg.hg/", b".hg/") |
|
90 | .replace(b".hg.hg/", b".hg/") | |
91 | ) |
|
91 | ) | |
92 |
|
92 | |||
93 |
|
93 | |||
94 | def _reserved(): |
|
94 | def _reserved(): | |
95 | """characters that are problematic for filesystems |
|
95 | """characters that are problematic for filesystems | |
96 |
|
96 | |||
97 | * ascii escapes (0..31) |
|
97 | * ascii escapes (0..31) | |
98 | * ascii hi (126..255) |
|
98 | * ascii hi (126..255) | |
99 | * windows specials |
|
99 | * windows specials | |
100 |
|
100 | |||
101 | these characters will be escaped by encodefunctions |
|
101 | these characters will be escaped by encodefunctions | |
102 | """ |
|
102 | """ | |
103 | winreserved = [ord(x) for x in u'\\:*?"<>|'] |
|
103 | winreserved = [ord(x) for x in u'\\:*?"<>|'] | |
104 | for x in range(32): |
|
104 | for x in range(32): | |
105 | yield x |
|
105 | yield x | |
106 | for x in range(126, 256): |
|
106 | for x in range(126, 256): | |
107 | yield x |
|
107 | yield x | |
108 | for x in winreserved: |
|
108 | for x in winreserved: | |
109 | yield x |
|
109 | yield x | |
110 |
|
110 | |||
111 |
|
111 | |||
112 | def _buildencodefun(): |
|
112 | def _buildencodefun(): | |
113 | """ |
|
113 | """ | |
114 | >>> enc, dec = _buildencodefun() |
|
114 | >>> enc, dec = _buildencodefun() | |
115 |
|
115 | |||
116 | >>> enc(b'nothing/special.txt') |
|
116 | >>> enc(b'nothing/special.txt') | |
117 | 'nothing/special.txt' |
|
117 | 'nothing/special.txt' | |
118 | >>> dec(b'nothing/special.txt') |
|
118 | >>> dec(b'nothing/special.txt') | |
119 | 'nothing/special.txt' |
|
119 | 'nothing/special.txt' | |
120 |
|
120 | |||
121 | >>> enc(b'HELLO') |
|
121 | >>> enc(b'HELLO') | |
122 | '_h_e_l_l_o' |
|
122 | '_h_e_l_l_o' | |
123 | >>> dec(b'_h_e_l_l_o') |
|
123 | >>> dec(b'_h_e_l_l_o') | |
124 | 'HELLO' |
|
124 | 'HELLO' | |
125 |
|
125 | |||
126 | >>> enc(b'hello:world?') |
|
126 | >>> enc(b'hello:world?') | |
127 | 'hello~3aworld~3f' |
|
127 | 'hello~3aworld~3f' | |
128 | >>> dec(b'hello~3aworld~3f') |
|
128 | >>> dec(b'hello~3aworld~3f') | |
129 | 'hello:world?' |
|
129 | 'hello:world?' | |
130 |
|
130 | |||
131 | >>> enc(b'the\\x07quick\\xADshot') |
|
131 | >>> enc(b'the\\x07quick\\xADshot') | |
132 | 'the~07quick~adshot' |
|
132 | 'the~07quick~adshot' | |
133 | >>> dec(b'the~07quick~adshot') |
|
133 | >>> dec(b'the~07quick~adshot') | |
134 | 'the\\x07quick\\xadshot' |
|
134 | 'the\\x07quick\\xadshot' | |
135 | """ |
|
135 | """ | |
136 | e = b'_' |
|
136 | e = b'_' | |
137 | xchr = pycompat.bytechr |
|
137 | xchr = pycompat.bytechr | |
138 | asciistr = list(map(xchr, range(127))) |
|
138 | asciistr = list(map(xchr, range(127))) | |
139 | capitals = list(range(ord(b"A"), ord(b"Z") + 1)) |
|
139 | capitals = list(range(ord(b"A"), ord(b"Z") + 1)) | |
140 |
|
140 | |||
141 | cmap = {x: x for x in asciistr} |
|
141 | cmap = {x: x for x in asciistr} | |
142 | for x in _reserved(): |
|
142 | for x in _reserved(): | |
143 | cmap[xchr(x)] = b"~%02x" % x |
|
143 | cmap[xchr(x)] = b"~%02x" % x | |
144 | for x in capitals + [ord(e)]: |
|
144 | for x in capitals + [ord(e)]: | |
145 | cmap[xchr(x)] = e + xchr(x).lower() |
|
145 | cmap[xchr(x)] = e + xchr(x).lower() | |
146 |
|
146 | |||
147 | dmap = {} |
|
147 | dmap = {} | |
148 | for k, v in pycompat.iteritems(cmap): |
|
148 | for k, v in pycompat.iteritems(cmap): | |
149 | dmap[v] = k |
|
149 | dmap[v] = k | |
150 |
|
150 | |||
151 | def decode(s): |
|
151 | def decode(s): | |
152 | i = 0 |
|
152 | i = 0 | |
153 | while i < len(s): |
|
153 | while i < len(s): | |
154 | for l in pycompat.xrange(1, 4): |
|
154 | for l in pycompat.xrange(1, 4): | |
155 | try: |
|
155 | try: | |
156 | yield dmap[s[i : i + l]] |
|
156 | yield dmap[s[i : i + l]] | |
157 | i += l |
|
157 | i += l | |
158 | break |
|
158 | break | |
159 | except KeyError: |
|
159 | except KeyError: | |
160 | pass |
|
160 | pass | |
161 | else: |
|
161 | else: | |
162 | raise KeyError |
|
162 | raise KeyError | |
163 |
|
163 | |||
164 | return ( |
|
164 | return ( | |
165 | lambda s: b''.join( |
|
165 | lambda s: b''.join( | |
166 | [cmap[s[c : c + 1]] for c in pycompat.xrange(len(s))] |
|
166 | [cmap[s[c : c + 1]] for c in pycompat.xrange(len(s))] | |
167 | ), |
|
167 | ), | |
168 | lambda s: b''.join(list(decode(s))), |
|
168 | lambda s: b''.join(list(decode(s))), | |
169 | ) |
|
169 | ) | |
170 |
|
170 | |||
171 |
|
171 | |||
172 | _encodefname, _decodefname = _buildencodefun() |
|
172 | _encodefname, _decodefname = _buildencodefun() | |
173 |
|
173 | |||
174 |
|
174 | |||
175 | def encodefilename(s): |
|
175 | def encodefilename(s): | |
176 | """ |
|
176 | """ | |
177 | >>> encodefilename(b'foo.i/bar.d/bla.hg/hi:world?/HELLO') |
|
177 | >>> encodefilename(b'foo.i/bar.d/bla.hg/hi:world?/HELLO') | |
178 | 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o' |
|
178 | 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o' | |
179 | """ |
|
179 | """ | |
180 | return _encodefname(encodedir(s)) |
|
180 | return _encodefname(encodedir(s)) | |
181 |
|
181 | |||
182 |
|
182 | |||
183 | def decodefilename(s): |
|
183 | def decodefilename(s): | |
184 | """ |
|
184 | """ | |
185 | >>> decodefilename(b'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o') |
|
185 | >>> decodefilename(b'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o') | |
186 | 'foo.i/bar.d/bla.hg/hi:world?/HELLO' |
|
186 | 'foo.i/bar.d/bla.hg/hi:world?/HELLO' | |
187 | """ |
|
187 | """ | |
188 | return decodedir(_decodefname(s)) |
|
188 | return decodedir(_decodefname(s)) | |
189 |
|
189 | |||
190 |
|
190 | |||
191 | def _buildlowerencodefun(): |
|
191 | def _buildlowerencodefun(): | |
192 | """ |
|
192 | """ | |
193 | >>> f = _buildlowerencodefun() |
|
193 | >>> f = _buildlowerencodefun() | |
194 | >>> f(b'nothing/special.txt') |
|
194 | >>> f(b'nothing/special.txt') | |
195 | 'nothing/special.txt' |
|
195 | 'nothing/special.txt' | |
196 | >>> f(b'HELLO') |
|
196 | >>> f(b'HELLO') | |
197 | 'hello' |
|
197 | 'hello' | |
198 | >>> f(b'hello:world?') |
|
198 | >>> f(b'hello:world?') | |
199 | 'hello~3aworld~3f' |
|
199 | 'hello~3aworld~3f' | |
200 | >>> f(b'the\\x07quick\\xADshot') |
|
200 | >>> f(b'the\\x07quick\\xADshot') | |
201 | 'the~07quick~adshot' |
|
201 | 'the~07quick~adshot' | |
202 | """ |
|
202 | """ | |
203 | xchr = pycompat.bytechr |
|
203 | xchr = pycompat.bytechr | |
204 | cmap = {xchr(x): xchr(x) for x in pycompat.xrange(127)} |
|
204 | cmap = {xchr(x): xchr(x) for x in pycompat.xrange(127)} | |
205 | for x in _reserved(): |
|
205 | for x in _reserved(): | |
206 | cmap[xchr(x)] = b"~%02x" % x |
|
206 | cmap[xchr(x)] = b"~%02x" % x | |
207 | for x in range(ord(b"A"), ord(b"Z") + 1): |
|
207 | for x in range(ord(b"A"), ord(b"Z") + 1): | |
208 | cmap[xchr(x)] = xchr(x).lower() |
|
208 | cmap[xchr(x)] = xchr(x).lower() | |
209 |
|
209 | |||
210 | def lowerencode(s): |
|
210 | def lowerencode(s): | |
211 | return b"".join([cmap[c] for c in pycompat.iterbytestr(s)]) |
|
211 | return b"".join([cmap[c] for c in pycompat.iterbytestr(s)]) | |
212 |
|
212 | |||
213 | return lowerencode |
|
213 | return lowerencode | |
214 |
|
214 | |||
215 |
|
215 | |||
216 | lowerencode = getattr(parsers, 'lowerencode', None) or _buildlowerencodefun() |
|
216 | lowerencode = getattr(parsers, 'lowerencode', None) or _buildlowerencodefun() | |
217 |
|
217 | |||
218 | # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9 |
|
218 | # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9 | |
219 | _winres3 = (b'aux', b'con', b'prn', b'nul') # length 3 |
|
219 | _winres3 = (b'aux', b'con', b'prn', b'nul') # length 3 | |
220 | _winres4 = (b'com', b'lpt') # length 4 (with trailing 1..9) |
|
220 | _winres4 = (b'com', b'lpt') # length 4 (with trailing 1..9) | |
221 |
|
221 | |||
222 |
|
222 | |||
223 | def _auxencode(path, dotencode): |
|
223 | def _auxencode(path, dotencode): | |
224 | """ |
|
224 | """ | |
225 | Encodes filenames containing names reserved by Windows or which end in |
|
225 | Encodes filenames containing names reserved by Windows or which end in | |
226 | period or space. Does not touch other single reserved characters c. |
|
226 | period or space. Does not touch other single reserved characters c. | |
227 | Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here. |
|
227 | Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here. | |
228 | Additionally encodes space or period at the beginning, if dotencode is |
|
228 | Additionally encodes space or period at the beginning, if dotencode is | |
229 | True. Parameter path is assumed to be all lowercase. |
|
229 | True. Parameter path is assumed to be all lowercase. | |
230 | A segment only needs encoding if a reserved name appears as a |
|
230 | A segment only needs encoding if a reserved name appears as a | |
231 | basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux" |
|
231 | basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux" | |
232 | doesn't need encoding. |
|
232 | doesn't need encoding. | |
233 |
|
233 | |||
234 | >>> s = b'.foo/aux.txt/txt.aux/con/prn/nul/foo.' |
|
234 | >>> s = b'.foo/aux.txt/txt.aux/con/prn/nul/foo.' | |
235 | >>> _auxencode(s.split(b'/'), True) |
|
235 | >>> _auxencode(s.split(b'/'), True) | |
236 | ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e'] |
|
236 | ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e'] | |
237 | >>> s = b'.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.' |
|
237 | >>> s = b'.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.' | |
238 | >>> _auxencode(s.split(b'/'), False) |
|
238 | >>> _auxencode(s.split(b'/'), False) | |
239 | ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e'] |
|
239 | ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e'] | |
240 | >>> _auxencode([b'foo. '], True) |
|
240 | >>> _auxencode([b'foo. '], True) | |
241 | ['foo.~20'] |
|
241 | ['foo.~20'] | |
242 | >>> _auxencode([b' .foo'], True) |
|
242 | >>> _auxencode([b' .foo'], True) | |
243 | ['~20.foo'] |
|
243 | ['~20.foo'] | |
244 | """ |
|
244 | """ | |
245 | for i, n in enumerate(path): |
|
245 | for i, n in enumerate(path): | |
246 | if not n: |
|
246 | if not n: | |
247 | continue |
|
247 | continue | |
248 | if dotencode and n[0] in b'. ': |
|
248 | if dotencode and n[0] in b'. ': | |
249 | n = b"~%02x" % ord(n[0:1]) + n[1:] |
|
249 | n = b"~%02x" % ord(n[0:1]) + n[1:] | |
250 | path[i] = n |
|
250 | path[i] = n | |
251 | else: |
|
251 | else: | |
252 | l = n.find(b'.') |
|
252 | l = n.find(b'.') | |
253 | if l == -1: |
|
253 | if l == -1: | |
254 | l = len(n) |
|
254 | l = len(n) | |
255 | if (l == 3 and n[:3] in _winres3) or ( |
|
255 | if (l == 3 and n[:3] in _winres3) or ( | |
256 | l == 4 |
|
256 | l == 4 | |
257 | and n[3:4] <= b'9' |
|
257 | and n[3:4] <= b'9' | |
258 | and n[3:4] >= b'1' |
|
258 | and n[3:4] >= b'1' | |
259 | and n[:3] in _winres4 |
|
259 | and n[:3] in _winres4 | |
260 | ): |
|
260 | ): | |
261 | # encode third letter ('aux' -> 'au~78') |
|
261 | # encode third letter ('aux' -> 'au~78') | |
262 | ec = b"~%02x" % ord(n[2:3]) |
|
262 | ec = b"~%02x" % ord(n[2:3]) | |
263 | n = n[0:2] + ec + n[3:] |
|
263 | n = n[0:2] + ec + n[3:] | |
264 | path[i] = n |
|
264 | path[i] = n | |
265 | if n[-1] in b'. ': |
|
265 | if n[-1] in b'. ': | |
266 | # encode last period or space ('foo...' -> 'foo..~2e') |
|
266 | # encode last period or space ('foo...' -> 'foo..~2e') | |
267 | path[i] = n[:-1] + b"~%02x" % ord(n[-1:]) |
|
267 | path[i] = n[:-1] + b"~%02x" % ord(n[-1:]) | |
268 | return path |
|
268 | return path | |
269 |
|
269 | |||
270 |
|
270 | |||
271 | _maxstorepathlen = 120 |
|
271 | _maxstorepathlen = 120 | |
272 | _dirprefixlen = 8 |
|
272 | _dirprefixlen = 8 | |
273 | _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4 |
|
273 | _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4 | |
274 |
|
274 | |||
275 |
|
275 | |||
276 | def _hashencode(path, dotencode): |
|
276 | def _hashencode(path, dotencode): | |
277 | digest = hex(hashutil.sha1(path).digest()) |
|
277 | digest = hex(hashutil.sha1(path).digest()) | |
278 | le = lowerencode(path[5:]).split(b'/') # skips prefix 'data/' or 'meta/' |
|
278 | le = lowerencode(path[5:]).split(b'/') # skips prefix 'data/' or 'meta/' | |
279 | parts = _auxencode(le, dotencode) |
|
279 | parts = _auxencode(le, dotencode) | |
280 | basename = parts[-1] |
|
280 | basename = parts[-1] | |
281 | _root, ext = os.path.splitext(basename) |
|
281 | _root, ext = os.path.splitext(basename) | |
282 | sdirs = [] |
|
282 | sdirs = [] | |
283 | sdirslen = 0 |
|
283 | sdirslen = 0 | |
284 | for p in parts[:-1]: |
|
284 | for p in parts[:-1]: | |
285 | d = p[:_dirprefixlen] |
|
285 | d = p[:_dirprefixlen] | |
286 | if d[-1] in b'. ': |
|
286 | if d[-1] in b'. ': | |
287 | # Windows can't access dirs ending in period or space |
|
287 | # Windows can't access dirs ending in period or space | |
288 | d = d[:-1] + b'_' |
|
288 | d = d[:-1] + b'_' | |
289 | if sdirslen == 0: |
|
289 | if sdirslen == 0: | |
290 | t = len(d) |
|
290 | t = len(d) | |
291 | else: |
|
291 | else: | |
292 | t = sdirslen + 1 + len(d) |
|
292 | t = sdirslen + 1 + len(d) | |
293 | if t > _maxshortdirslen: |
|
293 | if t > _maxshortdirslen: | |
294 | break |
|
294 | break | |
295 | sdirs.append(d) |
|
295 | sdirs.append(d) | |
296 | sdirslen = t |
|
296 | sdirslen = t | |
297 | dirs = b'/'.join(sdirs) |
|
297 | dirs = b'/'.join(sdirs) | |
298 | if len(dirs) > 0: |
|
298 | if len(dirs) > 0: | |
299 | dirs += b'/' |
|
299 | dirs += b'/' | |
300 | res = b'dh/' + dirs + digest + ext |
|
300 | res = b'dh/' + dirs + digest + ext | |
301 | spaceleft = _maxstorepathlen - len(res) |
|
301 | spaceleft = _maxstorepathlen - len(res) | |
302 | if spaceleft > 0: |
|
302 | if spaceleft > 0: | |
303 | filler = basename[:spaceleft] |
|
303 | filler = basename[:spaceleft] | |
304 | res = b'dh/' + dirs + filler + digest + ext |
|
304 | res = b'dh/' + dirs + filler + digest + ext | |
305 | return res |
|
305 | return res | |
306 |
|
306 | |||
307 |
|
307 | |||
308 | def _hybridencode(path, dotencode): |
|
308 | def _hybridencode(path, dotencode): | |
309 | """encodes path with a length limit |
|
309 | """encodes path with a length limit | |
310 |
|
310 | |||
311 | Encodes all paths that begin with 'data/', according to the following. |
|
311 | Encodes all paths that begin with 'data/', according to the following. | |
312 |
|
312 | |||
313 | Default encoding (reversible): |
|
313 | Default encoding (reversible): | |
314 |
|
314 | |||
315 | Encodes all uppercase letters 'X' as '_x'. All reserved or illegal |
|
315 | Encodes all uppercase letters 'X' as '_x'. All reserved or illegal | |
316 | characters are encoded as '~xx', where xx is the two digit hex code |
|
316 | characters are encoded as '~xx', where xx is the two digit hex code | |
317 | of the character (see encodefilename). |
|
317 | of the character (see encodefilename). | |
318 | Relevant path components consisting of Windows reserved filenames are |
|
318 | Relevant path components consisting of Windows reserved filenames are | |
319 | masked by encoding the third character ('aux' -> 'au~78', see _auxencode). |
|
319 | masked by encoding the third character ('aux' -> 'au~78', see _auxencode). | |
320 |
|
320 | |||
321 | Hashed encoding (not reversible): |
|
321 | Hashed encoding (not reversible): | |
322 |
|
322 | |||
323 | If the default-encoded path is longer than _maxstorepathlen, a |
|
323 | If the default-encoded path is longer than _maxstorepathlen, a | |
324 | non-reversible hybrid hashing of the path is done instead. |
|
324 | non-reversible hybrid hashing of the path is done instead. | |
325 | This encoding uses up to _dirprefixlen characters of all directory |
|
325 | This encoding uses up to _dirprefixlen characters of all directory | |
326 | levels of the lowerencoded path, but not more levels than can fit into |
|
326 | levels of the lowerencoded path, but not more levels than can fit into | |
327 | _maxshortdirslen. |
|
327 | _maxshortdirslen. | |
328 | Then follows the filler followed by the sha digest of the full path. |
|
328 | Then follows the filler followed by the sha digest of the full path. | |
329 | The filler is the beginning of the basename of the lowerencoded path |
|
329 | The filler is the beginning of the basename of the lowerencoded path | |
330 | (the basename is everything after the last path separator). The filler |
|
330 | (the basename is everything after the last path separator). The filler | |
331 | is as long as possible, filling in characters from the basename until |
|
331 | is as long as possible, filling in characters from the basename until | |
332 | the encoded path has _maxstorepathlen characters (or all chars of the |
|
332 | the encoded path has _maxstorepathlen characters (or all chars of the | |
333 | basename have been taken). |
|
333 | basename have been taken). | |
334 | The extension (e.g. '.i' or '.d') is preserved. |
|
334 | The extension (e.g. '.i' or '.d') is preserved. | |
335 |
|
335 | |||
336 | The string 'data/' at the beginning is replaced with 'dh/', if the hashed |
|
336 | The string 'data/' at the beginning is replaced with 'dh/', if the hashed | |
337 | encoding was used. |
|
337 | encoding was used. | |
338 | """ |
|
338 | """ | |
339 | path = encodedir(path) |
|
339 | path = encodedir(path) | |
340 | ef = _encodefname(path).split(b'/') |
|
340 | ef = _encodefname(path).split(b'/') | |
341 | res = b'/'.join(_auxencode(ef, dotencode)) |
|
341 | res = b'/'.join(_auxencode(ef, dotencode)) | |
342 | if len(res) > _maxstorepathlen: |
|
342 | if len(res) > _maxstorepathlen: | |
343 | res = _hashencode(path, dotencode) |
|
343 | res = _hashencode(path, dotencode) | |
344 | return res |
|
344 | return res | |
345 |
|
345 | |||
346 |
|
346 | |||
347 | def _pathencode(path): |
|
347 | def _pathencode(path): | |
348 | de = encodedir(path) |
|
348 | de = encodedir(path) | |
349 | if len(path) > _maxstorepathlen: |
|
349 | if len(path) > _maxstorepathlen: | |
350 | return _hashencode(de, True) |
|
350 | return _hashencode(de, True) | |
351 | ef = _encodefname(de).split(b'/') |
|
351 | ef = _encodefname(de).split(b'/') | |
352 | res = b'/'.join(_auxencode(ef, True)) |
|
352 | res = b'/'.join(_auxencode(ef, True)) | |
353 | if len(res) > _maxstorepathlen: |
|
353 | if len(res) > _maxstorepathlen: | |
354 | return _hashencode(de, True) |
|
354 | return _hashencode(de, True) | |
355 | return res |
|
355 | return res | |
356 |
|
356 | |||
357 |
|
357 | |||
358 | _pathencode = getattr(parsers, 'pathencode', _pathencode) |
|
358 | _pathencode = getattr(parsers, 'pathencode', _pathencode) | |
359 |
|
359 | |||
360 |
|
360 | |||
361 | def _plainhybridencode(f): |
|
361 | def _plainhybridencode(f): | |
362 | return _hybridencode(f, False) |
|
362 | return _hybridencode(f, False) | |
363 |
|
363 | |||
364 |
|
364 | |||
365 | def _calcmode(vfs): |
|
365 | def _calcmode(vfs): | |
366 | try: |
|
366 | try: | |
367 | # files in .hg/ will be created using this mode |
|
367 | # files in .hg/ will be created using this mode | |
368 | mode = vfs.stat().st_mode |
|
368 | mode = vfs.stat().st_mode | |
369 | # avoid some useless chmods |
|
369 | # avoid some useless chmods | |
370 | if (0o777 & ~util.umask) == (0o777 & mode): |
|
370 | if (0o777 & ~util.umask) == (0o777 & mode): | |
371 | mode = None |
|
371 | mode = None | |
372 | except OSError: |
|
372 | except OSError: | |
373 | mode = None |
|
373 | mode = None | |
374 | return mode |
|
374 | return mode | |
375 |
|
375 | |||
376 |
|
376 | |||
377 | _data = [ |
|
377 | _data = [ | |
378 | b'bookmarks', |
|
378 | b'bookmarks', | |
379 | b'narrowspec', |
|
379 | b'narrowspec', | |
380 | b'data', |
|
380 | b'data', | |
381 | b'meta', |
|
381 | b'meta', | |
382 | b'00manifest.d', |
|
382 | b'00manifest.d', | |
383 | b'00manifest.i', |
|
383 | b'00manifest.i', | |
384 | b'00changelog.d', |
|
384 | b'00changelog.d', | |
385 | b'00changelog.i', |
|
385 | b'00changelog.i', | |
386 | b'phaseroots', |
|
386 | b'phaseroots', | |
387 | b'obsstore', |
|
387 | b'obsstore', | |
388 | b'requires', |
|
388 | b'requires', | |
389 | ] |
|
389 | ] | |
390 |
|
390 | |||
391 | REVLOG_FILES_MAIN_EXT = (b'.i', b'i.tmpcensored') |
|
391 | REVLOG_FILES_MAIN_EXT = (b'.i', b'i.tmpcensored') | |
392 | REVLOG_FILES_OTHER_EXT = ( |
|
392 | REVLOG_FILES_OTHER_EXT = ( | |
393 | b'.idx', |
|
393 | b'.idx', | |
394 | b'.d', |
|
394 | b'.d', | |
395 | b'.dat', |
|
395 | b'.dat', | |
396 | b'.n', |
|
396 | b'.n', | |
397 | b'.nd', |
|
397 | b'.nd', | |
398 | b'.sda', |
|
398 | b'.sda', | |
399 | b'd.tmpcensored', |
|
399 | b'd.tmpcensored', | |
400 | ) |
|
400 | ) | |
401 | # files that are "volatile" and might change between listing and streaming |
|
401 | # files that are "volatile" and might change between listing and streaming | |
402 | # |
|
402 | # | |
403 | # note: the ".nd" file are nodemap data and won't "change" but they might be |
|
403 | # note: the ".nd" file are nodemap data and won't "change" but they might be | |
404 | # deleted. |
|
404 | # deleted. | |
405 | REVLOG_FILES_VOLATILE_EXT = (b'.n', b'.nd') |
|
405 | REVLOG_FILES_VOLATILE_EXT = (b'.n', b'.nd') | |
406 |
|
406 | |||
407 | # some exception to the above matching |
|
407 | # some exception to the above matching | |
|
408 | # | |||
|
409 | # XXX This is currently not in use because of issue6542 | |||
408 | EXCLUDED = re.compile(b'.*undo\.[^/]+\.(nd?|i)$') |
|
410 | EXCLUDED = re.compile(b'.*undo\.[^/]+\.(nd?|i)$') | |
409 |
|
411 | |||
410 |
|
412 | |||
411 | def is_revlog(f, kind, st): |
|
413 | def is_revlog(f, kind, st): | |
412 | if kind != stat.S_IFREG: |
|
414 | if kind != stat.S_IFREG: | |
413 | return None |
|
415 | return None | |
414 | return revlog_type(f) |
|
416 | return revlog_type(f) | |
415 |
|
417 | |||
416 |
|
418 | |||
417 | def revlog_type(f): |
|
419 | def revlog_type(f): | |
418 | if f.endswith(REVLOG_FILES_MAIN_EXT) and EXCLUDED.match(f) is None: |
|
420 | # XXX we need to filter `undo.` created by the transaction here, however | |
|
421 | # being naive about it also filter revlog for `undo.*` files, leading to | |||
|
422 | # issue6542. So we no longer use EXCLUDED. | |||
|
423 | if f.endswith(REVLOG_FILES_MAIN_EXT): | |||
419 | return FILEFLAGS_REVLOG_MAIN |
|
424 | return FILEFLAGS_REVLOG_MAIN | |
420 |
elif f.endswith(REVLOG_FILES_OTHER_EXT) |
|
425 | elif f.endswith(REVLOG_FILES_OTHER_EXT): | |
421 | t = FILETYPE_FILELOG_OTHER |
|
426 | t = FILETYPE_FILELOG_OTHER | |
422 | if f.endswith(REVLOG_FILES_VOLATILE_EXT): |
|
427 | if f.endswith(REVLOG_FILES_VOLATILE_EXT): | |
423 | t |= FILEFLAGS_VOLATILE |
|
428 | t |= FILEFLAGS_VOLATILE | |
424 | return t |
|
429 | return t | |
425 | return None |
|
430 | return None | |
426 |
|
431 | |||
427 |
|
432 | |||
428 | # the file is part of changelog data |
|
433 | # the file is part of changelog data | |
429 | FILEFLAGS_CHANGELOG = 1 << 13 |
|
434 | FILEFLAGS_CHANGELOG = 1 << 13 | |
430 | # the file is part of manifest data |
|
435 | # the file is part of manifest data | |
431 | FILEFLAGS_MANIFESTLOG = 1 << 12 |
|
436 | FILEFLAGS_MANIFESTLOG = 1 << 12 | |
432 | # the file is part of filelog data |
|
437 | # the file is part of filelog data | |
433 | FILEFLAGS_FILELOG = 1 << 11 |
|
438 | FILEFLAGS_FILELOG = 1 << 11 | |
434 | # file that are not directly part of a revlog |
|
439 | # file that are not directly part of a revlog | |
435 | FILEFLAGS_OTHER = 1 << 10 |
|
440 | FILEFLAGS_OTHER = 1 << 10 | |
436 |
|
441 | |||
437 | # the main entry point for a revlog |
|
442 | # the main entry point for a revlog | |
438 | FILEFLAGS_REVLOG_MAIN = 1 << 1 |
|
443 | FILEFLAGS_REVLOG_MAIN = 1 << 1 | |
439 | # a secondary file for a revlog |
|
444 | # a secondary file for a revlog | |
440 | FILEFLAGS_REVLOG_OTHER = 1 << 0 |
|
445 | FILEFLAGS_REVLOG_OTHER = 1 << 0 | |
441 |
|
446 | |||
442 | # files that are "volatile" and might change between listing and streaming |
|
447 | # files that are "volatile" and might change between listing and streaming | |
443 | FILEFLAGS_VOLATILE = 1 << 20 |
|
448 | FILEFLAGS_VOLATILE = 1 << 20 | |
444 |
|
449 | |||
445 | FILETYPE_CHANGELOG_MAIN = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_MAIN |
|
450 | FILETYPE_CHANGELOG_MAIN = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_MAIN | |
446 | FILETYPE_CHANGELOG_OTHER = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_OTHER |
|
451 | FILETYPE_CHANGELOG_OTHER = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_OTHER | |
447 | FILETYPE_MANIFESTLOG_MAIN = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_MAIN |
|
452 | FILETYPE_MANIFESTLOG_MAIN = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_MAIN | |
448 | FILETYPE_MANIFESTLOG_OTHER = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_OTHER |
|
453 | FILETYPE_MANIFESTLOG_OTHER = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_OTHER | |
449 | FILETYPE_FILELOG_MAIN = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_MAIN |
|
454 | FILETYPE_FILELOG_MAIN = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_MAIN | |
450 | FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER |
|
455 | FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER | |
451 | FILETYPE_OTHER = FILEFLAGS_OTHER |
|
456 | FILETYPE_OTHER = FILEFLAGS_OTHER | |
452 |
|
457 | |||
453 |
|
458 | |||
454 | class basicstore(object): |
|
459 | class basicstore(object): | |
455 | '''base class for local repository stores''' |
|
460 | '''base class for local repository stores''' | |
456 |
|
461 | |||
457 | def __init__(self, path, vfstype): |
|
462 | def __init__(self, path, vfstype): | |
458 | vfs = vfstype(path) |
|
463 | vfs = vfstype(path) | |
459 | self.path = vfs.base |
|
464 | self.path = vfs.base | |
460 | self.createmode = _calcmode(vfs) |
|
465 | self.createmode = _calcmode(vfs) | |
461 | vfs.createmode = self.createmode |
|
466 | vfs.createmode = self.createmode | |
462 | self.rawvfs = vfs |
|
467 | self.rawvfs = vfs | |
463 | self.vfs = vfsmod.filtervfs(vfs, encodedir) |
|
468 | self.vfs = vfsmod.filtervfs(vfs, encodedir) | |
464 | self.opener = self.vfs |
|
469 | self.opener = self.vfs | |
465 |
|
470 | |||
466 | def join(self, f): |
|
471 | def join(self, f): | |
467 | return self.path + b'/' + encodedir(f) |
|
472 | return self.path + b'/' + encodedir(f) | |
468 |
|
473 | |||
469 | def _walk(self, relpath, recurse): |
|
474 | def _walk(self, relpath, recurse): | |
470 | '''yields (unencoded, encoded, size)''' |
|
475 | '''yields (unencoded, encoded, size)''' | |
471 | path = self.path |
|
476 | path = self.path | |
472 | if relpath: |
|
477 | if relpath: | |
473 | path += b'/' + relpath |
|
478 | path += b'/' + relpath | |
474 | striplen = len(self.path) + 1 |
|
479 | striplen = len(self.path) + 1 | |
475 | l = [] |
|
480 | l = [] | |
476 | if self.rawvfs.isdir(path): |
|
481 | if self.rawvfs.isdir(path): | |
477 | visit = [path] |
|
482 | visit = [path] | |
478 | readdir = self.rawvfs.readdir |
|
483 | readdir = self.rawvfs.readdir | |
479 | while visit: |
|
484 | while visit: | |
480 | p = visit.pop() |
|
485 | p = visit.pop() | |
481 | for f, kind, st in readdir(p, stat=True): |
|
486 | for f, kind, st in readdir(p, stat=True): | |
482 | fp = p + b'/' + f |
|
487 | fp = p + b'/' + f | |
483 | rl_type = is_revlog(f, kind, st) |
|
488 | rl_type = is_revlog(f, kind, st) | |
484 | if rl_type is not None: |
|
489 | if rl_type is not None: | |
485 | n = util.pconvert(fp[striplen:]) |
|
490 | n = util.pconvert(fp[striplen:]) | |
486 | l.append((rl_type, decodedir(n), n, st.st_size)) |
|
491 | l.append((rl_type, decodedir(n), n, st.st_size)) | |
487 | elif kind == stat.S_IFDIR and recurse: |
|
492 | elif kind == stat.S_IFDIR and recurse: | |
488 | visit.append(fp) |
|
493 | visit.append(fp) | |
489 | l.sort() |
|
494 | l.sort() | |
490 | return l |
|
495 | return l | |
491 |
|
496 | |||
492 | def changelog(self, trypending, concurrencychecker=None): |
|
497 | def changelog(self, trypending, concurrencychecker=None): | |
493 | return changelog.changelog( |
|
498 | return changelog.changelog( | |
494 | self.vfs, |
|
499 | self.vfs, | |
495 | trypending=trypending, |
|
500 | trypending=trypending, | |
496 | concurrencychecker=concurrencychecker, |
|
501 | concurrencychecker=concurrencychecker, | |
497 | ) |
|
502 | ) | |
498 |
|
503 | |||
499 | def manifestlog(self, repo, storenarrowmatch): |
|
504 | def manifestlog(self, repo, storenarrowmatch): | |
500 | rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) |
|
505 | rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) | |
501 | return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) |
|
506 | return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) | |
502 |
|
507 | |||
503 | def datafiles(self, matcher=None): |
|
508 | def datafiles(self, matcher=None): | |
504 | files = self._walk(b'data', True) + self._walk(b'meta', True) |
|
509 | files = self._walk(b'data', True) + self._walk(b'meta', True) | |
505 | for (t, u, e, s) in files: |
|
510 | for (t, u, e, s) in files: | |
506 | yield (FILEFLAGS_FILELOG | t, u, e, s) |
|
511 | yield (FILEFLAGS_FILELOG | t, u, e, s) | |
507 |
|
512 | |||
508 | def topfiles(self): |
|
513 | def topfiles(self): | |
509 | # yield manifest before changelog |
|
514 | # yield manifest before changelog | |
510 | files = reversed(self._walk(b'', False)) |
|
515 | files = reversed(self._walk(b'', False)) | |
511 | for (t, u, e, s) in files: |
|
516 | for (t, u, e, s) in files: | |
512 | if u.startswith(b'00changelog'): |
|
517 | if u.startswith(b'00changelog'): | |
513 | yield (FILEFLAGS_CHANGELOG | t, u, e, s) |
|
518 | yield (FILEFLAGS_CHANGELOG | t, u, e, s) | |
514 | elif u.startswith(b'00manifest'): |
|
519 | elif u.startswith(b'00manifest'): | |
515 | yield (FILEFLAGS_MANIFESTLOG | t, u, e, s) |
|
520 | yield (FILEFLAGS_MANIFESTLOG | t, u, e, s) | |
516 | else: |
|
521 | else: | |
517 | yield (FILETYPE_OTHER | t, u, e, s) |
|
522 | yield (FILETYPE_OTHER | t, u, e, s) | |
518 |
|
523 | |||
519 | def walk(self, matcher=None): |
|
524 | def walk(self, matcher=None): | |
520 | """return file related to data storage (ie: revlogs) |
|
525 | """return file related to data storage (ie: revlogs) | |
521 |
|
526 | |||
522 | yields (file_type, unencoded, encoded, size) |
|
527 | yields (file_type, unencoded, encoded, size) | |
523 |
|
528 | |||
524 | if a matcher is passed, storage files of only those tracked paths |
|
529 | if a matcher is passed, storage files of only those tracked paths | |
525 | are passed with matches the matcher |
|
530 | are passed with matches the matcher | |
526 | """ |
|
531 | """ | |
527 | # yield data files first |
|
532 | # yield data files first | |
528 | for x in self.datafiles(matcher): |
|
533 | for x in self.datafiles(matcher): | |
529 | yield x |
|
534 | yield x | |
530 | for x in self.topfiles(): |
|
535 | for x in self.topfiles(): | |
531 | yield x |
|
536 | yield x | |
532 |
|
537 | |||
533 | def copylist(self): |
|
538 | def copylist(self): | |
534 | return _data |
|
539 | return _data | |
535 |
|
540 | |||
536 | def write(self, tr): |
|
541 | def write(self, tr): | |
537 | pass |
|
542 | pass | |
538 |
|
543 | |||
539 | def invalidatecaches(self): |
|
544 | def invalidatecaches(self): | |
540 | pass |
|
545 | pass | |
541 |
|
546 | |||
542 | def markremoved(self, fn): |
|
547 | def markremoved(self, fn): | |
543 | pass |
|
548 | pass | |
544 |
|
549 | |||
545 | def __contains__(self, path): |
|
550 | def __contains__(self, path): | |
546 | '''Checks if the store contains path''' |
|
551 | '''Checks if the store contains path''' | |
547 | path = b"/".join((b"data", path)) |
|
552 | path = b"/".join((b"data", path)) | |
548 | # file? |
|
553 | # file? | |
549 | if self.vfs.exists(path + b".i"): |
|
554 | if self.vfs.exists(path + b".i"): | |
550 | return True |
|
555 | return True | |
551 | # dir? |
|
556 | # dir? | |
552 | if not path.endswith(b"/"): |
|
557 | if not path.endswith(b"/"): | |
553 | path = path + b"/" |
|
558 | path = path + b"/" | |
554 | return self.vfs.exists(path) |
|
559 | return self.vfs.exists(path) | |
555 |
|
560 | |||
556 |
|
561 | |||
557 | class encodedstore(basicstore): |
|
562 | class encodedstore(basicstore): | |
558 | def __init__(self, path, vfstype): |
|
563 | def __init__(self, path, vfstype): | |
559 | vfs = vfstype(path + b'/store') |
|
564 | vfs = vfstype(path + b'/store') | |
560 | self.path = vfs.base |
|
565 | self.path = vfs.base | |
561 | self.createmode = _calcmode(vfs) |
|
566 | self.createmode = _calcmode(vfs) | |
562 | vfs.createmode = self.createmode |
|
567 | vfs.createmode = self.createmode | |
563 | self.rawvfs = vfs |
|
568 | self.rawvfs = vfs | |
564 | self.vfs = vfsmod.filtervfs(vfs, encodefilename) |
|
569 | self.vfs = vfsmod.filtervfs(vfs, encodefilename) | |
565 | self.opener = self.vfs |
|
570 | self.opener = self.vfs | |
566 |
|
571 | |||
567 | def datafiles(self, matcher=None): |
|
572 | def datafiles(self, matcher=None): | |
568 | for t, a, b, size in super(encodedstore, self).datafiles(): |
|
573 | for t, a, b, size in super(encodedstore, self).datafiles(): | |
569 | try: |
|
574 | try: | |
570 | a = decodefilename(a) |
|
575 | a = decodefilename(a) | |
571 | except KeyError: |
|
576 | except KeyError: | |
572 | a = None |
|
577 | a = None | |
573 | if a is not None and not _matchtrackedpath(a, matcher): |
|
578 | if a is not None and not _matchtrackedpath(a, matcher): | |
574 | continue |
|
579 | continue | |
575 | yield t, a, b, size |
|
580 | yield t, a, b, size | |
576 |
|
581 | |||
577 | def join(self, f): |
|
582 | def join(self, f): | |
578 | return self.path + b'/' + encodefilename(f) |
|
583 | return self.path + b'/' + encodefilename(f) | |
579 |
|
584 | |||
580 | def copylist(self): |
|
585 | def copylist(self): | |
581 | return [b'requires', b'00changelog.i'] + [b'store/' + f for f in _data] |
|
586 | return [b'requires', b'00changelog.i'] + [b'store/' + f for f in _data] | |
582 |
|
587 | |||
583 |
|
588 | |||
584 | class fncache(object): |
|
589 | class fncache(object): | |
585 | # the filename used to be partially encoded |
|
590 | # the filename used to be partially encoded | |
586 | # hence the encodedir/decodedir dance |
|
591 | # hence the encodedir/decodedir dance | |
587 | def __init__(self, vfs): |
|
592 | def __init__(self, vfs): | |
588 | self.vfs = vfs |
|
593 | self.vfs = vfs | |
589 | self.entries = None |
|
594 | self.entries = None | |
590 | self._dirty = False |
|
595 | self._dirty = False | |
591 | # set of new additions to fncache |
|
596 | # set of new additions to fncache | |
592 | self.addls = set() |
|
597 | self.addls = set() | |
593 |
|
598 | |||
594 | def ensureloaded(self, warn=None): |
|
599 | def ensureloaded(self, warn=None): | |
595 | """read the fncache file if not already read. |
|
600 | """read the fncache file if not already read. | |
596 |
|
601 | |||
597 | If the file on disk is corrupted, raise. If warn is provided, |
|
602 | If the file on disk is corrupted, raise. If warn is provided, | |
598 | warn and keep going instead.""" |
|
603 | warn and keep going instead.""" | |
599 | if self.entries is None: |
|
604 | if self.entries is None: | |
600 | self._load(warn) |
|
605 | self._load(warn) | |
601 |
|
606 | |||
602 | def _load(self, warn=None): |
|
607 | def _load(self, warn=None): | |
603 | '''fill the entries from the fncache file''' |
|
608 | '''fill the entries from the fncache file''' | |
604 | self._dirty = False |
|
609 | self._dirty = False | |
605 | try: |
|
610 | try: | |
606 | fp = self.vfs(b'fncache', mode=b'rb') |
|
611 | fp = self.vfs(b'fncache', mode=b'rb') | |
607 | except IOError: |
|
612 | except IOError: | |
608 | # skip nonexistent file |
|
613 | # skip nonexistent file | |
609 | self.entries = set() |
|
614 | self.entries = set() | |
610 | return |
|
615 | return | |
611 |
|
616 | |||
612 | self.entries = set() |
|
617 | self.entries = set() | |
613 | chunk = b'' |
|
618 | chunk = b'' | |
614 | for c in iter(functools.partial(fp.read, fncache_chunksize), b''): |
|
619 | for c in iter(functools.partial(fp.read, fncache_chunksize), b''): | |
615 | chunk += c |
|
620 | chunk += c | |
616 | try: |
|
621 | try: | |
617 | p = chunk.rindex(b'\n') |
|
622 | p = chunk.rindex(b'\n') | |
618 | self.entries.update(decodedir(chunk[: p + 1]).splitlines()) |
|
623 | self.entries.update(decodedir(chunk[: p + 1]).splitlines()) | |
619 | chunk = chunk[p + 1 :] |
|
624 | chunk = chunk[p + 1 :] | |
620 | except ValueError: |
|
625 | except ValueError: | |
621 | # substring '\n' not found, maybe the entry is bigger than the |
|
626 | # substring '\n' not found, maybe the entry is bigger than the | |
622 | # chunksize, so let's keep iterating |
|
627 | # chunksize, so let's keep iterating | |
623 | pass |
|
628 | pass | |
624 |
|
629 | |||
625 | if chunk: |
|
630 | if chunk: | |
626 | msg = _(b"fncache does not ends with a newline") |
|
631 | msg = _(b"fncache does not ends with a newline") | |
627 | if warn: |
|
632 | if warn: | |
628 | warn(msg + b'\n') |
|
633 | warn(msg + b'\n') | |
629 | else: |
|
634 | else: | |
630 | raise error.Abort( |
|
635 | raise error.Abort( | |
631 | msg, |
|
636 | msg, | |
632 | hint=_( |
|
637 | hint=_( | |
633 | b"use 'hg debugrebuildfncache' to " |
|
638 | b"use 'hg debugrebuildfncache' to " | |
634 | b"rebuild the fncache" |
|
639 | b"rebuild the fncache" | |
635 | ), |
|
640 | ), | |
636 | ) |
|
641 | ) | |
637 | self._checkentries(fp, warn) |
|
642 | self._checkentries(fp, warn) | |
638 | fp.close() |
|
643 | fp.close() | |
639 |
|
644 | |||
640 | def _checkentries(self, fp, warn): |
|
645 | def _checkentries(self, fp, warn): | |
641 | """make sure there is no empty string in entries""" |
|
646 | """make sure there is no empty string in entries""" | |
642 | if b'' in self.entries: |
|
647 | if b'' in self.entries: | |
643 | fp.seek(0) |
|
648 | fp.seek(0) | |
644 | for n, line in enumerate(util.iterfile(fp)): |
|
649 | for n, line in enumerate(util.iterfile(fp)): | |
645 | if not line.rstrip(b'\n'): |
|
650 | if not line.rstrip(b'\n'): | |
646 | t = _(b'invalid entry in fncache, line %d') % (n + 1) |
|
651 | t = _(b'invalid entry in fncache, line %d') % (n + 1) | |
647 | if warn: |
|
652 | if warn: | |
648 | warn(t + b'\n') |
|
653 | warn(t + b'\n') | |
649 | else: |
|
654 | else: | |
650 | raise error.Abort(t) |
|
655 | raise error.Abort(t) | |
651 |
|
656 | |||
652 | def write(self, tr): |
|
657 | def write(self, tr): | |
653 | if self._dirty: |
|
658 | if self._dirty: | |
654 | assert self.entries is not None |
|
659 | assert self.entries is not None | |
655 | self.entries = self.entries | self.addls |
|
660 | self.entries = self.entries | self.addls | |
656 | self.addls = set() |
|
661 | self.addls = set() | |
657 | tr.addbackup(b'fncache') |
|
662 | tr.addbackup(b'fncache') | |
658 | fp = self.vfs(b'fncache', mode=b'wb', atomictemp=True) |
|
663 | fp = self.vfs(b'fncache', mode=b'wb', atomictemp=True) | |
659 | if self.entries: |
|
664 | if self.entries: | |
660 | fp.write(encodedir(b'\n'.join(self.entries) + b'\n')) |
|
665 | fp.write(encodedir(b'\n'.join(self.entries) + b'\n')) | |
661 | fp.close() |
|
666 | fp.close() | |
662 | self._dirty = False |
|
667 | self._dirty = False | |
663 | if self.addls: |
|
668 | if self.addls: | |
664 | # if we have just new entries, let's append them to the fncache |
|
669 | # if we have just new entries, let's append them to the fncache | |
665 | tr.addbackup(b'fncache') |
|
670 | tr.addbackup(b'fncache') | |
666 | fp = self.vfs(b'fncache', mode=b'ab', atomictemp=True) |
|
671 | fp = self.vfs(b'fncache', mode=b'ab', atomictemp=True) | |
667 | if self.addls: |
|
672 | if self.addls: | |
668 | fp.write(encodedir(b'\n'.join(self.addls) + b'\n')) |
|
673 | fp.write(encodedir(b'\n'.join(self.addls) + b'\n')) | |
669 | fp.close() |
|
674 | fp.close() | |
670 | self.entries = None |
|
675 | self.entries = None | |
671 | self.addls = set() |
|
676 | self.addls = set() | |
672 |
|
677 | |||
673 | def add(self, fn): |
|
678 | def add(self, fn): | |
674 | if self.entries is None: |
|
679 | if self.entries is None: | |
675 | self._load() |
|
680 | self._load() | |
676 | if fn not in self.entries: |
|
681 | if fn not in self.entries: | |
677 | self.addls.add(fn) |
|
682 | self.addls.add(fn) | |
678 |
|
683 | |||
679 | def remove(self, fn): |
|
684 | def remove(self, fn): | |
680 | if self.entries is None: |
|
685 | if self.entries is None: | |
681 | self._load() |
|
686 | self._load() | |
682 | if fn in self.addls: |
|
687 | if fn in self.addls: | |
683 | self.addls.remove(fn) |
|
688 | self.addls.remove(fn) | |
684 | return |
|
689 | return | |
685 | try: |
|
690 | try: | |
686 | self.entries.remove(fn) |
|
691 | self.entries.remove(fn) | |
687 | self._dirty = True |
|
692 | self._dirty = True | |
688 | except KeyError: |
|
693 | except KeyError: | |
689 | pass |
|
694 | pass | |
690 |
|
695 | |||
691 | def __contains__(self, fn): |
|
696 | def __contains__(self, fn): | |
692 | if fn in self.addls: |
|
697 | if fn in self.addls: | |
693 | return True |
|
698 | return True | |
694 | if self.entries is None: |
|
699 | if self.entries is None: | |
695 | self._load() |
|
700 | self._load() | |
696 | return fn in self.entries |
|
701 | return fn in self.entries | |
697 |
|
702 | |||
698 | def __iter__(self): |
|
703 | def __iter__(self): | |
699 | if self.entries is None: |
|
704 | if self.entries is None: | |
700 | self._load() |
|
705 | self._load() | |
701 | return iter(self.entries | self.addls) |
|
706 | return iter(self.entries | self.addls) | |
702 |
|
707 | |||
703 |
|
708 | |||
704 | class _fncachevfs(vfsmod.proxyvfs): |
|
709 | class _fncachevfs(vfsmod.proxyvfs): | |
705 | def __init__(self, vfs, fnc, encode): |
|
710 | def __init__(self, vfs, fnc, encode): | |
706 | vfsmod.proxyvfs.__init__(self, vfs) |
|
711 | vfsmod.proxyvfs.__init__(self, vfs) | |
707 | self.fncache = fnc |
|
712 | self.fncache = fnc | |
708 | self.encode = encode |
|
713 | self.encode = encode | |
709 |
|
714 | |||
710 | def __call__(self, path, mode=b'r', *args, **kw): |
|
715 | def __call__(self, path, mode=b'r', *args, **kw): | |
711 | encoded = self.encode(path) |
|
716 | encoded = self.encode(path) | |
712 | if mode not in (b'r', b'rb') and ( |
|
717 | if mode not in (b'r', b'rb') and ( | |
713 | path.startswith(b'data/') or path.startswith(b'meta/') |
|
718 | path.startswith(b'data/') or path.startswith(b'meta/') | |
714 | ): |
|
719 | ): | |
715 | # do not trigger a fncache load when adding a file that already is |
|
720 | # do not trigger a fncache load when adding a file that already is | |
716 | # known to exist. |
|
721 | # known to exist. | |
717 | notload = self.fncache.entries is None and self.vfs.exists(encoded) |
|
722 | notload = self.fncache.entries is None and self.vfs.exists(encoded) | |
718 | if notload and b'r+' in mode and not self.vfs.stat(encoded).st_size: |
|
723 | if notload and b'r+' in mode and not self.vfs.stat(encoded).st_size: | |
719 | # when appending to an existing file, if the file has size zero, |
|
724 | # when appending to an existing file, if the file has size zero, | |
720 | # it should be considered as missing. Such zero-size files are |
|
725 | # it should be considered as missing. Such zero-size files are | |
721 | # the result of truncation when a transaction is aborted. |
|
726 | # the result of truncation when a transaction is aborted. | |
722 | notload = False |
|
727 | notload = False | |
723 | if not notload: |
|
728 | if not notload: | |
724 | self.fncache.add(path) |
|
729 | self.fncache.add(path) | |
725 | return self.vfs(encoded, mode, *args, **kw) |
|
730 | return self.vfs(encoded, mode, *args, **kw) | |
726 |
|
731 | |||
727 | def join(self, path): |
|
732 | def join(self, path): | |
728 | if path: |
|
733 | if path: | |
729 | return self.vfs.join(self.encode(path)) |
|
734 | return self.vfs.join(self.encode(path)) | |
730 | else: |
|
735 | else: | |
731 | return self.vfs.join(path) |
|
736 | return self.vfs.join(path) | |
732 |
|
737 | |||
733 | def register_file(self, path): |
|
738 | def register_file(self, path): | |
734 | """generic hook point to lets fncache steer its stew""" |
|
739 | """generic hook point to lets fncache steer its stew""" | |
735 | if path.startswith(b'data/') or path.startswith(b'meta/'): |
|
740 | if path.startswith(b'data/') or path.startswith(b'meta/'): | |
736 | self.fncache.add(path) |
|
741 | self.fncache.add(path) | |
737 |
|
742 | |||
738 |
|
743 | |||
739 | class fncachestore(basicstore): |
|
744 | class fncachestore(basicstore): | |
740 | def __init__(self, path, vfstype, dotencode): |
|
745 | def __init__(self, path, vfstype, dotencode): | |
741 | if dotencode: |
|
746 | if dotencode: | |
742 | encode = _pathencode |
|
747 | encode = _pathencode | |
743 | else: |
|
748 | else: | |
744 | encode = _plainhybridencode |
|
749 | encode = _plainhybridencode | |
745 | self.encode = encode |
|
750 | self.encode = encode | |
746 | vfs = vfstype(path + b'/store') |
|
751 | vfs = vfstype(path + b'/store') | |
747 | self.path = vfs.base |
|
752 | self.path = vfs.base | |
748 | self.pathsep = self.path + b'/' |
|
753 | self.pathsep = self.path + b'/' | |
749 | self.createmode = _calcmode(vfs) |
|
754 | self.createmode = _calcmode(vfs) | |
750 | vfs.createmode = self.createmode |
|
755 | vfs.createmode = self.createmode | |
751 | self.rawvfs = vfs |
|
756 | self.rawvfs = vfs | |
752 | fnc = fncache(vfs) |
|
757 | fnc = fncache(vfs) | |
753 | self.fncache = fnc |
|
758 | self.fncache = fnc | |
754 | self.vfs = _fncachevfs(vfs, fnc, encode) |
|
759 | self.vfs = _fncachevfs(vfs, fnc, encode) | |
755 | self.opener = self.vfs |
|
760 | self.opener = self.vfs | |
756 |
|
761 | |||
757 | def join(self, f): |
|
762 | def join(self, f): | |
758 | return self.pathsep + self.encode(f) |
|
763 | return self.pathsep + self.encode(f) | |
759 |
|
764 | |||
760 | def getsize(self, path): |
|
765 | def getsize(self, path): | |
761 | return self.rawvfs.stat(path).st_size |
|
766 | return self.rawvfs.stat(path).st_size | |
762 |
|
767 | |||
763 | def datafiles(self, matcher=None): |
|
768 | def datafiles(self, matcher=None): | |
764 | for f in sorted(self.fncache): |
|
769 | for f in sorted(self.fncache): | |
765 | if not _matchtrackedpath(f, matcher): |
|
770 | if not _matchtrackedpath(f, matcher): | |
766 | continue |
|
771 | continue | |
767 | ef = self.encode(f) |
|
772 | ef = self.encode(f) | |
768 | try: |
|
773 | try: | |
769 | t = revlog_type(f) |
|
774 | t = revlog_type(f) | |
770 | assert t is not None, f |
|
775 | assert t is not None, f | |
771 | t |= FILEFLAGS_FILELOG |
|
776 | t |= FILEFLAGS_FILELOG | |
772 | yield t, f, ef, self.getsize(ef) |
|
777 | yield t, f, ef, self.getsize(ef) | |
773 | except OSError as err: |
|
778 | except OSError as err: | |
774 | if err.errno != errno.ENOENT: |
|
779 | if err.errno != errno.ENOENT: | |
775 | raise |
|
780 | raise | |
776 |
|
781 | |||
777 | def copylist(self): |
|
782 | def copylist(self): | |
778 | d = ( |
|
783 | d = ( | |
779 | b'bookmarks', |
|
784 | b'bookmarks', | |
780 | b'narrowspec', |
|
785 | b'narrowspec', | |
781 | b'data', |
|
786 | b'data', | |
782 | b'meta', |
|
787 | b'meta', | |
783 | b'dh', |
|
788 | b'dh', | |
784 | b'fncache', |
|
789 | b'fncache', | |
785 | b'phaseroots', |
|
790 | b'phaseroots', | |
786 | b'obsstore', |
|
791 | b'obsstore', | |
787 | b'00manifest.d', |
|
792 | b'00manifest.d', | |
788 | b'00manifest.i', |
|
793 | b'00manifest.i', | |
789 | b'00changelog.d', |
|
794 | b'00changelog.d', | |
790 | b'00changelog.i', |
|
795 | b'00changelog.i', | |
791 | b'requires', |
|
796 | b'requires', | |
792 | ) |
|
797 | ) | |
793 | return [b'requires', b'00changelog.i'] + [b'store/' + f for f in d] |
|
798 | return [b'requires', b'00changelog.i'] + [b'store/' + f for f in d] | |
794 |
|
799 | |||
795 | def write(self, tr): |
|
800 | def write(self, tr): | |
796 | self.fncache.write(tr) |
|
801 | self.fncache.write(tr) | |
797 |
|
802 | |||
798 | def invalidatecaches(self): |
|
803 | def invalidatecaches(self): | |
799 | self.fncache.entries = None |
|
804 | self.fncache.entries = None | |
800 | self.fncache.addls = set() |
|
805 | self.fncache.addls = set() | |
801 |
|
806 | |||
802 | def markremoved(self, fn): |
|
807 | def markremoved(self, fn): | |
803 | self.fncache.remove(fn) |
|
808 | self.fncache.remove(fn) | |
804 |
|
809 | |||
805 | def _exists(self, f): |
|
810 | def _exists(self, f): | |
806 | ef = self.encode(f) |
|
811 | ef = self.encode(f) | |
807 | try: |
|
812 | try: | |
808 | self.getsize(ef) |
|
813 | self.getsize(ef) | |
809 | return True |
|
814 | return True | |
810 | except OSError as err: |
|
815 | except OSError as err: | |
811 | if err.errno != errno.ENOENT: |
|
816 | if err.errno != errno.ENOENT: | |
812 | raise |
|
817 | raise | |
813 | # nonexistent entry |
|
818 | # nonexistent entry | |
814 | return False |
|
819 | return False | |
815 |
|
820 | |||
816 | def __contains__(self, path): |
|
821 | def __contains__(self, path): | |
817 | '''Checks if the store contains path''' |
|
822 | '''Checks if the store contains path''' | |
818 | path = b"/".join((b"data", path)) |
|
823 | path = b"/".join((b"data", path)) | |
819 | # check for files (exact match) |
|
824 | # check for files (exact match) | |
820 | e = path + b'.i' |
|
825 | e = path + b'.i' | |
821 | if e in self.fncache and self._exists(e): |
|
826 | if e in self.fncache and self._exists(e): | |
822 | return True |
|
827 | return True | |
823 | # now check for directories (prefix match) |
|
828 | # now check for directories (prefix match) | |
824 | if not path.endswith(b'/'): |
|
829 | if not path.endswith(b'/'): | |
825 | path += b'/' |
|
830 | path += b'/' | |
826 | for e in self.fncache: |
|
831 | for e in self.fncache: | |
827 | if e.startswith(path) and self._exists(e): |
|
832 | if e.startswith(path) and self._exists(e): | |
828 | return True |
|
833 | return True | |
829 | return False |
|
834 | return False |
@@ -1,632 +1,643 b'' | |||||
1 | # upgrade.py - functions for in place upgrade of Mercurial repository |
|
1 | # upgrade.py - functions for in place upgrade of Mercurial repository | |
2 | # |
|
2 | # | |
3 | # Copyright (c) 2016-present, Gregory Szorc |
|
3 | # Copyright (c) 2016-present, Gregory Szorc | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | import stat |
|
10 | import stat | |
11 |
|
11 | |||
12 | from ..i18n import _ |
|
12 | from ..i18n import _ | |
13 | from ..pycompat import getattr |
|
13 | from ..pycompat import getattr | |
14 | from .. import ( |
|
14 | from .. import ( | |
15 | changelog, |
|
15 | changelog, | |
16 | error, |
|
16 | error, | |
17 | filelog, |
|
17 | filelog, | |
18 | manifest, |
|
18 | manifest, | |
19 | metadata, |
|
19 | metadata, | |
20 | pycompat, |
|
20 | pycompat, | |
21 | requirements, |
|
21 | requirements, | |
22 | scmutil, |
|
22 | scmutil, | |
23 | store, |
|
23 | store, | |
24 | util, |
|
24 | util, | |
25 | vfs as vfsmod, |
|
25 | vfs as vfsmod, | |
26 | ) |
|
26 | ) | |
27 | from ..revlogutils import ( |
|
27 | from ..revlogutils import ( | |
28 | constants as revlogconst, |
|
28 | constants as revlogconst, | |
29 | flagutil, |
|
29 | flagutil, | |
30 | nodemap, |
|
30 | nodemap, | |
31 | sidedata as sidedatamod, |
|
31 | sidedata as sidedatamod, | |
32 | ) |
|
32 | ) | |
33 | from . import actions as upgrade_actions |
|
33 | from . import actions as upgrade_actions | |
34 |
|
34 | |||
35 |
|
35 | |||
36 | def get_sidedata_helpers(srcrepo, dstrepo): |
|
36 | def get_sidedata_helpers(srcrepo, dstrepo): | |
37 | use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade') |
|
37 | use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade') | |
38 | sequential = pycompat.iswindows or not use_w |
|
38 | sequential = pycompat.iswindows or not use_w | |
39 | if not sequential: |
|
39 | if not sequential: | |
40 | srcrepo.register_sidedata_computer( |
|
40 | srcrepo.register_sidedata_computer( | |
41 | revlogconst.KIND_CHANGELOG, |
|
41 | revlogconst.KIND_CHANGELOG, | |
42 | sidedatamod.SD_FILES, |
|
42 | sidedatamod.SD_FILES, | |
43 | (sidedatamod.SD_FILES,), |
|
43 | (sidedatamod.SD_FILES,), | |
44 | metadata._get_worker_sidedata_adder(srcrepo, dstrepo), |
|
44 | metadata._get_worker_sidedata_adder(srcrepo, dstrepo), | |
45 | flagutil.REVIDX_HASCOPIESINFO, |
|
45 | flagutil.REVIDX_HASCOPIESINFO, | |
46 | replace=True, |
|
46 | replace=True, | |
47 | ) |
|
47 | ) | |
48 | return sidedatamod.get_sidedata_helpers(srcrepo, dstrepo._wanted_sidedata) |
|
48 | return sidedatamod.get_sidedata_helpers(srcrepo, dstrepo._wanted_sidedata) | |
49 |
|
49 | |||
50 |
|
50 | |||
51 | def _revlogfrompath(repo, rl_type, path): |
|
51 | def _revlogfrompath(repo, rl_type, path): | |
52 | """Obtain a revlog from a repo path. |
|
52 | """Obtain a revlog from a repo path. | |
53 |
|
53 | |||
54 | An instance of the appropriate class is returned. |
|
54 | An instance of the appropriate class is returned. | |
55 | """ |
|
55 | """ | |
56 | if rl_type & store.FILEFLAGS_CHANGELOG: |
|
56 | if rl_type & store.FILEFLAGS_CHANGELOG: | |
57 | return changelog.changelog(repo.svfs) |
|
57 | return changelog.changelog(repo.svfs) | |
58 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: |
|
58 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: | |
59 | mandir = b'' |
|
59 | mandir = b'' | |
60 | if b'/' in path: |
|
60 | if b'/' in path: | |
61 | mandir = path.rsplit(b'/', 1)[0] |
|
61 | mandir = path.rsplit(b'/', 1)[0] | |
62 | return manifest.manifestrevlog( |
|
62 | return manifest.manifestrevlog( | |
63 | repo.nodeconstants, repo.svfs, tree=mandir |
|
63 | repo.nodeconstants, repo.svfs, tree=mandir | |
64 | ) |
|
64 | ) | |
65 | else: |
|
65 | else: | |
66 | # drop the extension and the `data/` prefix |
|
66 | # drop the extension and the `data/` prefix | |
67 | path = path.rsplit(b'.', 1)[0].split(b'/', 1)[1] |
|
67 | path = path.rsplit(b'.', 1)[0].split(b'/', 1)[1] | |
68 | return filelog.filelog(repo.svfs, path) |
|
68 | return filelog.filelog(repo.svfs, path) | |
69 |
|
69 | |||
70 |
|
70 | |||
71 | def _copyrevlog(tr, destrepo, oldrl, rl_type, unencodedname): |
|
71 | def _copyrevlog(tr, destrepo, oldrl, rl_type, unencodedname): | |
72 | """copy all relevant files for `oldrl` into `destrepo` store |
|
72 | """copy all relevant files for `oldrl` into `destrepo` store | |
73 |
|
73 | |||
74 | Files are copied "as is" without any transformation. The copy is performed |
|
74 | Files are copied "as is" without any transformation. The copy is performed | |
75 | without extra checks. Callers are responsible for making sure the copied |
|
75 | without extra checks. Callers are responsible for making sure the copied | |
76 | content is compatible with format of the destination repository. |
|
76 | content is compatible with format of the destination repository. | |
77 | """ |
|
77 | """ | |
78 | oldrl = getattr(oldrl, '_revlog', oldrl) |
|
78 | oldrl = getattr(oldrl, '_revlog', oldrl) | |
79 | newrl = _revlogfrompath(destrepo, rl_type, unencodedname) |
|
79 | newrl = _revlogfrompath(destrepo, rl_type, unencodedname) | |
80 | newrl = getattr(newrl, '_revlog', newrl) |
|
80 | newrl = getattr(newrl, '_revlog', newrl) | |
81 |
|
81 | |||
82 | oldvfs = oldrl.opener |
|
82 | oldvfs = oldrl.opener | |
83 | newvfs = newrl.opener |
|
83 | newvfs = newrl.opener | |
84 | oldindex = oldvfs.join(oldrl._indexfile) |
|
84 | oldindex = oldvfs.join(oldrl._indexfile) | |
85 | newindex = newvfs.join(newrl._indexfile) |
|
85 | newindex = newvfs.join(newrl._indexfile) | |
86 | olddata = oldvfs.join(oldrl._datafile) |
|
86 | olddata = oldvfs.join(oldrl._datafile) | |
87 | newdata = newvfs.join(newrl._datafile) |
|
87 | newdata = newvfs.join(newrl._datafile) | |
88 |
|
88 | |||
89 | with newvfs(newrl._indexfile, b'w'): |
|
89 | with newvfs(newrl._indexfile, b'w'): | |
90 | pass # create all the directories |
|
90 | pass # create all the directories | |
91 |
|
91 | |||
92 | util.copyfile(oldindex, newindex) |
|
92 | util.copyfile(oldindex, newindex) | |
93 | copydata = oldrl.opener.exists(oldrl._datafile) |
|
93 | copydata = oldrl.opener.exists(oldrl._datafile) | |
94 | if copydata: |
|
94 | if copydata: | |
95 | util.copyfile(olddata, newdata) |
|
95 | util.copyfile(olddata, newdata) | |
96 |
|
96 | |||
97 | if rl_type & store.FILEFLAGS_FILELOG: |
|
97 | if rl_type & store.FILEFLAGS_FILELOG: | |
98 | destrepo.svfs.fncache.add(unencodedname) |
|
98 | destrepo.svfs.fncache.add(unencodedname) | |
99 | if copydata: |
|
99 | if copydata: | |
100 | destrepo.svfs.fncache.add(unencodedname[:-2] + b'.d') |
|
100 | destrepo.svfs.fncache.add(unencodedname[:-2] + b'.d') | |
101 |
|
101 | |||
102 |
|
102 | |||
103 | UPGRADE_CHANGELOG = b"changelog" |
|
103 | UPGRADE_CHANGELOG = b"changelog" | |
104 | UPGRADE_MANIFEST = b"manifest" |
|
104 | UPGRADE_MANIFEST = b"manifest" | |
105 | UPGRADE_FILELOGS = b"all-filelogs" |
|
105 | UPGRADE_FILELOGS = b"all-filelogs" | |
106 |
|
106 | |||
107 | UPGRADE_ALL_REVLOGS = frozenset( |
|
107 | UPGRADE_ALL_REVLOGS = frozenset( | |
108 | [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOGS] |
|
108 | [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOGS] | |
109 | ) |
|
109 | ) | |
110 |
|
110 | |||
111 |
|
111 | |||
112 | def matchrevlog(revlogfilter, rl_type): |
|
112 | def matchrevlog(revlogfilter, rl_type): | |
113 | """check if a revlog is selected for cloning. |
|
113 | """check if a revlog is selected for cloning. | |
114 |
|
114 | |||
115 | In other words, are there any updates which need to be done on revlog |
|
115 | In other words, are there any updates which need to be done on revlog | |
116 | or it can be blindly copied. |
|
116 | or it can be blindly copied. | |
117 |
|
117 | |||
118 | The store entry is checked against the passed filter""" |
|
118 | The store entry is checked against the passed filter""" | |
119 | if rl_type & store.FILEFLAGS_CHANGELOG: |
|
119 | if rl_type & store.FILEFLAGS_CHANGELOG: | |
120 | return UPGRADE_CHANGELOG in revlogfilter |
|
120 | return UPGRADE_CHANGELOG in revlogfilter | |
121 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: |
|
121 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: | |
122 | return UPGRADE_MANIFEST in revlogfilter |
|
122 | return UPGRADE_MANIFEST in revlogfilter | |
123 | assert rl_type & store.FILEFLAGS_FILELOG |
|
123 | assert rl_type & store.FILEFLAGS_FILELOG | |
124 | return UPGRADE_FILELOGS in revlogfilter |
|
124 | return UPGRADE_FILELOGS in revlogfilter | |
125 |
|
125 | |||
126 |
|
126 | |||
127 | def _perform_clone( |
|
127 | def _perform_clone( | |
128 | ui, |
|
128 | ui, | |
129 | dstrepo, |
|
129 | dstrepo, | |
130 | tr, |
|
130 | tr, | |
131 | old_revlog, |
|
131 | old_revlog, | |
132 | rl_type, |
|
132 | rl_type, | |
133 | unencoded, |
|
133 | unencoded, | |
134 | upgrade_op, |
|
134 | upgrade_op, | |
135 | sidedata_helpers, |
|
135 | sidedata_helpers, | |
136 | oncopiedrevision, |
|
136 | oncopiedrevision, | |
137 | ): |
|
137 | ): | |
138 | """returns the new revlog object created""" |
|
138 | """returns the new revlog object created""" | |
139 | newrl = None |
|
139 | newrl = None | |
140 | if matchrevlog(upgrade_op.revlogs_to_process, rl_type): |
|
140 | if matchrevlog(upgrade_op.revlogs_to_process, rl_type): | |
141 | ui.note( |
|
141 | ui.note( | |
142 | _(b'cloning %d revisions from %s\n') % (len(old_revlog), unencoded) |
|
142 | _(b'cloning %d revisions from %s\n') % (len(old_revlog), unencoded) | |
143 | ) |
|
143 | ) | |
144 | newrl = _revlogfrompath(dstrepo, rl_type, unencoded) |
|
144 | newrl = _revlogfrompath(dstrepo, rl_type, unencoded) | |
145 | old_revlog.clone( |
|
145 | old_revlog.clone( | |
146 | tr, |
|
146 | tr, | |
147 | newrl, |
|
147 | newrl, | |
148 | addrevisioncb=oncopiedrevision, |
|
148 | addrevisioncb=oncopiedrevision, | |
149 | deltareuse=upgrade_op.delta_reuse_mode, |
|
149 | deltareuse=upgrade_op.delta_reuse_mode, | |
150 | forcedeltabothparents=upgrade_op.force_re_delta_both_parents, |
|
150 | forcedeltabothparents=upgrade_op.force_re_delta_both_parents, | |
151 | sidedata_helpers=sidedata_helpers, |
|
151 | sidedata_helpers=sidedata_helpers, | |
152 | ) |
|
152 | ) | |
153 | else: |
|
153 | else: | |
154 | msg = _(b'blindly copying %s containing %i revisions\n') |
|
154 | msg = _(b'blindly copying %s containing %i revisions\n') | |
155 | ui.note(msg % (unencoded, len(old_revlog))) |
|
155 | ui.note(msg % (unencoded, len(old_revlog))) | |
156 | _copyrevlog(tr, dstrepo, old_revlog, rl_type, unencoded) |
|
156 | _copyrevlog(tr, dstrepo, old_revlog, rl_type, unencoded) | |
157 |
|
157 | |||
158 | newrl = _revlogfrompath(dstrepo, rl_type, unencoded) |
|
158 | newrl = _revlogfrompath(dstrepo, rl_type, unencoded) | |
159 | return newrl |
|
159 | return newrl | |
160 |
|
160 | |||
161 |
|
161 | |||
162 | def _clonerevlogs( |
|
162 | def _clonerevlogs( | |
163 | ui, |
|
163 | ui, | |
164 | srcrepo, |
|
164 | srcrepo, | |
165 | dstrepo, |
|
165 | dstrepo, | |
166 | tr, |
|
166 | tr, | |
167 | upgrade_op, |
|
167 | upgrade_op, | |
168 | ): |
|
168 | ): | |
169 | """Copy revlogs between 2 repos.""" |
|
169 | """Copy revlogs between 2 repos.""" | |
170 | revcount = 0 |
|
170 | revcount = 0 | |
171 | srcsize = 0 |
|
171 | srcsize = 0 | |
172 | srcrawsize = 0 |
|
172 | srcrawsize = 0 | |
173 | dstsize = 0 |
|
173 | dstsize = 0 | |
174 | fcount = 0 |
|
174 | fcount = 0 | |
175 | frevcount = 0 |
|
175 | frevcount = 0 | |
176 | fsrcsize = 0 |
|
176 | fsrcsize = 0 | |
177 | frawsize = 0 |
|
177 | frawsize = 0 | |
178 | fdstsize = 0 |
|
178 | fdstsize = 0 | |
179 | mcount = 0 |
|
179 | mcount = 0 | |
180 | mrevcount = 0 |
|
180 | mrevcount = 0 | |
181 | msrcsize = 0 |
|
181 | msrcsize = 0 | |
182 | mrawsize = 0 |
|
182 | mrawsize = 0 | |
183 | mdstsize = 0 |
|
183 | mdstsize = 0 | |
184 | crevcount = 0 |
|
184 | crevcount = 0 | |
185 | csrcsize = 0 |
|
185 | csrcsize = 0 | |
186 | crawsize = 0 |
|
186 | crawsize = 0 | |
187 | cdstsize = 0 |
|
187 | cdstsize = 0 | |
188 |
|
188 | |||
189 | alldatafiles = list(srcrepo.store.walk()) |
|
189 | alldatafiles = list(srcrepo.store.walk()) | |
190 | # mapping of data files which needs to be cloned |
|
190 | # mapping of data files which needs to be cloned | |
191 | # key is unencoded filename |
|
191 | # key is unencoded filename | |
192 | # value is revlog_object_from_srcrepo |
|
192 | # value is revlog_object_from_srcrepo | |
193 | manifests = {} |
|
193 | manifests = {} | |
194 | changelogs = {} |
|
194 | changelogs = {} | |
195 | filelogs = {} |
|
195 | filelogs = {} | |
196 |
|
196 | |||
197 | # Perform a pass to collect metadata. This validates we can open all |
|
197 | # Perform a pass to collect metadata. This validates we can open all | |
198 | # source files and allows a unified progress bar to be displayed. |
|
198 | # source files and allows a unified progress bar to be displayed. | |
199 | for rl_type, unencoded, encoded, size in alldatafiles: |
|
199 | for rl_type, unencoded, encoded, size in alldatafiles: | |
200 | if not rl_type & store.FILEFLAGS_REVLOG_MAIN: |
|
200 | if not rl_type & store.FILEFLAGS_REVLOG_MAIN: | |
201 | continue |
|
201 | continue | |
202 |
|
202 | |||
|
203 | # the store.walk function will wrongly pickup transaction backup and | |||
|
204 | # get confused. As a quick fix for 5.9 release, we ignore those. | |||
|
205 | # (this is not a module constants because it seems better to keep the | |||
|
206 | # hack together) | |||
|
207 | skip_undo = ( | |||
|
208 | b'undo.backup.00changelog.i', | |||
|
209 | b'undo.backup.00manifest.i', | |||
|
210 | ) | |||
|
211 | if unencoded in skip_undo: | |||
|
212 | continue | |||
|
213 | ||||
203 | rl = _revlogfrompath(srcrepo, rl_type, unencoded) |
|
214 | rl = _revlogfrompath(srcrepo, rl_type, unencoded) | |
204 |
|
215 | |||
205 | info = rl.storageinfo( |
|
216 | info = rl.storageinfo( | |
206 | exclusivefiles=True, |
|
217 | exclusivefiles=True, | |
207 | revisionscount=True, |
|
218 | revisionscount=True, | |
208 | trackedsize=True, |
|
219 | trackedsize=True, | |
209 | storedsize=True, |
|
220 | storedsize=True, | |
210 | ) |
|
221 | ) | |
211 |
|
222 | |||
212 | revcount += info[b'revisionscount'] or 0 |
|
223 | revcount += info[b'revisionscount'] or 0 | |
213 | datasize = info[b'storedsize'] or 0 |
|
224 | datasize = info[b'storedsize'] or 0 | |
214 | rawsize = info[b'trackedsize'] or 0 |
|
225 | rawsize = info[b'trackedsize'] or 0 | |
215 |
|
226 | |||
216 | srcsize += datasize |
|
227 | srcsize += datasize | |
217 | srcrawsize += rawsize |
|
228 | srcrawsize += rawsize | |
218 |
|
229 | |||
219 | # This is for the separate progress bars. |
|
230 | # This is for the separate progress bars. | |
220 | if rl_type & store.FILEFLAGS_CHANGELOG: |
|
231 | if rl_type & store.FILEFLAGS_CHANGELOG: | |
221 | changelogs[unencoded] = (rl_type, rl) |
|
232 | changelogs[unencoded] = (rl_type, rl) | |
222 | crevcount += len(rl) |
|
233 | crevcount += len(rl) | |
223 | csrcsize += datasize |
|
234 | csrcsize += datasize | |
224 | crawsize += rawsize |
|
235 | crawsize += rawsize | |
225 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: |
|
236 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: | |
226 | manifests[unencoded] = (rl_type, rl) |
|
237 | manifests[unencoded] = (rl_type, rl) | |
227 | mcount += 1 |
|
238 | mcount += 1 | |
228 | mrevcount += len(rl) |
|
239 | mrevcount += len(rl) | |
229 | msrcsize += datasize |
|
240 | msrcsize += datasize | |
230 | mrawsize += rawsize |
|
241 | mrawsize += rawsize | |
231 | elif rl_type & store.FILEFLAGS_FILELOG: |
|
242 | elif rl_type & store.FILEFLAGS_FILELOG: | |
232 | filelogs[unencoded] = (rl_type, rl) |
|
243 | filelogs[unencoded] = (rl_type, rl) | |
233 | fcount += 1 |
|
244 | fcount += 1 | |
234 | frevcount += len(rl) |
|
245 | frevcount += len(rl) | |
235 | fsrcsize += datasize |
|
246 | fsrcsize += datasize | |
236 | frawsize += rawsize |
|
247 | frawsize += rawsize | |
237 | else: |
|
248 | else: | |
238 | error.ProgrammingError(b'unknown revlog type') |
|
249 | error.ProgrammingError(b'unknown revlog type') | |
239 |
|
250 | |||
240 | if not revcount: |
|
251 | if not revcount: | |
241 | return |
|
252 | return | |
242 |
|
253 | |||
243 | ui.status( |
|
254 | ui.status( | |
244 | _( |
|
255 | _( | |
245 | b'migrating %d total revisions (%d in filelogs, %d in manifests, ' |
|
256 | b'migrating %d total revisions (%d in filelogs, %d in manifests, ' | |
246 | b'%d in changelog)\n' |
|
257 | b'%d in changelog)\n' | |
247 | ) |
|
258 | ) | |
248 | % (revcount, frevcount, mrevcount, crevcount) |
|
259 | % (revcount, frevcount, mrevcount, crevcount) | |
249 | ) |
|
260 | ) | |
250 | ui.status( |
|
261 | ui.status( | |
251 | _(b'migrating %s in store; %s tracked data\n') |
|
262 | _(b'migrating %s in store; %s tracked data\n') | |
252 | % ((util.bytecount(srcsize), util.bytecount(srcrawsize))) |
|
263 | % ((util.bytecount(srcsize), util.bytecount(srcrawsize))) | |
253 | ) |
|
264 | ) | |
254 |
|
265 | |||
255 | # Used to keep track of progress. |
|
266 | # Used to keep track of progress. | |
256 | progress = None |
|
267 | progress = None | |
257 |
|
268 | |||
258 | def oncopiedrevision(rl, rev, node): |
|
269 | def oncopiedrevision(rl, rev, node): | |
259 | progress.increment() |
|
270 | progress.increment() | |
260 |
|
271 | |||
261 | sidedata_helpers = get_sidedata_helpers(srcrepo, dstrepo) |
|
272 | sidedata_helpers = get_sidedata_helpers(srcrepo, dstrepo) | |
262 |
|
273 | |||
263 | # Migrating filelogs |
|
274 | # Migrating filelogs | |
264 | ui.status( |
|
275 | ui.status( | |
265 | _( |
|
276 | _( | |
266 | b'migrating %d filelogs containing %d revisions ' |
|
277 | b'migrating %d filelogs containing %d revisions ' | |
267 | b'(%s in store; %s tracked data)\n' |
|
278 | b'(%s in store; %s tracked data)\n' | |
268 | ) |
|
279 | ) | |
269 | % ( |
|
280 | % ( | |
270 | fcount, |
|
281 | fcount, | |
271 | frevcount, |
|
282 | frevcount, | |
272 | util.bytecount(fsrcsize), |
|
283 | util.bytecount(fsrcsize), | |
273 | util.bytecount(frawsize), |
|
284 | util.bytecount(frawsize), | |
274 | ) |
|
285 | ) | |
275 | ) |
|
286 | ) | |
276 | progress = srcrepo.ui.makeprogress(_(b'file revisions'), total=frevcount) |
|
287 | progress = srcrepo.ui.makeprogress(_(b'file revisions'), total=frevcount) | |
277 | for unencoded, (rl_type, oldrl) in sorted(filelogs.items()): |
|
288 | for unencoded, (rl_type, oldrl) in sorted(filelogs.items()): | |
278 | newrl = _perform_clone( |
|
289 | newrl = _perform_clone( | |
279 | ui, |
|
290 | ui, | |
280 | dstrepo, |
|
291 | dstrepo, | |
281 | tr, |
|
292 | tr, | |
282 | oldrl, |
|
293 | oldrl, | |
283 | rl_type, |
|
294 | rl_type, | |
284 | unencoded, |
|
295 | unencoded, | |
285 | upgrade_op, |
|
296 | upgrade_op, | |
286 | sidedata_helpers, |
|
297 | sidedata_helpers, | |
287 | oncopiedrevision, |
|
298 | oncopiedrevision, | |
288 | ) |
|
299 | ) | |
289 | info = newrl.storageinfo(storedsize=True) |
|
300 | info = newrl.storageinfo(storedsize=True) | |
290 | fdstsize += info[b'storedsize'] or 0 |
|
301 | fdstsize += info[b'storedsize'] or 0 | |
291 | ui.status( |
|
302 | ui.status( | |
292 | _( |
|
303 | _( | |
293 | b'finished migrating %d filelog revisions across %d ' |
|
304 | b'finished migrating %d filelog revisions across %d ' | |
294 | b'filelogs; change in size: %s\n' |
|
305 | b'filelogs; change in size: %s\n' | |
295 | ) |
|
306 | ) | |
296 | % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)) |
|
307 | % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)) | |
297 | ) |
|
308 | ) | |
298 |
|
309 | |||
299 | # Migrating manifests |
|
310 | # Migrating manifests | |
300 | ui.status( |
|
311 | ui.status( | |
301 | _( |
|
312 | _( | |
302 | b'migrating %d manifests containing %d revisions ' |
|
313 | b'migrating %d manifests containing %d revisions ' | |
303 | b'(%s in store; %s tracked data)\n' |
|
314 | b'(%s in store; %s tracked data)\n' | |
304 | ) |
|
315 | ) | |
305 | % ( |
|
316 | % ( | |
306 | mcount, |
|
317 | mcount, | |
307 | mrevcount, |
|
318 | mrevcount, | |
308 | util.bytecount(msrcsize), |
|
319 | util.bytecount(msrcsize), | |
309 | util.bytecount(mrawsize), |
|
320 | util.bytecount(mrawsize), | |
310 | ) |
|
321 | ) | |
311 | ) |
|
322 | ) | |
312 | if progress: |
|
323 | if progress: | |
313 | progress.complete() |
|
324 | progress.complete() | |
314 | progress = srcrepo.ui.makeprogress( |
|
325 | progress = srcrepo.ui.makeprogress( | |
315 | _(b'manifest revisions'), total=mrevcount |
|
326 | _(b'manifest revisions'), total=mrevcount | |
316 | ) |
|
327 | ) | |
317 | for unencoded, (rl_type, oldrl) in sorted(manifests.items()): |
|
328 | for unencoded, (rl_type, oldrl) in sorted(manifests.items()): | |
318 | newrl = _perform_clone( |
|
329 | newrl = _perform_clone( | |
319 | ui, |
|
330 | ui, | |
320 | dstrepo, |
|
331 | dstrepo, | |
321 | tr, |
|
332 | tr, | |
322 | oldrl, |
|
333 | oldrl, | |
323 | rl_type, |
|
334 | rl_type, | |
324 | unencoded, |
|
335 | unencoded, | |
325 | upgrade_op, |
|
336 | upgrade_op, | |
326 | sidedata_helpers, |
|
337 | sidedata_helpers, | |
327 | oncopiedrevision, |
|
338 | oncopiedrevision, | |
328 | ) |
|
339 | ) | |
329 | info = newrl.storageinfo(storedsize=True) |
|
340 | info = newrl.storageinfo(storedsize=True) | |
330 | mdstsize += info[b'storedsize'] or 0 |
|
341 | mdstsize += info[b'storedsize'] or 0 | |
331 | ui.status( |
|
342 | ui.status( | |
332 | _( |
|
343 | _( | |
333 | b'finished migrating %d manifest revisions across %d ' |
|
344 | b'finished migrating %d manifest revisions across %d ' | |
334 | b'manifests; change in size: %s\n' |
|
345 | b'manifests; change in size: %s\n' | |
335 | ) |
|
346 | ) | |
336 | % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)) |
|
347 | % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)) | |
337 | ) |
|
348 | ) | |
338 |
|
349 | |||
339 | # Migrating changelog |
|
350 | # Migrating changelog | |
340 | ui.status( |
|
351 | ui.status( | |
341 | _( |
|
352 | _( | |
342 | b'migrating changelog containing %d revisions ' |
|
353 | b'migrating changelog containing %d revisions ' | |
343 | b'(%s in store; %s tracked data)\n' |
|
354 | b'(%s in store; %s tracked data)\n' | |
344 | ) |
|
355 | ) | |
345 | % ( |
|
356 | % ( | |
346 | crevcount, |
|
357 | crevcount, | |
347 | util.bytecount(csrcsize), |
|
358 | util.bytecount(csrcsize), | |
348 | util.bytecount(crawsize), |
|
359 | util.bytecount(crawsize), | |
349 | ) |
|
360 | ) | |
350 | ) |
|
361 | ) | |
351 | if progress: |
|
362 | if progress: | |
352 | progress.complete() |
|
363 | progress.complete() | |
353 | progress = srcrepo.ui.makeprogress( |
|
364 | progress = srcrepo.ui.makeprogress( | |
354 | _(b'changelog revisions'), total=crevcount |
|
365 | _(b'changelog revisions'), total=crevcount | |
355 | ) |
|
366 | ) | |
356 | for unencoded, (rl_type, oldrl) in sorted(changelogs.items()): |
|
367 | for unencoded, (rl_type, oldrl) in sorted(changelogs.items()): | |
357 | newrl = _perform_clone( |
|
368 | newrl = _perform_clone( | |
358 | ui, |
|
369 | ui, | |
359 | dstrepo, |
|
370 | dstrepo, | |
360 | tr, |
|
371 | tr, | |
361 | oldrl, |
|
372 | oldrl, | |
362 | rl_type, |
|
373 | rl_type, | |
363 | unencoded, |
|
374 | unencoded, | |
364 | upgrade_op, |
|
375 | upgrade_op, | |
365 | sidedata_helpers, |
|
376 | sidedata_helpers, | |
366 | oncopiedrevision, |
|
377 | oncopiedrevision, | |
367 | ) |
|
378 | ) | |
368 | info = newrl.storageinfo(storedsize=True) |
|
379 | info = newrl.storageinfo(storedsize=True) | |
369 | cdstsize += info[b'storedsize'] or 0 |
|
380 | cdstsize += info[b'storedsize'] or 0 | |
370 | progress.complete() |
|
381 | progress.complete() | |
371 | ui.status( |
|
382 | ui.status( | |
372 | _( |
|
383 | _( | |
373 | b'finished migrating %d changelog revisions; change in size: ' |
|
384 | b'finished migrating %d changelog revisions; change in size: ' | |
374 | b'%s\n' |
|
385 | b'%s\n' | |
375 | ) |
|
386 | ) | |
376 | % (crevcount, util.bytecount(cdstsize - csrcsize)) |
|
387 | % (crevcount, util.bytecount(cdstsize - csrcsize)) | |
377 | ) |
|
388 | ) | |
378 |
|
389 | |||
379 | dstsize = fdstsize + mdstsize + cdstsize |
|
390 | dstsize = fdstsize + mdstsize + cdstsize | |
380 | ui.status( |
|
391 | ui.status( | |
381 | _( |
|
392 | _( | |
382 | b'finished migrating %d total revisions; total change in store ' |
|
393 | b'finished migrating %d total revisions; total change in store ' | |
383 | b'size: %s\n' |
|
394 | b'size: %s\n' | |
384 | ) |
|
395 | ) | |
385 | % (revcount, util.bytecount(dstsize - srcsize)) |
|
396 | % (revcount, util.bytecount(dstsize - srcsize)) | |
386 | ) |
|
397 | ) | |
387 |
|
398 | |||
388 |
|
399 | |||
389 | def _files_to_copy_post_revlog_clone(srcrepo): |
|
400 | def _files_to_copy_post_revlog_clone(srcrepo): | |
390 | """yields files which should be copied to destination after revlogs |
|
401 | """yields files which should be copied to destination after revlogs | |
391 | are cloned""" |
|
402 | are cloned""" | |
392 | for path, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)): |
|
403 | for path, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)): | |
393 | # don't copy revlogs as they are already cloned |
|
404 | # don't copy revlogs as they are already cloned | |
394 | if store.revlog_type(path) is not None: |
|
405 | if store.revlog_type(path) is not None: | |
395 | continue |
|
406 | continue | |
396 | # Skip transaction related files. |
|
407 | # Skip transaction related files. | |
397 | if path.startswith(b'undo'): |
|
408 | if path.startswith(b'undo'): | |
398 | continue |
|
409 | continue | |
399 | # Only copy regular files. |
|
410 | # Only copy regular files. | |
400 | if kind != stat.S_IFREG: |
|
411 | if kind != stat.S_IFREG: | |
401 | continue |
|
412 | continue | |
402 | # Skip other skipped files. |
|
413 | # Skip other skipped files. | |
403 | if path in (b'lock', b'fncache'): |
|
414 | if path in (b'lock', b'fncache'): | |
404 | continue |
|
415 | continue | |
405 | # TODO: should we skip cache too? |
|
416 | # TODO: should we skip cache too? | |
406 |
|
417 | |||
407 | yield path |
|
418 | yield path | |
408 |
|
419 | |||
409 |
|
420 | |||
410 | def _replacestores(currentrepo, upgradedrepo, backupvfs, upgrade_op): |
|
421 | def _replacestores(currentrepo, upgradedrepo, backupvfs, upgrade_op): | |
411 | """Replace the stores after current repository is upgraded |
|
422 | """Replace the stores after current repository is upgraded | |
412 |
|
423 | |||
413 | Creates a backup of current repository store at backup path |
|
424 | Creates a backup of current repository store at backup path | |
414 | Replaces upgraded store files in current repo from upgraded one |
|
425 | Replaces upgraded store files in current repo from upgraded one | |
415 |
|
426 | |||
416 | Arguments: |
|
427 | Arguments: | |
417 | currentrepo: repo object of current repository |
|
428 | currentrepo: repo object of current repository | |
418 | upgradedrepo: repo object of the upgraded data |
|
429 | upgradedrepo: repo object of the upgraded data | |
419 | backupvfs: vfs object for the backup path |
|
430 | backupvfs: vfs object for the backup path | |
420 | upgrade_op: upgrade operation object |
|
431 | upgrade_op: upgrade operation object | |
421 | to be used to decide what all is upgraded |
|
432 | to be used to decide what all is upgraded | |
422 | """ |
|
433 | """ | |
423 | # TODO: don't blindly rename everything in store |
|
434 | # TODO: don't blindly rename everything in store | |
424 | # There can be upgrades where store is not touched at all |
|
435 | # There can be upgrades where store is not touched at all | |
425 | if upgrade_op.backup_store: |
|
436 | if upgrade_op.backup_store: | |
426 | util.rename(currentrepo.spath, backupvfs.join(b'store')) |
|
437 | util.rename(currentrepo.spath, backupvfs.join(b'store')) | |
427 | else: |
|
438 | else: | |
428 | currentrepo.vfs.rmtree(b'store', forcibly=True) |
|
439 | currentrepo.vfs.rmtree(b'store', forcibly=True) | |
429 | util.rename(upgradedrepo.spath, currentrepo.spath) |
|
440 | util.rename(upgradedrepo.spath, currentrepo.spath) | |
430 |
|
441 | |||
431 |
|
442 | |||
432 | def finishdatamigration(ui, srcrepo, dstrepo, requirements): |
|
443 | def finishdatamigration(ui, srcrepo, dstrepo, requirements): | |
433 | """Hook point for extensions to perform additional actions during upgrade. |
|
444 | """Hook point for extensions to perform additional actions during upgrade. | |
434 |
|
445 | |||
435 | This function is called after revlogs and store files have been copied but |
|
446 | This function is called after revlogs and store files have been copied but | |
436 | before the new store is swapped into the original location. |
|
447 | before the new store is swapped into the original location. | |
437 | """ |
|
448 | """ | |
438 |
|
449 | |||
439 |
|
450 | |||
440 | def upgrade(ui, srcrepo, dstrepo, upgrade_op): |
|
451 | def upgrade(ui, srcrepo, dstrepo, upgrade_op): | |
441 | """Do the low-level work of upgrading a repository. |
|
452 | """Do the low-level work of upgrading a repository. | |
442 |
|
453 | |||
443 | The upgrade is effectively performed as a copy between a source |
|
454 | The upgrade is effectively performed as a copy between a source | |
444 | repository and a temporary destination repository. |
|
455 | repository and a temporary destination repository. | |
445 |
|
456 | |||
446 | The source repository is unmodified for as long as possible so the |
|
457 | The source repository is unmodified for as long as possible so the | |
447 | upgrade can abort at any time without causing loss of service for |
|
458 | upgrade can abort at any time without causing loss of service for | |
448 | readers and without corrupting the source repository. |
|
459 | readers and without corrupting the source repository. | |
449 | """ |
|
460 | """ | |
450 | assert srcrepo.currentwlock() |
|
461 | assert srcrepo.currentwlock() | |
451 | assert dstrepo.currentwlock() |
|
462 | assert dstrepo.currentwlock() | |
452 | backuppath = None |
|
463 | backuppath = None | |
453 | backupvfs = None |
|
464 | backupvfs = None | |
454 |
|
465 | |||
455 | ui.status( |
|
466 | ui.status( | |
456 | _( |
|
467 | _( | |
457 | b'(it is safe to interrupt this process any time before ' |
|
468 | b'(it is safe to interrupt this process any time before ' | |
458 | b'data migration completes)\n' |
|
469 | b'data migration completes)\n' | |
459 | ) |
|
470 | ) | |
460 | ) |
|
471 | ) | |
461 |
|
472 | |||
462 | if upgrade_actions.dirstatev2 in upgrade_op.upgrade_actions: |
|
473 | if upgrade_actions.dirstatev2 in upgrade_op.upgrade_actions: | |
463 | ui.status(_(b'upgrading to dirstate-v2 from v1\n')) |
|
474 | ui.status(_(b'upgrading to dirstate-v2 from v1\n')) | |
464 | upgrade_dirstate(ui, srcrepo, upgrade_op, b'v1', b'v2') |
|
475 | upgrade_dirstate(ui, srcrepo, upgrade_op, b'v1', b'v2') | |
465 | upgrade_op.upgrade_actions.remove(upgrade_actions.dirstatev2) |
|
476 | upgrade_op.upgrade_actions.remove(upgrade_actions.dirstatev2) | |
466 |
|
477 | |||
467 | if upgrade_actions.dirstatev2 in upgrade_op.removed_actions: |
|
478 | if upgrade_actions.dirstatev2 in upgrade_op.removed_actions: | |
468 | ui.status(_(b'downgrading from dirstate-v2 to v1\n')) |
|
479 | ui.status(_(b'downgrading from dirstate-v2 to v1\n')) | |
469 | upgrade_dirstate(ui, srcrepo, upgrade_op, b'v2', b'v1') |
|
480 | upgrade_dirstate(ui, srcrepo, upgrade_op, b'v2', b'v1') | |
470 | upgrade_op.removed_actions.remove(upgrade_actions.dirstatev2) |
|
481 | upgrade_op.removed_actions.remove(upgrade_actions.dirstatev2) | |
471 |
|
482 | |||
472 | if not (upgrade_op.upgrade_actions or upgrade_op.removed_actions): |
|
483 | if not (upgrade_op.upgrade_actions or upgrade_op.removed_actions): | |
473 | return |
|
484 | return | |
474 |
|
485 | |||
475 | if upgrade_op.requirements_only: |
|
486 | if upgrade_op.requirements_only: | |
476 | ui.status(_(b'upgrading repository requirements\n')) |
|
487 | ui.status(_(b'upgrading repository requirements\n')) | |
477 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
|
488 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) | |
478 | # if there is only one action and that is persistent nodemap upgrade |
|
489 | # if there is only one action and that is persistent nodemap upgrade | |
479 | # directly write the nodemap file and update requirements instead of going |
|
490 | # directly write the nodemap file and update requirements instead of going | |
480 | # through the whole cloning process |
|
491 | # through the whole cloning process | |
481 | elif ( |
|
492 | elif ( | |
482 | len(upgrade_op.upgrade_actions) == 1 |
|
493 | len(upgrade_op.upgrade_actions) == 1 | |
483 | and b'persistent-nodemap' in upgrade_op.upgrade_actions_names |
|
494 | and b'persistent-nodemap' in upgrade_op.upgrade_actions_names | |
484 | and not upgrade_op.removed_actions |
|
495 | and not upgrade_op.removed_actions | |
485 | ): |
|
496 | ): | |
486 | ui.status( |
|
497 | ui.status( | |
487 | _(b'upgrading repository to use persistent nodemap feature\n') |
|
498 | _(b'upgrading repository to use persistent nodemap feature\n') | |
488 | ) |
|
499 | ) | |
489 | with srcrepo.transaction(b'upgrade') as tr: |
|
500 | with srcrepo.transaction(b'upgrade') as tr: | |
490 | unfi = srcrepo.unfiltered() |
|
501 | unfi = srcrepo.unfiltered() | |
491 | cl = unfi.changelog |
|
502 | cl = unfi.changelog | |
492 | nodemap.persist_nodemap(tr, cl, force=True) |
|
503 | nodemap.persist_nodemap(tr, cl, force=True) | |
493 | # we want to directly operate on the underlying revlog to force |
|
504 | # we want to directly operate on the underlying revlog to force | |
494 | # create a nodemap file. This is fine since this is upgrade code |
|
505 | # create a nodemap file. This is fine since this is upgrade code | |
495 | # and it heavily relies on repository being revlog based |
|
506 | # and it heavily relies on repository being revlog based | |
496 | # hence accessing private attributes can be justified |
|
507 | # hence accessing private attributes can be justified | |
497 | nodemap.persist_nodemap( |
|
508 | nodemap.persist_nodemap( | |
498 | tr, unfi.manifestlog._rootstore._revlog, force=True |
|
509 | tr, unfi.manifestlog._rootstore._revlog, force=True | |
499 | ) |
|
510 | ) | |
500 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
|
511 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) | |
501 | elif ( |
|
512 | elif ( | |
502 | len(upgrade_op.removed_actions) == 1 |
|
513 | len(upgrade_op.removed_actions) == 1 | |
503 | and [ |
|
514 | and [ | |
504 | x |
|
515 | x | |
505 | for x in upgrade_op.removed_actions |
|
516 | for x in upgrade_op.removed_actions | |
506 | if x.name == b'persistent-nodemap' |
|
517 | if x.name == b'persistent-nodemap' | |
507 | ] |
|
518 | ] | |
508 | and not upgrade_op.upgrade_actions |
|
519 | and not upgrade_op.upgrade_actions | |
509 | ): |
|
520 | ): | |
510 | ui.status( |
|
521 | ui.status( | |
511 | _(b'downgrading repository to not use persistent nodemap feature\n') |
|
522 | _(b'downgrading repository to not use persistent nodemap feature\n') | |
512 | ) |
|
523 | ) | |
513 | with srcrepo.transaction(b'upgrade') as tr: |
|
524 | with srcrepo.transaction(b'upgrade') as tr: | |
514 | unfi = srcrepo.unfiltered() |
|
525 | unfi = srcrepo.unfiltered() | |
515 | cl = unfi.changelog |
|
526 | cl = unfi.changelog | |
516 | nodemap.delete_nodemap(tr, srcrepo, cl) |
|
527 | nodemap.delete_nodemap(tr, srcrepo, cl) | |
517 | # check comment 20 lines above for accessing private attributes |
|
528 | # check comment 20 lines above for accessing private attributes | |
518 | nodemap.delete_nodemap( |
|
529 | nodemap.delete_nodemap( | |
519 | tr, srcrepo, unfi.manifestlog._rootstore._revlog |
|
530 | tr, srcrepo, unfi.manifestlog._rootstore._revlog | |
520 | ) |
|
531 | ) | |
521 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
|
532 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) | |
522 | else: |
|
533 | else: | |
523 | with dstrepo.transaction(b'upgrade') as tr: |
|
534 | with dstrepo.transaction(b'upgrade') as tr: | |
524 | _clonerevlogs( |
|
535 | _clonerevlogs( | |
525 | ui, |
|
536 | ui, | |
526 | srcrepo, |
|
537 | srcrepo, | |
527 | dstrepo, |
|
538 | dstrepo, | |
528 | tr, |
|
539 | tr, | |
529 | upgrade_op, |
|
540 | upgrade_op, | |
530 | ) |
|
541 | ) | |
531 |
|
542 | |||
532 | # Now copy other files in the store directory. |
|
543 | # Now copy other files in the store directory. | |
533 | for p in _files_to_copy_post_revlog_clone(srcrepo): |
|
544 | for p in _files_to_copy_post_revlog_clone(srcrepo): | |
534 | srcrepo.ui.status(_(b'copying %s\n') % p) |
|
545 | srcrepo.ui.status(_(b'copying %s\n') % p) | |
535 | src = srcrepo.store.rawvfs.join(p) |
|
546 | src = srcrepo.store.rawvfs.join(p) | |
536 | dst = dstrepo.store.rawvfs.join(p) |
|
547 | dst = dstrepo.store.rawvfs.join(p) | |
537 | util.copyfile(src, dst, copystat=True) |
|
548 | util.copyfile(src, dst, copystat=True) | |
538 |
|
549 | |||
539 | finishdatamigration(ui, srcrepo, dstrepo, requirements) |
|
550 | finishdatamigration(ui, srcrepo, dstrepo, requirements) | |
540 |
|
551 | |||
541 | ui.status(_(b'data fully upgraded in a temporary repository\n')) |
|
552 | ui.status(_(b'data fully upgraded in a temporary repository\n')) | |
542 |
|
553 | |||
543 | if upgrade_op.backup_store: |
|
554 | if upgrade_op.backup_store: | |
544 | backuppath = pycompat.mkdtemp( |
|
555 | backuppath = pycompat.mkdtemp( | |
545 | prefix=b'upgradebackup.', dir=srcrepo.path |
|
556 | prefix=b'upgradebackup.', dir=srcrepo.path | |
546 | ) |
|
557 | ) | |
547 | backupvfs = vfsmod.vfs(backuppath) |
|
558 | backupvfs = vfsmod.vfs(backuppath) | |
548 |
|
559 | |||
549 | # Make a backup of requires file first, as it is the first to be modified. |
|
560 | # Make a backup of requires file first, as it is the first to be modified. | |
550 | util.copyfile( |
|
561 | util.copyfile( | |
551 | srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires') |
|
562 | srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires') | |
552 | ) |
|
563 | ) | |
553 |
|
564 | |||
554 | # We install an arbitrary requirement that clients must not support |
|
565 | # We install an arbitrary requirement that clients must not support | |
555 | # as a mechanism to lock out new clients during the data swap. This is |
|
566 | # as a mechanism to lock out new clients during the data swap. This is | |
556 | # better than allowing a client to continue while the repository is in |
|
567 | # better than allowing a client to continue while the repository is in | |
557 | # an inconsistent state. |
|
568 | # an inconsistent state. | |
558 | ui.status( |
|
569 | ui.status( | |
559 | _( |
|
570 | _( | |
560 | b'marking source repository as being upgraded; clients will be ' |
|
571 | b'marking source repository as being upgraded; clients will be ' | |
561 | b'unable to read from repository\n' |
|
572 | b'unable to read from repository\n' | |
562 | ) |
|
573 | ) | |
563 | ) |
|
574 | ) | |
564 | scmutil.writereporequirements( |
|
575 | scmutil.writereporequirements( | |
565 | srcrepo, srcrepo.requirements | {b'upgradeinprogress'} |
|
576 | srcrepo, srcrepo.requirements | {b'upgradeinprogress'} | |
566 | ) |
|
577 | ) | |
567 |
|
578 | |||
568 | ui.status(_(b'starting in-place swap of repository data\n')) |
|
579 | ui.status(_(b'starting in-place swap of repository data\n')) | |
569 | if upgrade_op.backup_store: |
|
580 | if upgrade_op.backup_store: | |
570 | ui.status( |
|
581 | ui.status( | |
571 | _(b'replaced files will be backed up at %s\n') % backuppath |
|
582 | _(b'replaced files will be backed up at %s\n') % backuppath | |
572 | ) |
|
583 | ) | |
573 |
|
584 | |||
574 | # Now swap in the new store directory. Doing it as a rename should make |
|
585 | # Now swap in the new store directory. Doing it as a rename should make | |
575 | # the operation nearly instantaneous and atomic (at least in well-behaved |
|
586 | # the operation nearly instantaneous and atomic (at least in well-behaved | |
576 | # environments). |
|
587 | # environments). | |
577 | ui.status(_(b'replacing store...\n')) |
|
588 | ui.status(_(b'replacing store...\n')) | |
578 | tstart = util.timer() |
|
589 | tstart = util.timer() | |
579 | _replacestores(srcrepo, dstrepo, backupvfs, upgrade_op) |
|
590 | _replacestores(srcrepo, dstrepo, backupvfs, upgrade_op) | |
580 | elapsed = util.timer() - tstart |
|
591 | elapsed = util.timer() - tstart | |
581 | ui.status( |
|
592 | ui.status( | |
582 | _( |
|
593 | _( | |
583 | b'store replacement complete; repository was inconsistent for ' |
|
594 | b'store replacement complete; repository was inconsistent for ' | |
584 | b'%0.1fs\n' |
|
595 | b'%0.1fs\n' | |
585 | ) |
|
596 | ) | |
586 | % elapsed |
|
597 | % elapsed | |
587 | ) |
|
598 | ) | |
588 |
|
599 | |||
589 | # We first write the requirements file. Any new requirements will lock |
|
600 | # We first write the requirements file. Any new requirements will lock | |
590 | # out legacy clients. |
|
601 | # out legacy clients. | |
591 | ui.status( |
|
602 | ui.status( | |
592 | _( |
|
603 | _( | |
593 | b'finalizing requirements file and making repository readable ' |
|
604 | b'finalizing requirements file and making repository readable ' | |
594 | b'again\n' |
|
605 | b'again\n' | |
595 | ) |
|
606 | ) | |
596 | ) |
|
607 | ) | |
597 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
|
608 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) | |
598 |
|
609 | |||
599 | if upgrade_op.backup_store: |
|
610 | if upgrade_op.backup_store: | |
600 | # The lock file from the old store won't be removed because nothing has a |
|
611 | # The lock file from the old store won't be removed because nothing has a | |
601 | # reference to its new location. So clean it up manually. Alternatively, we |
|
612 | # reference to its new location. So clean it up manually. Alternatively, we | |
602 | # could update srcrepo.svfs and other variables to point to the new |
|
613 | # could update srcrepo.svfs and other variables to point to the new | |
603 | # location. This is simpler. |
|
614 | # location. This is simpler. | |
604 | assert backupvfs is not None # help pytype |
|
615 | assert backupvfs is not None # help pytype | |
605 | backupvfs.unlink(b'store/lock') |
|
616 | backupvfs.unlink(b'store/lock') | |
606 |
|
617 | |||
607 | return backuppath |
|
618 | return backuppath | |
608 |
|
619 | |||
609 |
|
620 | |||
610 | def upgrade_dirstate(ui, srcrepo, upgrade_op, old, new): |
|
621 | def upgrade_dirstate(ui, srcrepo, upgrade_op, old, new): | |
611 | if upgrade_op.backup_store: |
|
622 | if upgrade_op.backup_store: | |
612 | backuppath = pycompat.mkdtemp( |
|
623 | backuppath = pycompat.mkdtemp( | |
613 | prefix=b'upgradebackup.', dir=srcrepo.path |
|
624 | prefix=b'upgradebackup.', dir=srcrepo.path | |
614 | ) |
|
625 | ) | |
615 | ui.status(_(b'replaced files will be backed up at %s\n') % backuppath) |
|
626 | ui.status(_(b'replaced files will be backed up at %s\n') % backuppath) | |
616 | backupvfs = vfsmod.vfs(backuppath) |
|
627 | backupvfs = vfsmod.vfs(backuppath) | |
617 | util.copyfile( |
|
628 | util.copyfile( | |
618 | srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires') |
|
629 | srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires') | |
619 | ) |
|
630 | ) | |
620 | util.copyfile( |
|
631 | util.copyfile( | |
621 | srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate') |
|
632 | srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate') | |
622 | ) |
|
633 | ) | |
623 |
|
634 | |||
624 | assert srcrepo.dirstate._use_dirstate_v2 == (old == b'v2') |
|
635 | assert srcrepo.dirstate._use_dirstate_v2 == (old == b'v2') | |
625 | srcrepo.dirstate._map._use_dirstate_tree = True |
|
636 | srcrepo.dirstate._map._use_dirstate_tree = True | |
626 | srcrepo.dirstate._map.preload() |
|
637 | srcrepo.dirstate._map.preload() | |
627 | srcrepo.dirstate._use_dirstate_v2 = new == b'v2' |
|
638 | srcrepo.dirstate._use_dirstate_v2 = new == b'v2' | |
628 | srcrepo.dirstate._map._use_dirstate_v2 = srcrepo.dirstate._use_dirstate_v2 |
|
639 | srcrepo.dirstate._map._use_dirstate_v2 = srcrepo.dirstate._use_dirstate_v2 | |
629 | srcrepo.dirstate._dirty = True |
|
640 | srcrepo.dirstate._dirty = True | |
630 | srcrepo.dirstate.write(None) |
|
641 | srcrepo.dirstate.write(None) | |
631 |
|
642 | |||
632 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
|
643 | scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) |
@@ -1,707 +1,868 b'' | |||||
1 | #require serve no-reposimplestore no-chg |
|
1 | #require serve no-reposimplestore no-chg | |
2 |
|
2 | |||
3 | #testcases stream-legacy stream-bundle2 |
|
3 | #testcases stream-legacy stream-bundle2 | |
4 |
|
4 | |||
5 | #if stream-legacy |
|
5 | #if stream-legacy | |
6 | $ cat << EOF >> $HGRCPATH |
|
6 | $ cat << EOF >> $HGRCPATH | |
7 | > [server] |
|
7 | > [server] | |
8 | > bundle2.stream = no |
|
8 | > bundle2.stream = no | |
9 | > EOF |
|
9 | > EOF | |
10 | #endif |
|
10 | #endif | |
11 |
|
11 | |||
12 | Initialize repository |
|
12 | Initialize repository | |
13 | the status call is to check for issue5130 |
|
13 | the status call is to check for issue5130 | |
14 |
|
14 | |||
15 | $ hg init server |
|
15 | $ hg init server | |
16 | $ cd server |
|
16 | $ cd server | |
17 | $ touch foo |
|
17 | $ touch foo | |
18 | $ hg -q commit -A -m initial |
|
18 | $ hg -q commit -A -m initial | |
19 | >>> for i in range(1024): |
|
19 | >>> for i in range(1024): | |
20 | ... with open(str(i), 'wb') as fh: |
|
20 | ... with open(str(i), 'wb') as fh: | |
21 | ... fh.write(b"%d" % i) and None |
|
21 | ... fh.write(b"%d" % i) and None | |
22 | $ hg -q commit -A -m 'add a lot of files' |
|
22 | $ hg -q commit -A -m 'add a lot of files' | |
23 | $ hg st |
|
23 | $ hg st | |
|
24 | ||||
|
25 | add files with "tricky" name: | |||
|
26 | ||||
|
27 | $ echo foo > 00changelog.i | |||
|
28 | $ echo foo > 00changelog.d | |||
|
29 | $ echo foo > 00changelog.n | |||
|
30 | $ echo foo > 00changelog-ab349180a0405010.nd | |||
|
31 | $ echo foo > 00manifest.i | |||
|
32 | $ echo foo > 00manifest.d | |||
|
33 | $ echo foo > foo.i | |||
|
34 | $ echo foo > foo.d | |||
|
35 | $ echo foo > foo.n | |||
|
36 | $ echo foo > undo.py | |||
|
37 | $ echo foo > undo.i | |||
|
38 | $ echo foo > undo.d | |||
|
39 | $ echo foo > undo.n | |||
|
40 | $ echo foo > undo.foo.i | |||
|
41 | $ echo foo > undo.foo.d | |||
|
42 | $ echo foo > undo.foo.n | |||
|
43 | $ echo foo > undo.babar | |||
|
44 | $ mkdir savanah | |||
|
45 | $ echo foo > savanah/foo.i | |||
|
46 | $ echo foo > savanah/foo.d | |||
|
47 | $ echo foo > savanah/foo.n | |||
|
48 | $ echo foo > savanah/undo.py | |||
|
49 | $ echo foo > savanah/undo.i | |||
|
50 | $ echo foo > savanah/undo.d | |||
|
51 | $ echo foo > savanah/undo.n | |||
|
52 | $ echo foo > savanah/undo.foo.i | |||
|
53 | $ echo foo > savanah/undo.foo.d | |||
|
54 | $ echo foo > savanah/undo.foo.n | |||
|
55 | $ echo foo > savanah/undo.babar | |||
|
56 | $ mkdir data | |||
|
57 | $ echo foo > data/foo.i | |||
|
58 | $ echo foo > data/foo.d | |||
|
59 | $ echo foo > data/foo.n | |||
|
60 | $ echo foo > data/undo.py | |||
|
61 | $ echo foo > data/undo.i | |||
|
62 | $ echo foo > data/undo.d | |||
|
63 | $ echo foo > data/undo.n | |||
|
64 | $ echo foo > data/undo.foo.i | |||
|
65 | $ echo foo > data/undo.foo.d | |||
|
66 | $ echo foo > data/undo.foo.n | |||
|
67 | $ echo foo > data/undo.babar | |||
|
68 | $ mkdir meta | |||
|
69 | $ echo foo > meta/foo.i | |||
|
70 | $ echo foo > meta/foo.d | |||
|
71 | $ echo foo > meta/foo.n | |||
|
72 | $ echo foo > meta/undo.py | |||
|
73 | $ echo foo > meta/undo.i | |||
|
74 | $ echo foo > meta/undo.d | |||
|
75 | $ echo foo > meta/undo.n | |||
|
76 | $ echo foo > meta/undo.foo.i | |||
|
77 | $ echo foo > meta/undo.foo.d | |||
|
78 | $ echo foo > meta/undo.foo.n | |||
|
79 | $ echo foo > meta/undo.babar | |||
|
80 | $ mkdir store | |||
|
81 | $ echo foo > store/foo.i | |||
|
82 | $ echo foo > store/foo.d | |||
|
83 | $ echo foo > store/foo.n | |||
|
84 | $ echo foo > store/undo.py | |||
|
85 | $ echo foo > store/undo.i | |||
|
86 | $ echo foo > store/undo.d | |||
|
87 | $ echo foo > store/undo.n | |||
|
88 | $ echo foo > store/undo.foo.i | |||
|
89 | $ echo foo > store/undo.foo.d | |||
|
90 | $ echo foo > store/undo.foo.n | |||
|
91 | $ echo foo > store/undo.babar | |||
|
92 | $ hg add . | |||
|
93 | adding 00changelog-ab349180a0405010.nd | |||
|
94 | adding 00changelog.d | |||
|
95 | adding 00changelog.i | |||
|
96 | adding 00changelog.n | |||
|
97 | adding 00manifest.d | |||
|
98 | adding 00manifest.i | |||
|
99 | adding data/foo.d | |||
|
100 | adding data/foo.i | |||
|
101 | adding data/foo.n | |||
|
102 | adding data/undo.babar | |||
|
103 | adding data/undo.d | |||
|
104 | adding data/undo.foo.d | |||
|
105 | adding data/undo.foo.i | |||
|
106 | adding data/undo.foo.n | |||
|
107 | adding data/undo.i | |||
|
108 | adding data/undo.n | |||
|
109 | adding data/undo.py | |||
|
110 | adding foo.d | |||
|
111 | adding foo.i | |||
|
112 | adding foo.n | |||
|
113 | adding meta/foo.d | |||
|
114 | adding meta/foo.i | |||
|
115 | adding meta/foo.n | |||
|
116 | adding meta/undo.babar | |||
|
117 | adding meta/undo.d | |||
|
118 | adding meta/undo.foo.d | |||
|
119 | adding meta/undo.foo.i | |||
|
120 | adding meta/undo.foo.n | |||
|
121 | adding meta/undo.i | |||
|
122 | adding meta/undo.n | |||
|
123 | adding meta/undo.py | |||
|
124 | adding savanah/foo.d | |||
|
125 | adding savanah/foo.i | |||
|
126 | adding savanah/foo.n | |||
|
127 | adding savanah/undo.babar | |||
|
128 | adding savanah/undo.d | |||
|
129 | adding savanah/undo.foo.d | |||
|
130 | adding savanah/undo.foo.i | |||
|
131 | adding savanah/undo.foo.n | |||
|
132 | adding savanah/undo.i | |||
|
133 | adding savanah/undo.n | |||
|
134 | adding savanah/undo.py | |||
|
135 | adding store/foo.d | |||
|
136 | adding store/foo.i | |||
|
137 | adding store/foo.n | |||
|
138 | adding store/undo.babar | |||
|
139 | adding store/undo.d | |||
|
140 | adding store/undo.foo.d | |||
|
141 | adding store/undo.foo.i | |||
|
142 | adding store/undo.foo.n | |||
|
143 | adding store/undo.i | |||
|
144 | adding store/undo.n | |||
|
145 | adding store/undo.py | |||
|
146 | adding undo.babar | |||
|
147 | adding undo.d | |||
|
148 | adding undo.foo.d | |||
|
149 | adding undo.foo.i | |||
|
150 | adding undo.foo.n | |||
|
151 | adding undo.i | |||
|
152 | adding undo.n | |||
|
153 | adding undo.py | |||
|
154 | $ hg ci -m 'add files with "tricky" name' | |||
24 | $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid |
|
155 | $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid | |
25 | $ cat hg.pid > $DAEMON_PIDS |
|
156 | $ cat hg.pid > $DAEMON_PIDS | |
26 | $ cd .. |
|
157 | $ cd .. | |
27 |
|
158 | |||
28 | Cannot stream clone when server.uncompressed is set |
|
159 | Cannot stream clone when server.uncompressed is set | |
29 |
|
160 | |||
30 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out' |
|
161 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out' | |
31 | 200 Script output follows |
|
162 | 200 Script output follows | |
32 |
|
163 | |||
33 | 1 |
|
164 | 1 | |
34 |
|
165 | |||
35 | #if stream-legacy |
|
166 | #if stream-legacy | |
36 | $ hg debugcapabilities http://localhost:$HGPORT |
|
167 | $ hg debugcapabilities http://localhost:$HGPORT | |
37 | Main capabilities: |
|
168 | Main capabilities: | |
38 | batch |
|
169 | batch | |
39 | branchmap |
|
170 | branchmap | |
40 | $USUAL_BUNDLE2_CAPS_SERVER$ |
|
171 | $USUAL_BUNDLE2_CAPS_SERVER$ | |
41 | changegroupsubset |
|
172 | changegroupsubset | |
42 | compression=$BUNDLE2_COMPRESSIONS$ |
|
173 | compression=$BUNDLE2_COMPRESSIONS$ | |
43 | getbundle |
|
174 | getbundle | |
44 | httpheader=1024 |
|
175 | httpheader=1024 | |
45 | httpmediatype=0.1rx,0.1tx,0.2tx |
|
176 | httpmediatype=0.1rx,0.1tx,0.2tx | |
46 | known |
|
177 | known | |
47 | lookup |
|
178 | lookup | |
48 | pushkey |
|
179 | pushkey | |
49 | unbundle=HG10GZ,HG10BZ,HG10UN |
|
180 | unbundle=HG10GZ,HG10BZ,HG10UN | |
50 | unbundlehash |
|
181 | unbundlehash | |
51 | Bundle2 capabilities: |
|
182 | Bundle2 capabilities: | |
52 | HG20 |
|
183 | HG20 | |
53 | bookmarks |
|
184 | bookmarks | |
54 | changegroup |
|
185 | changegroup | |
55 | 01 |
|
186 | 01 | |
56 | 02 |
|
187 | 02 | |
57 | checkheads |
|
188 | checkheads | |
58 | related |
|
189 | related | |
59 | digests |
|
190 | digests | |
60 | md5 |
|
191 | md5 | |
61 | sha1 |
|
192 | sha1 | |
62 | sha512 |
|
193 | sha512 | |
63 | error |
|
194 | error | |
64 | abort |
|
195 | abort | |
65 | unsupportedcontent |
|
196 | unsupportedcontent | |
66 | pushraced |
|
197 | pushraced | |
67 | pushkey |
|
198 | pushkey | |
68 | hgtagsfnodes |
|
199 | hgtagsfnodes | |
69 | listkeys |
|
200 | listkeys | |
70 | phases |
|
201 | phases | |
71 | heads |
|
202 | heads | |
72 | pushkey |
|
203 | pushkey | |
73 | remote-changegroup |
|
204 | remote-changegroup | |
74 | http |
|
205 | http | |
75 | https |
|
206 | https | |
76 |
|
207 | |||
77 | $ hg clone --stream -U http://localhost:$HGPORT server-disabled |
|
208 | $ hg clone --stream -U http://localhost:$HGPORT server-disabled | |
78 | warning: stream clone requested but server has them disabled |
|
209 | warning: stream clone requested but server has them disabled | |
79 | requesting all changes |
|
210 | requesting all changes | |
80 | adding changesets |
|
211 | adding changesets | |
81 | adding manifests |
|
212 | adding manifests | |
82 | adding file changes |
|
213 | adding file changes | |
83 |
added |
|
214 | added 3 changesets with 1086 changes to 1086 files | |
84 |
new changesets 96ee1d7354c4: |
|
215 | new changesets 96ee1d7354c4:7406a3463c3d | |
85 |
|
216 | |||
86 |
$ |
|
217 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" | |
87 | 200 Script output follows |
|
218 | 200 Script output follows | |
88 | content-type: application/mercurial-0.2 |
|
219 | content-type: application/mercurial-0.2 | |
89 |
|
220 | |||
90 |
|
221 | |||
91 | $ f --size body --hexdump --bytes 100 |
|
222 | $ f --size body --hexdump --bytes 100 | |
92 | body: size=232 |
|
223 | body: size=232 | |
93 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
224 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
94 | 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...| |
|
225 | 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...| | |
95 | 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest| |
|
226 | 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest| | |
96 | 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques| |
|
227 | 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques| | |
97 | 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d| |
|
228 | 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d| | |
98 | 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th| |
|
229 | 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th| | |
99 | 0060: 69 73 20 66 |is f| |
|
230 | 0060: 69 73 20 66 |is f| | |
100 |
|
231 | |||
101 | #endif |
|
232 | #endif | |
102 | #if stream-bundle2 |
|
233 | #if stream-bundle2 | |
103 | $ hg debugcapabilities http://localhost:$HGPORT |
|
234 | $ hg debugcapabilities http://localhost:$HGPORT | |
104 | Main capabilities: |
|
235 | Main capabilities: | |
105 | batch |
|
236 | batch | |
106 | branchmap |
|
237 | branchmap | |
107 | $USUAL_BUNDLE2_CAPS_SERVER$ |
|
238 | $USUAL_BUNDLE2_CAPS_SERVER$ | |
108 | changegroupsubset |
|
239 | changegroupsubset | |
109 | compression=$BUNDLE2_COMPRESSIONS$ |
|
240 | compression=$BUNDLE2_COMPRESSIONS$ | |
110 | getbundle |
|
241 | getbundle | |
111 | httpheader=1024 |
|
242 | httpheader=1024 | |
112 | httpmediatype=0.1rx,0.1tx,0.2tx |
|
243 | httpmediatype=0.1rx,0.1tx,0.2tx | |
113 | known |
|
244 | known | |
114 | lookup |
|
245 | lookup | |
115 | pushkey |
|
246 | pushkey | |
116 | unbundle=HG10GZ,HG10BZ,HG10UN |
|
247 | unbundle=HG10GZ,HG10BZ,HG10UN | |
117 | unbundlehash |
|
248 | unbundlehash | |
118 | Bundle2 capabilities: |
|
249 | Bundle2 capabilities: | |
119 | HG20 |
|
250 | HG20 | |
120 | bookmarks |
|
251 | bookmarks | |
121 | changegroup |
|
252 | changegroup | |
122 | 01 |
|
253 | 01 | |
123 | 02 |
|
254 | 02 | |
124 | checkheads |
|
255 | checkheads | |
125 | related |
|
256 | related | |
126 | digests |
|
257 | digests | |
127 | md5 |
|
258 | md5 | |
128 | sha1 |
|
259 | sha1 | |
129 | sha512 |
|
260 | sha512 | |
130 | error |
|
261 | error | |
131 | abort |
|
262 | abort | |
132 | unsupportedcontent |
|
263 | unsupportedcontent | |
133 | pushraced |
|
264 | pushraced | |
134 | pushkey |
|
265 | pushkey | |
135 | hgtagsfnodes |
|
266 | hgtagsfnodes | |
136 | listkeys |
|
267 | listkeys | |
137 | phases |
|
268 | phases | |
138 | heads |
|
269 | heads | |
139 | pushkey |
|
270 | pushkey | |
140 | remote-changegroup |
|
271 | remote-changegroup | |
141 | http |
|
272 | http | |
142 | https |
|
273 | https | |
143 |
|
274 | |||
144 | $ hg clone --stream -U http://localhost:$HGPORT server-disabled |
|
275 | $ hg clone --stream -U http://localhost:$HGPORT server-disabled | |
145 | warning: stream clone requested but server has them disabled |
|
276 | warning: stream clone requested but server has them disabled | |
146 | requesting all changes |
|
277 | requesting all changes | |
147 | adding changesets |
|
278 | adding changesets | |
148 | adding manifests |
|
279 | adding manifests | |
149 | adding file changes |
|
280 | adding file changes | |
150 |
added |
|
281 | added 3 changesets with 1086 changes to 1086 files | |
151 |
new changesets 96ee1d7354c4: |
|
282 | new changesets 96ee1d7354c4:7406a3463c3d | |
152 |
|
283 | |||
153 |
$ |
|
284 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" | |
154 | 200 Script output follows |
|
285 | 200 Script output follows | |
155 | content-type: application/mercurial-0.2 |
|
286 | content-type: application/mercurial-0.2 | |
156 |
|
287 | |||
157 |
|
288 | |||
158 | $ f --size body --hexdump --bytes 100 |
|
289 | $ f --size body --hexdump --bytes 100 | |
159 | body: size=232 |
|
290 | body: size=232 | |
160 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
291 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
161 | 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...| |
|
292 | 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...| | |
162 | 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest| |
|
293 | 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest| | |
163 | 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques| |
|
294 | 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques| | |
164 | 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d| |
|
295 | 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d| | |
165 | 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th| |
|
296 | 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th| | |
166 | 0060: 69 73 20 66 |is f| |
|
297 | 0060: 69 73 20 66 |is f| | |
167 |
|
298 | |||
168 | #endif |
|
299 | #endif | |
169 |
|
300 | |||
170 | $ killdaemons.py |
|
301 | $ killdaemons.py | |
171 | $ cd server |
|
302 | $ cd server | |
172 | $ hg serve -p $HGPORT -d --pid-file=hg.pid --error errors.txt |
|
303 | $ hg serve -p $HGPORT -d --pid-file=hg.pid --error errors.txt | |
173 | $ cat hg.pid > $DAEMON_PIDS |
|
304 | $ cat hg.pid > $DAEMON_PIDS | |
174 | $ cd .. |
|
305 | $ cd .. | |
175 |
|
306 | |||
176 | Basic clone |
|
307 | Basic clone | |
177 |
|
308 | |||
178 | #if stream-legacy |
|
309 | #if stream-legacy | |
179 | $ hg clone --stream -U http://localhost:$HGPORT clone1 |
|
310 | $ hg clone --stream -U http://localhost:$HGPORT clone1 | |
180 | streaming all changes |
|
311 | streaming all changes | |
181 |
10 |
|
312 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
182 |
transferred |
|
313 | transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) | |
183 |
10 |
|
314 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
184 |
transferred 9 |
|
315 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
185 | searching for changes |
|
316 | searching for changes | |
186 | no changes found |
|
317 | no changes found | |
187 | $ cat server/errors.txt |
|
318 | $ cat server/errors.txt | |
188 | #endif |
|
319 | #endif | |
189 | #if stream-bundle2 |
|
320 | #if stream-bundle2 | |
190 | $ hg clone --stream -U http://localhost:$HGPORT clone1 |
|
321 | $ hg clone --stream -U http://localhost:$HGPORT clone1 | |
191 | streaming all changes |
|
322 | streaming all changes | |
192 |
10 |
|
323 | 1091 files to transfer, 101 KB of data (no-zstd !) | |
193 |
transferred |
|
324 | transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) | |
194 |
10 |
|
325 | 1091 files to transfer, 98.5 KB of data (zstd !) | |
195 |
transferred 9 |
|
326 | transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) | |
196 |
|
327 | |||
197 | $ ls -1 clone1/.hg/cache |
|
328 | $ ls -1 clone1/.hg/cache | |
198 | branch2-base |
|
329 | branch2-base | |
199 | branch2-immutable |
|
330 | branch2-immutable | |
200 | branch2-served |
|
331 | branch2-served | |
201 | branch2-served.hidden |
|
332 | branch2-served.hidden | |
202 | branch2-visible |
|
333 | branch2-visible | |
203 | branch2-visible-hidden |
|
334 | branch2-visible-hidden | |
204 | rbc-names-v1 |
|
335 | rbc-names-v1 | |
205 | rbc-revs-v1 |
|
336 | rbc-revs-v1 | |
206 | tags2 |
|
337 | tags2 | |
207 | tags2-served |
|
338 | tags2-served | |
208 | $ cat server/errors.txt |
|
339 | $ cat server/errors.txt | |
209 | #endif |
|
340 | #endif | |
210 |
|
341 | |||
211 | getbundle requests with stream=1 are uncompressed |
|
342 | getbundle requests with stream=1 are uncompressed | |
212 |
|
343 | |||
213 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" |
|
344 | $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" | |
214 | 200 Script output follows |
|
345 | 200 Script output follows | |
215 | content-type: application/mercurial-0.2 |
|
346 | content-type: application/mercurial-0.2 | |
216 |
|
347 | |||
217 |
|
348 | |||
218 | #if no-zstd no-rust |
|
349 | #if no-zstd no-rust | |
219 | $ f --size --hex --bytes 256 body |
|
350 | $ f --size --hex --bytes 256 body | |
220 |
body: size=11 |
|
351 | body: size=118551 | |
221 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
352 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
222 |
0010: |
|
353 | 0010: 80 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| | |
223 |
0020: 0 |
|
354 | 0020: 06 09 04 0c 44 62 79 74 65 63 6f 75 6e 74 31 30 |....Dbytecount10| | |
224 |
0030: 3 |
|
355 | 0030: 33 36 39 35 66 69 6c 65 63 6f 75 6e 74 31 30 39 |3695filecount109| | |
225 |
0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |
|
356 | 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| | |
226 |
0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |
|
357 | 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| | |
227 |
0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |
|
358 | 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| | |
228 |
0070: 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |
|
359 | 0070: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa| | |
229 |
0080: 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |
|
360 | 0080: 72 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |rserevlog%2Cstor| | |
230 |
0090: 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |
|
361 | 0090: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i| | |
231 |
00a0: 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |
|
362 | 00a0: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................| | |
232 |
00b0: 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |
|
363 | 00b0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................| | |
233 |
00c0: 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c |
|
364 | 00c0: 80 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c |.)c.I.#....Vg.g,| | |
234 |
00d0: d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 |
|
365 | 00d0: 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 |i..9............| | |
235 |
00e0: 30 73 |
|
366 | 00e0: 75 30 73 26 45 64 61 74 61 2f 30 30 63 68 61 6e |u0s&Edata/00chan| | |
236 | 00f0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................| |
|
367 | 00f0: 67 65 6c 6f 67 2d 61 62 33 34 39 31 38 30 61 30 |gelog-ab349180a0| | |
237 | #endif |
|
368 | #endif | |
238 | #if zstd no-rust |
|
369 | #if zstd no-rust | |
239 | $ f --size --hex --bytes 256 body |
|
370 | $ f --size --hex --bytes 256 body | |
240 |
body: size=1 |
|
371 | body: size=115738 | |
241 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
372 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
242 |
0010: 9 |
|
373 | 0010: 9a 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| | |
243 |
0020: 0 |
|
374 | 0020: 06 09 04 0c 5e 62 79 74 65 63 6f 75 6e 74 31 30 |....^bytecount10| | |
244 |
0030: 38 3 |
|
375 | 0030: 30 38 35 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0856filecount109| | |
245 |
0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |
|
376 | 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| | |
246 |
0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |
|
377 | 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| | |
247 |
0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |
|
378 | 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| | |
248 |
0070: 43 72 65 76 6c 6f 67 2d 63 6f 6d 70 72 65 73 |
|
379 | 0070: 32 43 72 65 76 6c 6f 67 2d 63 6f 6d 70 72 65 73 |2Crevlog-compres| | |
249 |
0080: 69 6f 6e 2d 7a 73 74 64 25 32 43 72 65 76 6c |
|
380 | 0080: 73 69 6f 6e 2d 7a 73 74 64 25 32 43 72 65 76 6c |sion-zstd%2Crevl| | |
250 |
0090: 67 76 31 25 32 43 73 70 61 72 73 65 72 65 76 |
|
381 | 0090: 6f 67 76 31 25 32 43 73 70 61 72 73 65 72 65 76 |ogv1%2Csparserev| | |
251 |
00a0: 6f 67 25 32 43 73 74 6f 72 65 00 00 80 00 73 |
|
382 | 00a0: 6c 6f 67 25 32 43 73 74 6f 72 65 00 00 80 00 73 |log%2Cstore....s| | |
252 |
00b0: 42 64 61 74 61 2f 30 2e 69 00 03 00 01 00 00 |
|
383 | 00b0: 08 42 64 61 74 61 2f 30 2e 69 00 03 00 01 00 00 |.Bdata/0.i......| | |
253 |
00c0: 00 00 00 00 02 00 00 00 01 00 00 00 00 00 00 |
|
384 | 00c0: 00 00 00 00 00 02 00 00 00 01 00 00 00 00 00 00 |................| | |
254 |
00d0: 01 ff ff ff ff ff ff ff ff 80 29 63 a0 49 d3 |
|
385 | 00d0: 00 01 ff ff ff ff ff ff ff ff 80 29 63 a0 49 d3 |...........)c.I.| | |
255 |
00e0: 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 00 00 |
|
386 | 00e0: 23 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 00 00 |#....Vg.g,i..9..| | |
256 |
00f0: 00 00 00 00 00 00 00 00 00 75 30 73 |
|
387 | 00f0: 00 00 00 00 00 00 00 00 00 00 75 30 73 26 45 64 |..........u0s&Ed| | |
257 | #endif |
|
388 | #endif | |
258 | #if zstd rust no-dirstate-v2 |
|
389 | #if zstd rust no-dirstate-v2 | |
259 | $ f --size --hex --bytes 256 body |
|
390 | $ f --size --hex --bytes 256 body | |
260 |
body: size=1 |
|
391 | body: size=115759 | |
261 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
392 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
262 |
0010: a |
|
393 | 0010: af 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| | |
263 |
0020: 0 |
|
394 | 0020: 06 09 04 0c 73 62 79 74 65 63 6f 75 6e 74 31 30 |....sbytecount10| | |
264 |
0030: 38 3 |
|
395 | 0030: 30 38 35 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0856filecount109| | |
265 |
0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |
|
396 | 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| | |
266 |
0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |
|
397 | 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| | |
267 |
0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |
|
398 | 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| | |
268 |
0070: 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f 64 |
|
399 | 0070: 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f 64 |2Cpersistent-nod| | |
269 |
0080: 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 6f |
|
400 | 0080: 65 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 6f |emap%2Crevlog-co| | |
270 |
0090: 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 32 |
|
401 | 0090: 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 32 |mpression-zstd%2| | |
271 |
00a0: 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 72 |
|
402 | 00a0: 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 72 |Crevlogv1%2Cspar| | |
272 |
00b0: 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 65 |
|
403 | 00b0: 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 65 |serevlog%2Cstore| | |
273 |
00c0: 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 00 |
|
404 | 00c0: 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 00 |....s.Bdata/0.i.| | |
274 |
00d0: 00 01 00 00 00 00 00 00 00 02 00 00 00 01 00 |
|
405 | 00d0: 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 00 |................| | |
275 |
00e0: 00 00 00 00 00 01 ff ff ff ff ff ff ff ff 80 |
|
406 | 00e0: 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff 80 |................| | |
276 |
00f0: 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 |
|
407 | 00f0: 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 |)c.I.#....Vg.g,i| | |
277 | #endif |
|
408 | #endif | |
278 | #if zstd dirstate-v2 |
|
409 | #if zstd dirstate-v2 | |
279 | $ f --size --hex --bytes 256 body |
|
410 | $ f --size --hex --bytes 256 body | |
280 | body: size=109449 |
|
411 | body: size=109449 | |
281 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| |
|
412 | 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| | |
282 | 0010: c0 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| |
|
413 | 0010: c0 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| | |
283 | 0020: 05 09 04 0c 85 62 79 74 65 63 6f 75 6e 74 39 35 |.....bytecount95| |
|
414 | 0020: 05 09 04 0c 85 62 79 74 65 63 6f 75 6e 74 39 35 |.....bytecount95| | |
284 | 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030| |
|
415 | 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030| | |
285 | 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote| |
|
416 | 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote| | |
286 | 0050: 6e 63 6f 64 65 25 32 43 65 78 70 2d 64 69 72 73 |ncode%2Cexp-dirs| |
|
417 | 0050: 6e 63 6f 64 65 25 32 43 65 78 70 2d 64 69 72 73 |ncode%2Cexp-dirs| | |
287 | 0060: 74 61 74 65 2d 76 32 25 32 43 66 6e 63 61 63 68 |tate-v2%2Cfncach| |
|
418 | 0060: 74 61 74 65 2d 76 32 25 32 43 66 6e 63 61 63 68 |tate-v2%2Cfncach| | |
288 | 0070: 65 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 |e%2Cgeneraldelta| |
|
419 | 0070: 65 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 |e%2Cgeneraldelta| | |
289 | 0080: 25 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f |%2Cpersistent-no| |
|
420 | 0080: 25 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f |%2Cpersistent-no| | |
290 | 0090: 64 65 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 |demap%2Crevlog-c| |
|
421 | 0090: 64 65 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 |demap%2Crevlog-c| | |
291 | 00a0: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 |ompression-zstd%| |
|
422 | 00a0: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 |ompression-zstd%| | |
292 | 00b0: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa| |
|
423 | 00b0: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa| | |
293 | 00c0: 72 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |rserevlog%2Cstor| |
|
424 | 00c0: 72 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |rserevlog%2Cstor| | |
294 | 00d0: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i| |
|
425 | 00d0: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i| | |
295 | 00e0: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................| |
|
426 | 00e0: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................| | |
296 | 00f0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................| |
|
427 | 00f0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................| | |
297 | #endif |
|
428 | #endif | |
298 |
|
429 | |||
299 | --uncompressed is an alias to --stream |
|
430 | --uncompressed is an alias to --stream | |
300 |
|
431 | |||
301 | #if stream-legacy |
|
432 | #if stream-legacy | |
302 | $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed |
|
433 | $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed | |
303 | streaming all changes |
|
434 | streaming all changes | |
304 |
10 |
|
435 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
305 |
transferred |
|
436 | transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) | |
306 |
10 |
|
437 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
307 |
transferred 9 |
|
438 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
308 | searching for changes |
|
439 | searching for changes | |
309 | no changes found |
|
440 | no changes found | |
310 | #endif |
|
441 | #endif | |
311 | #if stream-bundle2 |
|
442 | #if stream-bundle2 | |
312 | $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed |
|
443 | $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed | |
313 | streaming all changes |
|
444 | streaming all changes | |
314 |
10 |
|
445 | 1091 files to transfer, 101 KB of data (no-zstd !) | |
315 |
transferred |
|
446 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
316 |
10 |
|
447 | 1091 files to transfer, 98.5 KB of data (zstd !) | |
317 |
transferred 9 |
|
448 | transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) | |
318 | #endif |
|
449 | #endif | |
319 |
|
450 | |||
320 | Clone with background file closing enabled |
|
451 | Clone with background file closing enabled | |
321 |
|
452 | |||
322 | #if stream-legacy |
|
453 | #if stream-legacy | |
323 | $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding |
|
454 | $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding | |
324 | using http://localhost:$HGPORT/ |
|
455 | using http://localhost:$HGPORT/ | |
325 | sending capabilities command |
|
456 | sending capabilities command | |
326 | sending branchmap command |
|
457 | sending branchmap command | |
327 | streaming all changes |
|
458 | streaming all changes | |
328 | sending stream_out command |
|
459 | sending stream_out command | |
329 |
10 |
|
460 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
330 |
10 |
|
461 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
331 | starting 4 threads for background file closing |
|
462 | starting 4 threads for background file closing | |
332 | updating the branch cache |
|
463 | updating the branch cache | |
333 |
transferred |
|
464 | transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) | |
334 |
transferred 9 |
|
465 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
335 | query 1; heads |
|
466 | query 1; heads | |
336 | sending batch command |
|
467 | sending batch command | |
337 | searching for changes |
|
468 | searching for changes | |
338 | all remote heads known locally |
|
469 | all remote heads known locally | |
339 | no changes found |
|
470 | no changes found | |
340 | sending getbundle command |
|
471 | sending getbundle command | |
341 | bundle2-input-bundle: with-transaction |
|
472 | bundle2-input-bundle: with-transaction | |
342 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported |
|
473 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported | |
343 | bundle2-input-part: "phase-heads" supported |
|
474 | bundle2-input-part: "phase-heads" supported | |
344 | bundle2-input-part: total payload size 24 |
|
475 | bundle2-input-part: total payload size 24 | |
345 | bundle2-input-bundle: 2 parts total |
|
476 | bundle2-input-bundle: 2 parts total | |
346 | checking for updated bookmarks |
|
477 | checking for updated bookmarks | |
347 | updating the branch cache |
|
478 | updating the branch cache | |
348 | (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob) |
|
479 | (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob) | |
349 | #endif |
|
480 | #endif | |
350 | #if stream-bundle2 |
|
481 | #if stream-bundle2 | |
351 | $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding |
|
482 | $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding | |
352 | using http://localhost:$HGPORT/ |
|
483 | using http://localhost:$HGPORT/ | |
353 | sending capabilities command |
|
484 | sending capabilities command | |
354 | query 1; heads |
|
485 | query 1; heads | |
355 | sending batch command |
|
486 | sending batch command | |
356 | streaming all changes |
|
487 | streaming all changes | |
357 | sending getbundle command |
|
488 | sending getbundle command | |
358 | bundle2-input-bundle: with-transaction |
|
489 | bundle2-input-bundle: with-transaction | |
359 | bundle2-input-part: "stream2" (params: 3 mandatory) supported |
|
490 | bundle2-input-part: "stream2" (params: 3 mandatory) supported | |
360 | applying stream bundle |
|
491 | applying stream bundle | |
361 |
10 |
|
492 | 1091 files to transfer, 101 KB of data (no-zstd !) | |
362 |
10 |
|
493 | 1091 files to transfer, 98.5 KB of data (zstd !) | |
363 | starting 4 threads for background file closing |
|
494 | starting 4 threads for background file closing | |
364 | starting 4 threads for background file closing |
|
495 | starting 4 threads for background file closing | |
365 | updating the branch cache |
|
496 | updating the branch cache | |
366 |
transferred |
|
497 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
367 |
bundle2-input-part: total payload size 112 |
|
498 | bundle2-input-part: total payload size 118382 (no-zstd !) | |
368 |
transferred 9 |
|
499 | transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) | |
369 |
bundle2-input-part: total payload size 1 |
|
500 | bundle2-input-part: total payload size 115543 (zstd !) | |
370 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported |
|
501 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported | |
371 | bundle2-input-bundle: 2 parts total |
|
502 | bundle2-input-bundle: 2 parts total | |
372 | checking for updated bookmarks |
|
503 | checking for updated bookmarks | |
373 | updating the branch cache |
|
504 | updating the branch cache | |
374 | (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob) |
|
505 | (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob) | |
375 | #endif |
|
506 | #endif | |
376 |
|
507 | |||
377 | Cannot stream clone when there are secret changesets |
|
508 | Cannot stream clone when there are secret changesets | |
378 |
|
509 | |||
379 | $ hg -R server phase --force --secret -r tip |
|
510 | $ hg -R server phase --force --secret -r tip | |
380 | $ hg clone --stream -U http://localhost:$HGPORT secret-denied |
|
511 | $ hg clone --stream -U http://localhost:$HGPORT secret-denied | |
381 | warning: stream clone requested but server has them disabled |
|
512 | warning: stream clone requested but server has them disabled | |
382 | requesting all changes |
|
513 | requesting all changes | |
383 | adding changesets |
|
514 | adding changesets | |
384 | adding manifests |
|
515 | adding manifests | |
385 | adding file changes |
|
516 | adding file changes | |
386 |
added |
|
517 | added 2 changesets with 1025 changes to 1025 files | |
387 | new changesets 96ee1d7354c4 |
|
518 | new changesets 96ee1d7354c4:c17445101a72 | |
388 |
|
519 | |||
389 | $ killdaemons.py |
|
520 | $ killdaemons.py | |
390 |
|
521 | |||
391 | Streaming of secrets can be overridden by server config |
|
522 | Streaming of secrets can be overridden by server config | |
392 |
|
523 | |||
393 | $ cd server |
|
524 | $ cd server | |
394 | $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid |
|
525 | $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid | |
395 | $ cat hg.pid > $DAEMON_PIDS |
|
526 | $ cat hg.pid > $DAEMON_PIDS | |
396 | $ cd .. |
|
527 | $ cd .. | |
397 |
|
528 | |||
398 | #if stream-legacy |
|
529 | #if stream-legacy | |
399 | $ hg clone --stream -U http://localhost:$HGPORT secret-allowed |
|
530 | $ hg clone --stream -U http://localhost:$HGPORT secret-allowed | |
400 | streaming all changes |
|
531 | streaming all changes | |
401 |
10 |
|
532 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
402 |
transferred |
|
533 | transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) | |
403 |
10 |
|
534 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
404 |
transferred 9 |
|
535 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
405 | searching for changes |
|
536 | searching for changes | |
406 | no changes found |
|
537 | no changes found | |
407 | #endif |
|
538 | #endif | |
408 | #if stream-bundle2 |
|
539 | #if stream-bundle2 | |
409 | $ hg clone --stream -U http://localhost:$HGPORT secret-allowed |
|
540 | $ hg clone --stream -U http://localhost:$HGPORT secret-allowed | |
410 | streaming all changes |
|
541 | streaming all changes | |
411 |
10 |
|
542 | 1091 files to transfer, 101 KB of data (no-zstd !) | |
412 |
transferred |
|
543 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
413 |
10 |
|
544 | 1091 files to transfer, 98.5 KB of data (zstd !) | |
414 |
transferred 9 |
|
545 | transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) | |
415 | #endif |
|
546 | #endif | |
416 |
|
547 | |||
417 | $ killdaemons.py |
|
548 | $ killdaemons.py | |
418 |
|
549 | |||
419 | Verify interaction between preferuncompressed and secret presence |
|
550 | Verify interaction between preferuncompressed and secret presence | |
420 |
|
551 | |||
421 | $ cd server |
|
552 | $ cd server | |
422 | $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid |
|
553 | $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid | |
423 | $ cat hg.pid > $DAEMON_PIDS |
|
554 | $ cat hg.pid > $DAEMON_PIDS | |
424 | $ cd .. |
|
555 | $ cd .. | |
425 |
|
556 | |||
426 | $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret |
|
557 | $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret | |
427 | requesting all changes |
|
558 | requesting all changes | |
428 | adding changesets |
|
559 | adding changesets | |
429 | adding manifests |
|
560 | adding manifests | |
430 | adding file changes |
|
561 | adding file changes | |
431 |
added |
|
562 | added 2 changesets with 1025 changes to 1025 files | |
432 | new changesets 96ee1d7354c4 |
|
563 | new changesets 96ee1d7354c4:c17445101a72 | |
433 |
|
564 | |||
434 | $ killdaemons.py |
|
565 | $ killdaemons.py | |
435 |
|
566 | |||
436 | Clone not allowed when full bundles disabled and can't serve secrets |
|
567 | Clone not allowed when full bundles disabled and can't serve secrets | |
437 |
|
568 | |||
438 | $ cd server |
|
569 | $ cd server | |
439 | $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid |
|
570 | $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid | |
440 | $ cat hg.pid > $DAEMON_PIDS |
|
571 | $ cat hg.pid > $DAEMON_PIDS | |
441 | $ cd .. |
|
572 | $ cd .. | |
442 |
|
573 | |||
443 | $ hg clone --stream http://localhost:$HGPORT secret-full-disabled |
|
574 | $ hg clone --stream http://localhost:$HGPORT secret-full-disabled | |
444 | warning: stream clone requested but server has them disabled |
|
575 | warning: stream clone requested but server has them disabled | |
445 | requesting all changes |
|
576 | requesting all changes | |
446 | remote: abort: server has pull-based clones disabled |
|
577 | remote: abort: server has pull-based clones disabled | |
447 | abort: pull failed on remote |
|
578 | abort: pull failed on remote | |
448 | (remove --pull if specified or upgrade Mercurial) |
|
579 | (remove --pull if specified or upgrade Mercurial) | |
449 | [100] |
|
580 | [100] | |
450 |
|
581 | |||
451 | Local stream clone with secrets involved |
|
582 | Local stream clone with secrets involved | |
452 | (This is just a test over behavior: if you have access to the repo's files, |
|
583 | (This is just a test over behavior: if you have access to the repo's files, | |
453 | there is no security so it isn't important to prevent a clone here.) |
|
584 | there is no security so it isn't important to prevent a clone here.) | |
454 |
|
585 | |||
455 | $ hg clone -U --stream server local-secret |
|
586 | $ hg clone -U --stream server local-secret | |
456 | warning: stream clone requested but server has them disabled |
|
587 | warning: stream clone requested but server has them disabled | |
457 | requesting all changes |
|
588 | requesting all changes | |
458 | adding changesets |
|
589 | adding changesets | |
459 | adding manifests |
|
590 | adding manifests | |
460 | adding file changes |
|
591 | adding file changes | |
461 |
added |
|
592 | added 2 changesets with 1025 changes to 1025 files | |
462 | new changesets 96ee1d7354c4 |
|
593 | new changesets 96ee1d7354c4:c17445101a72 | |
463 |
|
594 | |||
464 | Stream clone while repo is changing: |
|
595 | Stream clone while repo is changing: | |
465 |
|
596 | |||
466 | $ mkdir changing |
|
597 | $ mkdir changing | |
467 | $ cd changing |
|
598 | $ cd changing | |
468 |
|
599 | |||
469 | extension for delaying the server process so we reliably can modify the repo |
|
600 | extension for delaying the server process so we reliably can modify the repo | |
470 | while cloning |
|
601 | while cloning | |
471 |
|
602 | |||
472 | $ cat > stream_steps.py <<EOF |
|
603 | $ cat > stream_steps.py <<EOF | |
473 | > import os |
|
604 | > import os | |
474 | > import sys |
|
605 | > import sys | |
475 | > from mercurial import ( |
|
606 | > from mercurial import ( | |
476 | > encoding, |
|
607 | > encoding, | |
477 | > extensions, |
|
608 | > extensions, | |
478 | > streamclone, |
|
609 | > streamclone, | |
479 | > testing, |
|
610 | > testing, | |
480 | > ) |
|
611 | > ) | |
481 | > WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1'] |
|
612 | > WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1'] | |
482 | > WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2'] |
|
613 | > WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2'] | |
483 | > |
|
614 | > | |
484 | > def _test_sync_point_walk_1(orig, repo): |
|
615 | > def _test_sync_point_walk_1(orig, repo): | |
485 | > testing.write_file(WALKED_FILE_1) |
|
616 | > testing.write_file(WALKED_FILE_1) | |
486 | > |
|
617 | > | |
487 | > def _test_sync_point_walk_2(orig, repo): |
|
618 | > def _test_sync_point_walk_2(orig, repo): | |
488 | > assert repo._currentlock(repo._lockref) is None |
|
619 | > assert repo._currentlock(repo._lockref) is None | |
489 | > testing.wait_file(WALKED_FILE_2) |
|
620 | > testing.wait_file(WALKED_FILE_2) | |
490 | > |
|
621 | > | |
491 | > extensions.wrapfunction( |
|
622 | > extensions.wrapfunction( | |
492 | > streamclone, |
|
623 | > streamclone, | |
493 | > '_test_sync_point_walk_1', |
|
624 | > '_test_sync_point_walk_1', | |
494 | > _test_sync_point_walk_1 |
|
625 | > _test_sync_point_walk_1 | |
495 | > ) |
|
626 | > ) | |
496 | > extensions.wrapfunction( |
|
627 | > extensions.wrapfunction( | |
497 | > streamclone, |
|
628 | > streamclone, | |
498 | > '_test_sync_point_walk_2', |
|
629 | > '_test_sync_point_walk_2', | |
499 | > _test_sync_point_walk_2 |
|
630 | > _test_sync_point_walk_2 | |
500 | > ) |
|
631 | > ) | |
501 | > EOF |
|
632 | > EOF | |
502 |
|
633 | |||
503 | prepare repo with small and big file to cover both code paths in emitrevlogdata |
|
634 | prepare repo with small and big file to cover both code paths in emitrevlogdata | |
504 |
|
635 | |||
505 | $ hg init repo |
|
636 | $ hg init repo | |
506 | $ touch repo/f1 |
|
637 | $ touch repo/f1 | |
507 | $ $TESTDIR/seq.py 50000 > repo/f2 |
|
638 | $ $TESTDIR/seq.py 50000 > repo/f2 | |
508 | $ hg -R repo ci -Aqm "0" |
|
639 | $ hg -R repo ci -Aqm "0" | |
509 | $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1" |
|
640 | $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1" | |
510 | $ export HG_TEST_STREAM_WALKED_FILE_1 |
|
641 | $ export HG_TEST_STREAM_WALKED_FILE_1 | |
511 | $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2" |
|
642 | $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2" | |
512 | $ export HG_TEST_STREAM_WALKED_FILE_2 |
|
643 | $ export HG_TEST_STREAM_WALKED_FILE_2 | |
513 | $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3" |
|
644 | $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3" | |
514 | $ export HG_TEST_STREAM_WALKED_FILE_3 |
|
645 | $ export HG_TEST_STREAM_WALKED_FILE_3 | |
515 | # $ cat << EOF >> $HGRCPATH |
|
646 | # $ cat << EOF >> $HGRCPATH | |
516 | # > [hooks] |
|
647 | # > [hooks] | |
517 | # > pre-clone=rm -f "$TESTTMP/sync_file_walked_*" |
|
648 | # > pre-clone=rm -f "$TESTTMP/sync_file_walked_*" | |
518 | # > EOF |
|
649 | # > EOF | |
519 | $ hg serve -R repo -p $HGPORT1 -d --error errors.log --pid-file=hg.pid --config extensions.stream_steps="$RUNTESTDIR/testlib/ext-stream-clone-steps.py" |
|
650 | $ hg serve -R repo -p $HGPORT1 -d --error errors.log --pid-file=hg.pid --config extensions.stream_steps="$RUNTESTDIR/testlib/ext-stream-clone-steps.py" | |
520 | $ cat hg.pid >> $DAEMON_PIDS |
|
651 | $ cat hg.pid >> $DAEMON_PIDS | |
521 |
|
652 | |||
522 | clone while modifying the repo between stating file with write lock and |
|
653 | clone while modifying the repo between stating file with write lock and | |
523 | actually serving file content |
|
654 | actually serving file content | |
524 |
|
655 | |||
525 | $ (hg clone -q --stream -U http://localhost:$HGPORT1 clone; touch "$HG_TEST_STREAM_WALKED_FILE_3") & |
|
656 | $ (hg clone -q --stream -U http://localhost:$HGPORT1 clone; touch "$HG_TEST_STREAM_WALKED_FILE_3") & | |
526 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 |
|
657 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 | |
527 | $ echo >> repo/f1 |
|
658 | $ echo >> repo/f1 | |
528 | $ echo >> repo/f2 |
|
659 | $ echo >> repo/f2 | |
529 | $ hg -R repo ci -m "1" --config ui.timeout.warn=-1 |
|
660 | $ hg -R repo ci -m "1" --config ui.timeout.warn=-1 | |
530 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 |
|
661 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 | |
531 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 |
|
662 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 | |
532 | $ hg -R clone id |
|
663 | $ hg -R clone id | |
533 | 000000000000 |
|
664 | 000000000000 | |
534 | $ cat errors.log |
|
665 | $ cat errors.log | |
535 | $ cd .. |
|
666 | $ cd .. | |
536 |
|
667 | |||
537 | Stream repository with bookmarks |
|
668 | Stream repository with bookmarks | |
538 | -------------------------------- |
|
669 | -------------------------------- | |
539 |
|
670 | |||
540 | (revert introduction of secret changeset) |
|
671 | (revert introduction of secret changeset) | |
541 |
|
672 | |||
542 | $ hg -R server phase --draft 'secret()' |
|
673 | $ hg -R server phase --draft 'secret()' | |
543 |
|
674 | |||
544 | add a bookmark |
|
675 | add a bookmark | |
545 |
|
676 | |||
546 | $ hg -R server bookmark -r tip some-bookmark |
|
677 | $ hg -R server bookmark -r tip some-bookmark | |
547 |
|
678 | |||
548 | clone it |
|
679 | clone it | |
549 |
|
680 | |||
550 | #if stream-legacy |
|
681 | #if stream-legacy | |
551 | $ hg clone --stream http://localhost:$HGPORT with-bookmarks |
|
682 | $ hg clone --stream http://localhost:$HGPORT with-bookmarks | |
552 | streaming all changes |
|
683 | streaming all changes | |
553 |
10 |
|
684 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
554 |
transferred |
|
685 | transferred 101 KB in * seconds (*) (glob) (no-zstd !) | |
555 |
10 |
|
686 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
556 |
transferred 9 |
|
687 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
557 | searching for changes |
|
688 | searching for changes | |
558 | no changes found |
|
689 | no changes found | |
559 | updating to branch default |
|
690 | updating to branch default | |
560 |
10 |
|
691 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
561 | #endif |
|
692 | #endif | |
562 | #if stream-bundle2 |
|
693 | #if stream-bundle2 | |
563 | $ hg clone --stream http://localhost:$HGPORT with-bookmarks |
|
694 | $ hg clone --stream http://localhost:$HGPORT with-bookmarks | |
564 | streaming all changes |
|
695 | streaming all changes | |
565 |
10 |
|
696 | 1094 files to transfer, 101 KB of data (no-zstd !) | |
566 |
transferred |
|
697 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
567 |
10 |
|
698 | 1094 files to transfer, 98.7 KB of data (zstd !) | |
568 |
transferred 9 |
|
699 | transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) | |
569 | updating to branch default |
|
700 | updating to branch default | |
570 |
10 |
|
701 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
571 | #endif |
|
702 | #endif | |
|
703 | $ hg verify -R with-bookmarks | |||
|
704 | checking changesets | |||
|
705 | checking manifests | |||
|
706 | crosschecking files in changesets and manifests | |||
|
707 | checking files | |||
|
708 | checked 3 changesets with 1086 changes to 1086 files | |||
572 | $ hg -R with-bookmarks bookmarks |
|
709 | $ hg -R with-bookmarks bookmarks | |
573 |
some-bookmark |
|
710 | some-bookmark 2:7406a3463c3d | |
574 |
|
711 | |||
575 | Stream repository with phases |
|
712 | Stream repository with phases | |
576 | ----------------------------- |
|
713 | ----------------------------- | |
577 |
|
714 | |||
578 | Clone as publishing |
|
715 | Clone as publishing | |
579 |
|
716 | |||
580 | $ hg -R server phase -r 'all()' |
|
717 | $ hg -R server phase -r 'all()' | |
581 | 0: draft |
|
718 | 0: draft | |
582 | 1: draft |
|
719 | 1: draft | |
|
720 | 2: draft | |||
583 |
|
721 | |||
584 | #if stream-legacy |
|
722 | #if stream-legacy | |
585 | $ hg clone --stream http://localhost:$HGPORT phase-publish |
|
723 | $ hg clone --stream http://localhost:$HGPORT phase-publish | |
586 | streaming all changes |
|
724 | streaming all changes | |
587 |
10 |
|
725 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
588 |
transferred |
|
726 | transferred 101 KB in * seconds (*) (glob) (no-zstd !) | |
589 |
10 |
|
727 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
590 |
transferred 9 |
|
728 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
591 | searching for changes |
|
729 | searching for changes | |
592 | no changes found |
|
730 | no changes found | |
593 | updating to branch default |
|
731 | updating to branch default | |
594 |
10 |
|
732 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
595 | #endif |
|
733 | #endif | |
596 | #if stream-bundle2 |
|
734 | #if stream-bundle2 | |
597 | $ hg clone --stream http://localhost:$HGPORT phase-publish |
|
735 | $ hg clone --stream http://localhost:$HGPORT phase-publish | |
598 | streaming all changes |
|
736 | streaming all changes | |
599 |
10 |
|
737 | 1094 files to transfer, 101 KB of data (no-zstd !) | |
600 |
transferred |
|
738 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
601 |
10 |
|
739 | 1094 files to transfer, 98.7 KB of data (zstd !) | |
602 |
transferred 9 |
|
740 | transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) | |
603 | updating to branch default |
|
741 | updating to branch default | |
604 |
10 |
|
742 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
605 | #endif |
|
743 | #endif | |
|
744 | $ hg verify -R phase-publish | |||
|
745 | checking changesets | |||
|
746 | checking manifests | |||
|
747 | crosschecking files in changesets and manifests | |||
|
748 | checking files | |||
|
749 | checked 3 changesets with 1086 changes to 1086 files | |||
606 | $ hg -R phase-publish phase -r 'all()' |
|
750 | $ hg -R phase-publish phase -r 'all()' | |
607 | 0: public |
|
751 | 0: public | |
608 | 1: public |
|
752 | 1: public | |
|
753 | 2: public | |||
609 |
|
754 | |||
610 | Clone as non publishing |
|
755 | Clone as non publishing | |
611 |
|
756 | |||
612 | $ cat << EOF >> server/.hg/hgrc |
|
757 | $ cat << EOF >> server/.hg/hgrc | |
613 | > [phases] |
|
758 | > [phases] | |
614 | > publish = False |
|
759 | > publish = False | |
615 | > EOF |
|
760 | > EOF | |
616 | $ killdaemons.py |
|
761 | $ killdaemons.py | |
617 | $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid |
|
762 | $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid | |
618 | $ cat hg.pid > $DAEMON_PIDS |
|
763 | $ cat hg.pid > $DAEMON_PIDS | |
619 |
|
764 | |||
620 | #if stream-legacy |
|
765 | #if stream-legacy | |
621 |
|
766 | |||
622 | With v1 of the stream protocol, changeset are always cloned as public. It make |
|
767 | With v1 of the stream protocol, changeset are always cloned as public. It make | |
623 | stream v1 unsuitable for non-publishing repository. |
|
768 | stream v1 unsuitable for non-publishing repository. | |
624 |
|
769 | |||
625 | $ hg clone --stream http://localhost:$HGPORT phase-no-publish |
|
770 | $ hg clone --stream http://localhost:$HGPORT phase-no-publish | |
626 | streaming all changes |
|
771 | streaming all changes | |
627 |
10 |
|
772 | 1088 files to transfer, 101 KB of data (no-zstd !) | |
628 |
transferred |
|
773 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
629 |
10 |
|
774 | 1088 files to transfer, 98.4 KB of data (zstd !) | |
630 |
transferred 9 |
|
775 | transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) | |
631 | searching for changes |
|
776 | searching for changes | |
632 | no changes found |
|
777 | no changes found | |
633 | updating to branch default |
|
778 | updating to branch default | |
634 |
10 |
|
779 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
635 | $ hg -R phase-no-publish phase -r 'all()' |
|
780 | $ hg -R phase-no-publish phase -r 'all()' | |
636 | 0: public |
|
781 | 0: public | |
637 | 1: public |
|
782 | 1: public | |
|
783 | 2: public | |||
638 | #endif |
|
784 | #endif | |
639 | #if stream-bundle2 |
|
785 | #if stream-bundle2 | |
640 | $ hg clone --stream http://localhost:$HGPORT phase-no-publish |
|
786 | $ hg clone --stream http://localhost:$HGPORT phase-no-publish | |
641 | streaming all changes |
|
787 | streaming all changes | |
642 |
10 |
|
788 | 1095 files to transfer, 101 KB of data (no-zstd !) | |
643 |
transferred |
|
789 | transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) | |
644 |
10 |
|
790 | 1095 files to transfer, 98.7 KB of data (zstd !) | |
645 |
transferred 9 |
|
791 | transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) | |
646 | updating to branch default |
|
792 | updating to branch default | |
647 |
10 |
|
793 | 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
648 | $ hg -R phase-no-publish phase -r 'all()' |
|
794 | $ hg -R phase-no-publish phase -r 'all()' | |
649 | 0: draft |
|
795 | 0: draft | |
650 | 1: draft |
|
796 | 1: draft | |
|
797 | 2: draft | |||
651 | #endif |
|
798 | #endif | |
|
799 | $ hg verify -R phase-no-publish | |||
|
800 | checking changesets | |||
|
801 | checking manifests | |||
|
802 | crosschecking files in changesets and manifests | |||
|
803 | checking files | |||
|
804 | checked 3 changesets with 1086 changes to 1086 files | |||
652 |
|
805 | |||
653 | $ killdaemons.py |
|
806 | $ killdaemons.py | |
654 |
|
807 | |||
655 | #if stream-legacy |
|
808 | #if stream-legacy | |
656 |
|
809 | |||
657 | With v1 of the stream protocol, changeset are always cloned as public. There's |
|
810 | With v1 of the stream protocol, changeset are always cloned as public. There's | |
658 | no obsolescence markers exchange in stream v1. |
|
811 | no obsolescence markers exchange in stream v1. | |
659 |
|
812 | |||
660 | #endif |
|
813 | #endif | |
661 | #if stream-bundle2 |
|
814 | #if stream-bundle2 | |
662 |
|
815 | |||
663 | Stream repository with obsolescence |
|
816 | Stream repository with obsolescence | |
664 | ----------------------------------- |
|
817 | ----------------------------------- | |
665 |
|
818 | |||
666 | Clone non-publishing with obsolescence |
|
819 | Clone non-publishing with obsolescence | |
667 |
|
820 | |||
668 | $ cat >> $HGRCPATH << EOF |
|
821 | $ cat >> $HGRCPATH << EOF | |
669 | > [experimental] |
|
822 | > [experimental] | |
670 | > evolution=all |
|
823 | > evolution=all | |
671 | > EOF |
|
824 | > EOF | |
672 |
|
825 | |||
673 | $ cd server |
|
826 | $ cd server | |
674 | $ echo foo > foo |
|
827 | $ echo foo > foo | |
675 | $ hg -q commit -m 'about to be pruned' |
|
828 | $ hg -q commit -m 'about to be pruned' | |
676 | $ hg debugobsolete `hg log -r . -T '{node}'` -d '0 0' -u test --record-parents |
|
829 | $ hg debugobsolete `hg log -r . -T '{node}'` -d '0 0' -u test --record-parents | |
677 | 1 new obsolescence markers |
|
830 | 1 new obsolescence markers | |
678 | obsoleted 1 changesets |
|
831 | obsoleted 1 changesets | |
679 | $ hg up null -q |
|
832 | $ hg up null -q | |
680 | $ hg log -T '{rev}: {phase}\n' |
|
833 | $ hg log -T '{rev}: {phase}\n' | |
|
834 | 2: draft | |||
681 | 1: draft |
|
835 | 1: draft | |
682 | 0: draft |
|
836 | 0: draft | |
683 | $ hg serve -p $HGPORT -d --pid-file=hg.pid |
|
837 | $ hg serve -p $HGPORT -d --pid-file=hg.pid | |
684 | $ cat hg.pid > $DAEMON_PIDS |
|
838 | $ cat hg.pid > $DAEMON_PIDS | |
685 | $ cd .. |
|
839 | $ cd .. | |
686 |
|
840 | |||
687 | $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence |
|
841 | $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence | |
688 | streaming all changes |
|
842 | streaming all changes | |
689 |
10 |
|
843 | 1096 files to transfer, 102 KB of data (no-zstd !) | |
690 |
transferred |
|
844 | transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !) | |
691 |
10 |
|
845 | 1096 files to transfer, 99.1 KB of data (zstd !) | |
692 |
transferred 9 |
|
846 | transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !) | |
693 | $ hg -R with-obsolescence log -T '{rev}: {phase}\n' |
|
847 | $ hg -R with-obsolescence log -T '{rev}: {phase}\n' | |
|
848 | 2: draft | |||
694 | 1: draft |
|
849 | 1: draft | |
695 | 0: draft |
|
850 | 0: draft | |
696 | $ hg debugobsolete -R with-obsolescence |
|
851 | $ hg debugobsolete -R with-obsolescence | |
697 | 50382b884f66690b7045cac93a540cba4d4c906f 0 {c17445101a72edac06facd130d14808dfbd5c7c2} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
852 | aa82d3f59e13f41649d8ba3324e1ac8849ba78e7 0 {7406a3463c3de22c4288b4306d199705369a285a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
|
853 | $ hg verify -R with-obsolescence | |||
|
854 | checking changesets | |||
|
855 | checking manifests | |||
|
856 | crosschecking files in changesets and manifests | |||
|
857 | checking files | |||
|
858 | checked 4 changesets with 1087 changes to 1086 files | |||
698 |
|
859 | |||
699 |
$ |
|
860 | $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution | |
700 | streaming all changes |
|
861 | streaming all changes | |
701 | remote: abort: server has obsolescence markers, but client cannot receive them via stream clone |
|
862 | remote: abort: server has obsolescence markers, but client cannot receive them via stream clone | |
702 | abort: pull failed on remote |
|
863 | abort: pull failed on remote | |
703 | [100] |
|
864 | [100] | |
704 |
|
865 | |||
705 | $ killdaemons.py |
|
866 | $ killdaemons.py | |
706 |
|
867 | |||
707 | #endif |
|
868 | #endif |
@@ -1,1062 +1,1067 b'' | |||||
1 | =================================== |
|
1 | =================================== | |
2 | Test the persistent on-disk nodemap |
|
2 | Test the persistent on-disk nodemap | |
3 | =================================== |
|
3 | =================================== | |
4 |
|
4 | |||
5 |
|
5 | |||
6 | #if no-rust |
|
6 | #if no-rust | |
7 |
|
7 | |||
8 | $ cat << EOF >> $HGRCPATH |
|
8 | $ cat << EOF >> $HGRCPATH | |
9 | > [format] |
|
9 | > [format] | |
10 | > use-persistent-nodemap=yes |
|
10 | > use-persistent-nodemap=yes | |
11 | > [devel] |
|
11 | > [devel] | |
12 | > persistent-nodemap=yes |
|
12 | > persistent-nodemap=yes | |
13 | > EOF |
|
13 | > EOF | |
14 |
|
14 | |||
15 | #endif |
|
15 | #endif | |
16 |
|
16 | |||
17 | $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow |
|
17 | $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow | |
18 | $ cd test-repo |
|
18 | $ cd test-repo | |
19 |
|
19 | |||
20 | Check handling of the default slow-path value |
|
20 | Check handling of the default slow-path value | |
21 |
|
21 | |||
22 | #if no-pure no-rust |
|
22 | #if no-pure no-rust | |
23 |
|
23 | |||
24 | $ hg id |
|
24 | $ hg id | |
25 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
25 | abort: accessing `persistent-nodemap` repository without associated fast implementation. | |
26 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
26 | (check `hg help config.format.use-persistent-nodemap` for details) | |
27 | [255] |
|
27 | [255] | |
28 |
|
28 | |||
29 | Unlock further check (we are here to test the feature) |
|
29 | Unlock further check (we are here to test the feature) | |
30 |
|
30 | |||
31 | $ cat << EOF >> $HGRCPATH |
|
31 | $ cat << EOF >> $HGRCPATH | |
32 | > [storage] |
|
32 | > [storage] | |
33 | > # to avoid spamming the test |
|
33 | > # to avoid spamming the test | |
34 | > revlog.persistent-nodemap.slow-path=allow |
|
34 | > revlog.persistent-nodemap.slow-path=allow | |
35 | > EOF |
|
35 | > EOF | |
36 |
|
36 | |||
37 | #endif |
|
37 | #endif | |
38 |
|
38 | |||
39 | #if rust |
|
39 | #if rust | |
40 |
|
40 | |||
41 | Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule: |
|
41 | Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule: | |
42 | in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t` |
|
42 | in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t` | |
43 | (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs` |
|
43 | (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs` | |
44 | incorrectly used `libc::c_int` (32 bits). |
|
44 | incorrectly used `libc::c_int` (32 bits). | |
45 | As a result, -1 passed from Rust for the null revision became 4294967295 in C. |
|
45 | As a result, -1 passed from Rust for the null revision became 4294967295 in C. | |
46 |
|
46 | |||
47 | $ hg log -r 00000000 |
|
47 | $ hg log -r 00000000 | |
48 | changeset: -1:000000000000 |
|
48 | changeset: -1:000000000000 | |
49 | tag: tip |
|
49 | tag: tip | |
50 | user: |
|
50 | user: | |
51 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
51 | date: Thu Jan 01 00:00:00 1970 +0000 | |
52 |
|
52 | |||
53 |
|
53 | |||
54 | #endif |
|
54 | #endif | |
55 |
|
55 | |||
56 |
|
56 | |||
57 | $ hg debugformat |
|
57 | $ hg debugformat | |
58 | format-variant repo |
|
58 | format-variant repo | |
59 | fncache: yes |
|
59 | fncache: yes | |
60 | dirstate-v2: no |
|
60 | dirstate-v2: no | |
61 | dotencode: yes |
|
61 | dotencode: yes | |
62 | generaldelta: yes |
|
62 | generaldelta: yes | |
63 | share-safe: no |
|
63 | share-safe: no | |
64 | sparserevlog: yes |
|
64 | sparserevlog: yes | |
65 | persistent-nodemap: yes |
|
65 | persistent-nodemap: yes | |
66 | copies-sdc: no |
|
66 | copies-sdc: no | |
67 | revlog-v2: no |
|
67 | revlog-v2: no | |
68 | changelog-v2: no |
|
68 | changelog-v2: no | |
69 | plain-cl-delta: yes |
|
69 | plain-cl-delta: yes | |
70 | compression: zlib (no-zstd !) |
|
70 | compression: zlib (no-zstd !) | |
71 | compression: zstd (zstd !) |
|
71 | compression: zstd (zstd !) | |
72 | compression-level: default |
|
72 | compression-level: default | |
73 | $ hg debugbuilddag .+5000 --new-file |
|
73 | $ hg debugbuilddag .+5000 --new-file | |
74 |
|
74 | |||
75 | $ hg debugnodemap --metadata |
|
75 | $ hg debugnodemap --metadata | |
76 | uid: ???????? (glob) |
|
76 | uid: ???????? (glob) | |
77 | tip-rev: 5000 |
|
77 | tip-rev: 5000 | |
78 | tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c |
|
78 | tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c | |
79 | data-length: 121088 |
|
79 | data-length: 121088 | |
80 | data-unused: 0 |
|
80 | data-unused: 0 | |
81 | data-unused: 0.000% |
|
81 | data-unused: 0.000% | |
82 | $ f --size .hg/store/00changelog.n |
|
82 | $ f --size .hg/store/00changelog.n | |
83 | .hg/store/00changelog.n: size=62 |
|
83 | .hg/store/00changelog.n: size=62 | |
84 |
|
84 | |||
85 | Simple lookup works |
|
85 | Simple lookup works | |
86 |
|
86 | |||
87 | $ ANYNODE=`hg log --template '{node|short}\n' --rev tip` |
|
87 | $ ANYNODE=`hg log --template '{node|short}\n' --rev tip` | |
88 | $ hg log -r "$ANYNODE" --template '{rev}\n' |
|
88 | $ hg log -r "$ANYNODE" --template '{rev}\n' | |
89 | 5000 |
|
89 | 5000 | |
90 |
|
90 | |||
91 |
|
91 | |||
92 | #if rust |
|
92 | #if rust | |
93 |
|
93 | |||
94 | $ f --sha256 .hg/store/00changelog-*.nd |
|
94 | $ f --sha256 .hg/store/00changelog-*.nd | |
95 | .hg/store/00changelog-????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob) |
|
95 | .hg/store/00changelog-????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob) | |
96 |
|
96 | |||
97 | $ f --sha256 .hg/store/00manifest-*.nd |
|
97 | $ f --sha256 .hg/store/00manifest-*.nd | |
98 | .hg/store/00manifest-????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob) |
|
98 | .hg/store/00manifest-????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob) | |
99 | $ hg debugnodemap --dump-new | f --sha256 --size |
|
99 | $ hg debugnodemap --dump-new | f --sha256 --size | |
100 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd |
|
100 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd | |
101 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size |
|
101 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size | |
102 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd |
|
102 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd | |
103 | 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........| |
|
103 | 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........| | |
104 | 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."| |
|
104 | 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."| | |
105 | 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^| |
|
105 | 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^| | |
106 | 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....| |
|
106 | 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....| | |
107 | 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8| |
|
107 | 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8| | |
108 | 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i| |
|
108 | 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i| | |
109 | 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....| |
|
109 | 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....| | |
110 | 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........| |
|
110 | 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........| | |
111 | 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....| |
|
111 | 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....| | |
112 | 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................| |
|
112 | 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................| | |
113 | 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+| |
|
113 | 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+| | |
114 | 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................| |
|
114 | 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................| | |
115 | 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5| |
|
115 | 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5| | |
116 | 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U| |
|
116 | 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U| | |
117 | 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................| |
|
117 | 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................| | |
118 | 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................| |
|
118 | 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................| | |
119 |
|
119 | |||
120 |
|
120 | |||
121 | #else |
|
121 | #else | |
122 |
|
122 | |||
123 | $ f --sha256 .hg/store/00changelog-*.nd |
|
123 | $ f --sha256 .hg/store/00changelog-*.nd | |
124 | .hg/store/00changelog-????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob) |
|
124 | .hg/store/00changelog-????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob) | |
125 | $ hg debugnodemap --dump-new | f --sha256 --size |
|
125 | $ hg debugnodemap --dump-new | f --sha256 --size | |
126 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 |
|
126 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 | |
127 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size |
|
127 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size | |
128 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 |
|
128 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 | |
129 | 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
129 | 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
130 | 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
130 | 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
131 | 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................| |
|
131 | 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................| | |
132 | 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
132 | 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
133 | 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
133 | 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
134 | 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................| |
|
134 | 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................| | |
135 | 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............| |
|
135 | 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............| | |
136 | 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
136 | 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
137 | 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
137 | 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
138 | 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................| |
|
138 | 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................| | |
139 | 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........| |
|
139 | 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........| | |
140 | 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
140 | 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
141 | 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
141 | 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
142 | 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
142 | 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | |
143 | 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................| |
|
143 | 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................| | |
144 | 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................| |
|
144 | 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................| | |
145 |
|
145 | |||
146 | #endif |
|
146 | #endif | |
147 |
|
147 | |||
148 | $ hg debugnodemap --check |
|
148 | $ hg debugnodemap --check | |
149 | revision in index: 5001 |
|
149 | revision in index: 5001 | |
150 | revision in nodemap: 5001 |
|
150 | revision in nodemap: 5001 | |
151 |
|
151 | |||
152 | add a new commit |
|
152 | add a new commit | |
153 |
|
153 | |||
154 | $ hg up |
|
154 | $ hg up | |
155 | 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
155 | 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
156 | $ echo foo > foo |
|
156 | $ echo foo > foo | |
157 | $ hg add foo |
|
157 | $ hg add foo | |
158 |
|
158 | |||
159 |
|
159 | |||
160 | Check slow-path config value handling |
|
160 | Check slow-path config value handling | |
161 | ------------------------------------- |
|
161 | ------------------------------------- | |
162 |
|
162 | |||
163 | #if no-pure no-rust |
|
163 | #if no-pure no-rust | |
164 |
|
164 | |||
165 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" |
|
165 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" | |
166 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" |
|
166 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" | |
167 | falling back to default value: abort |
|
167 | falling back to default value: abort | |
168 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
168 | abort: accessing `persistent-nodemap` repository without associated fast implementation. | |
169 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
169 | (check `hg help config.format.use-persistent-nodemap` for details) | |
170 | [255] |
|
170 | [255] | |
171 |
|
171 | |||
172 | $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn" |
|
172 | $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn" | |
173 | warning: accessing `persistent-nodemap` repository without associated fast implementation. |
|
173 | warning: accessing `persistent-nodemap` repository without associated fast implementation. | |
174 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
174 | (check `hg help config.format.use-persistent-nodemap` for details) | |
175 | changeset: 5000:6b02b8c7b966 |
|
175 | changeset: 5000:6b02b8c7b966 | |
176 | tag: tip |
|
176 | tag: tip | |
177 | user: debugbuilddag |
|
177 | user: debugbuilddag | |
178 | date: Thu Jan 01 01:23:20 1970 +0000 |
|
178 | date: Thu Jan 01 01:23:20 1970 +0000 | |
179 | summary: r5000 |
|
179 | summary: r5000 | |
180 |
|
180 | |||
181 | $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort" |
|
181 | $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort" | |
182 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
182 | abort: accessing `persistent-nodemap` repository without associated fast implementation. | |
183 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
183 | (check `hg help config.format.use-persistent-nodemap` for details) | |
184 | [255] |
|
184 | [255] | |
185 |
|
185 | |||
186 | #else |
|
186 | #else | |
187 |
|
187 | |||
188 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" |
|
188 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" | |
189 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" |
|
189 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" | |
190 | falling back to default value: abort |
|
190 | falling back to default value: abort | |
191 | 6b02b8c7b966+ tip |
|
191 | 6b02b8c7b966+ tip | |
192 |
|
192 | |||
193 | #endif |
|
193 | #endif | |
194 |
|
194 | |||
195 | $ hg ci -m 'foo' |
|
195 | $ hg ci -m 'foo' | |
196 |
|
196 | |||
197 | #if no-pure no-rust |
|
197 | #if no-pure no-rust | |
198 | $ hg debugnodemap --metadata |
|
198 | $ hg debugnodemap --metadata | |
199 | uid: ???????? (glob) |
|
199 | uid: ???????? (glob) | |
200 | tip-rev: 5001 |
|
200 | tip-rev: 5001 | |
201 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c |
|
201 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c | |
202 | data-length: 121088 |
|
202 | data-length: 121088 | |
203 | data-unused: 0 |
|
203 | data-unused: 0 | |
204 | data-unused: 0.000% |
|
204 | data-unused: 0.000% | |
205 | #else |
|
205 | #else | |
206 | $ hg debugnodemap --metadata |
|
206 | $ hg debugnodemap --metadata | |
207 | uid: ???????? (glob) |
|
207 | uid: ???????? (glob) | |
208 | tip-rev: 5001 |
|
208 | tip-rev: 5001 | |
209 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c |
|
209 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c | |
210 | data-length: 121344 |
|
210 | data-length: 121344 | |
211 | data-unused: 256 |
|
211 | data-unused: 256 | |
212 | data-unused: 0.211% |
|
212 | data-unused: 0.211% | |
213 | #endif |
|
213 | #endif | |
214 |
|
214 | |||
215 | $ f --size .hg/store/00changelog.n |
|
215 | $ f --size .hg/store/00changelog.n | |
216 | .hg/store/00changelog.n: size=62 |
|
216 | .hg/store/00changelog.n: size=62 | |
217 |
|
217 | |||
218 | (The pure code use the debug code that perform incremental update, the C code reencode from scratch) |
|
218 | (The pure code use the debug code that perform incremental update, the C code reencode from scratch) | |
219 |
|
219 | |||
220 | #if pure |
|
220 | #if pure | |
221 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
221 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
222 | .hg/store/00changelog-????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob) |
|
222 | .hg/store/00changelog-????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob) | |
223 | #endif |
|
223 | #endif | |
224 |
|
224 | |||
225 | #if rust |
|
225 | #if rust | |
226 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
226 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
227 | .hg/store/00changelog-????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob) |
|
227 | .hg/store/00changelog-????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob) | |
228 | #endif |
|
228 | #endif | |
229 |
|
229 | |||
230 | #if no-pure no-rust |
|
230 | #if no-pure no-rust | |
231 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
231 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
232 | .hg/store/00changelog-????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob) |
|
232 | .hg/store/00changelog-????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob) | |
233 | #endif |
|
233 | #endif | |
234 |
|
234 | |||
235 | $ hg debugnodemap --check |
|
235 | $ hg debugnodemap --check | |
236 | revision in index: 5002 |
|
236 | revision in index: 5002 | |
237 | revision in nodemap: 5002 |
|
237 | revision in nodemap: 5002 | |
238 |
|
238 | |||
239 | Test code path without mmap |
|
239 | Test code path without mmap | |
240 | --------------------------- |
|
240 | --------------------------- | |
241 |
|
241 | |||
242 | $ echo bar > bar |
|
242 | $ echo bar > bar | |
243 | $ hg add bar |
|
243 | $ hg add bar | |
244 | $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no |
|
244 | $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no | |
245 |
|
245 | |||
246 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes |
|
246 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes | |
247 | revision in index: 5003 |
|
247 | revision in index: 5003 | |
248 | revision in nodemap: 5003 |
|
248 | revision in nodemap: 5003 | |
249 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no |
|
249 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no | |
250 | revision in index: 5003 |
|
250 | revision in index: 5003 | |
251 | revision in nodemap: 5003 |
|
251 | revision in nodemap: 5003 | |
252 |
|
252 | |||
253 |
|
253 | |||
254 | #if pure |
|
254 | #if pure | |
255 | $ hg debugnodemap --metadata |
|
255 | $ hg debugnodemap --metadata | |
256 | uid: ???????? (glob) |
|
256 | uid: ???????? (glob) | |
257 | tip-rev: 5002 |
|
257 | tip-rev: 5002 | |
258 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
258 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
259 | data-length: 121600 |
|
259 | data-length: 121600 | |
260 | data-unused: 512 |
|
260 | data-unused: 512 | |
261 | data-unused: 0.421% |
|
261 | data-unused: 0.421% | |
262 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
262 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
263 | .hg/store/00changelog-????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob) |
|
263 | .hg/store/00changelog-????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob) | |
264 | #endif |
|
264 | #endif | |
265 | #if rust |
|
265 | #if rust | |
266 | $ hg debugnodemap --metadata |
|
266 | $ hg debugnodemap --metadata | |
267 | uid: ???????? (glob) |
|
267 | uid: ???????? (glob) | |
268 | tip-rev: 5002 |
|
268 | tip-rev: 5002 | |
269 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
269 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
270 | data-length: 121600 |
|
270 | data-length: 121600 | |
271 | data-unused: 512 |
|
271 | data-unused: 512 | |
272 | data-unused: 0.421% |
|
272 | data-unused: 0.421% | |
273 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
273 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
274 | .hg/store/00changelog-????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob) |
|
274 | .hg/store/00changelog-????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob) | |
275 | #endif |
|
275 | #endif | |
276 | #if no-pure no-rust |
|
276 | #if no-pure no-rust | |
277 | $ hg debugnodemap --metadata |
|
277 | $ hg debugnodemap --metadata | |
278 | uid: ???????? (glob) |
|
278 | uid: ???????? (glob) | |
279 | tip-rev: 5002 |
|
279 | tip-rev: 5002 | |
280 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
280 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
281 | data-length: 121088 |
|
281 | data-length: 121088 | |
282 | data-unused: 0 |
|
282 | data-unused: 0 | |
283 | data-unused: 0.000% |
|
283 | data-unused: 0.000% | |
284 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
284 | $ f --sha256 .hg/store/00changelog-*.nd --size | |
285 | .hg/store/00changelog-????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob) |
|
285 | .hg/store/00changelog-????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob) | |
286 | #endif |
|
286 | #endif | |
287 |
|
287 | |||
288 | Test force warming the cache |
|
288 | Test force warming the cache | |
289 |
|
289 | |||
290 | $ rm .hg/store/00changelog.n |
|
290 | $ rm .hg/store/00changelog.n | |
291 | $ hg debugnodemap --metadata |
|
291 | $ hg debugnodemap --metadata | |
292 | $ hg debugupdatecache |
|
292 | $ hg debugupdatecache | |
293 | #if pure |
|
293 | #if pure | |
294 | $ hg debugnodemap --metadata |
|
294 | $ hg debugnodemap --metadata | |
295 | uid: ???????? (glob) |
|
295 | uid: ???????? (glob) | |
296 | tip-rev: 5002 |
|
296 | tip-rev: 5002 | |
297 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
297 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
298 | data-length: 121088 |
|
298 | data-length: 121088 | |
299 | data-unused: 0 |
|
299 | data-unused: 0 | |
300 | data-unused: 0.000% |
|
300 | data-unused: 0.000% | |
301 | #else |
|
301 | #else | |
302 | $ hg debugnodemap --metadata |
|
302 | $ hg debugnodemap --metadata | |
303 | uid: ???????? (glob) |
|
303 | uid: ???????? (glob) | |
304 | tip-rev: 5002 |
|
304 | tip-rev: 5002 | |
305 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
305 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
306 | data-length: 121088 |
|
306 | data-length: 121088 | |
307 | data-unused: 0 |
|
307 | data-unused: 0 | |
308 | data-unused: 0.000% |
|
308 | data-unused: 0.000% | |
309 | #endif |
|
309 | #endif | |
310 |
|
310 | |||
311 | Check out of sync nodemap |
|
311 | Check out of sync nodemap | |
312 | ========================= |
|
312 | ========================= | |
313 |
|
313 | |||
314 | First copy old data on the side. |
|
314 | First copy old data on the side. | |
315 |
|
315 | |||
316 | $ mkdir ../tmp-copies |
|
316 | $ mkdir ../tmp-copies | |
317 | $ cp .hg/store/00changelog-????????.nd .hg/store/00changelog.n ../tmp-copies |
|
317 | $ cp .hg/store/00changelog-????????.nd .hg/store/00changelog.n ../tmp-copies | |
318 |
|
318 | |||
319 | Nodemap lagging behind |
|
319 | Nodemap lagging behind | |
320 | ---------------------- |
|
320 | ---------------------- | |
321 |
|
321 | |||
322 | make a new commit |
|
322 | make a new commit | |
323 |
|
323 | |||
324 | $ echo bar2 > bar |
|
324 | $ echo bar2 > bar | |
325 | $ hg ci -m 'bar2' |
|
325 | $ hg ci -m 'bar2' | |
326 | $ NODE=`hg log -r tip -T '{node}\n'` |
|
326 | $ NODE=`hg log -r tip -T '{node}\n'` | |
327 | $ hg log -r "$NODE" -T '{rev}\n' |
|
327 | $ hg log -r "$NODE" -T '{rev}\n' | |
328 | 5003 |
|
328 | 5003 | |
329 |
|
329 | |||
330 | If the nodemap is lagging behind, it can catch up fine |
|
330 | If the nodemap is lagging behind, it can catch up fine | |
331 |
|
331 | |||
332 | $ hg debugnodemap --metadata |
|
332 | $ hg debugnodemap --metadata | |
333 | uid: ???????? (glob) |
|
333 | uid: ???????? (glob) | |
334 | tip-rev: 5003 |
|
334 | tip-rev: 5003 | |
335 | tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3 |
|
335 | tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3 | |
336 | data-length: 121344 (pure !) |
|
336 | data-length: 121344 (pure !) | |
337 | data-length: 121344 (rust !) |
|
337 | data-length: 121344 (rust !) | |
338 | data-length: 121152 (no-rust no-pure !) |
|
338 | data-length: 121152 (no-rust no-pure !) | |
339 | data-unused: 192 (pure !) |
|
339 | data-unused: 192 (pure !) | |
340 | data-unused: 192 (rust !) |
|
340 | data-unused: 192 (rust !) | |
341 | data-unused: 0 (no-rust no-pure !) |
|
341 | data-unused: 0 (no-rust no-pure !) | |
342 | data-unused: 0.158% (pure !) |
|
342 | data-unused: 0.158% (pure !) | |
343 | data-unused: 0.158% (rust !) |
|
343 | data-unused: 0.158% (rust !) | |
344 | data-unused: 0.000% (no-rust no-pure !) |
|
344 | data-unused: 0.000% (no-rust no-pure !) | |
345 | $ cp -f ../tmp-copies/* .hg/store/ |
|
345 | $ cp -f ../tmp-copies/* .hg/store/ | |
346 | $ hg debugnodemap --metadata |
|
346 | $ hg debugnodemap --metadata | |
347 | uid: ???????? (glob) |
|
347 | uid: ???????? (glob) | |
348 | tip-rev: 5002 |
|
348 | tip-rev: 5002 | |
349 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
349 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
350 | data-length: 121088 |
|
350 | data-length: 121088 | |
351 | data-unused: 0 |
|
351 | data-unused: 0 | |
352 | data-unused: 0.000% |
|
352 | data-unused: 0.000% | |
353 | $ hg log -r "$NODE" -T '{rev}\n' |
|
353 | $ hg log -r "$NODE" -T '{rev}\n' | |
354 | 5003 |
|
354 | 5003 | |
355 |
|
355 | |||
356 | changelog altered |
|
356 | changelog altered | |
357 | ----------------- |
|
357 | ----------------- | |
358 |
|
358 | |||
359 | If the nodemap is not gated behind a requirements, an unaware client can alter |
|
359 | If the nodemap is not gated behind a requirements, an unaware client can alter | |
360 | the repository so the revlog used to generate the nodemap is not longer |
|
360 | the repository so the revlog used to generate the nodemap is not longer | |
361 | compatible with the persistent nodemap. We need to detect that. |
|
361 | compatible with the persistent nodemap. We need to detect that. | |
362 |
|
362 | |||
363 | $ hg up "$NODE~5" |
|
363 | $ hg up "$NODE~5" | |
364 | 0 files updated, 0 files merged, 4 files removed, 0 files unresolved |
|
364 | 0 files updated, 0 files merged, 4 files removed, 0 files unresolved | |
365 | $ echo bar > babar |
|
365 | $ echo bar > babar | |
366 | $ hg add babar |
|
366 | $ hg add babar | |
367 | $ hg ci -m 'babar' |
|
367 | $ hg ci -m 'babar' | |
368 | created new head |
|
368 | created new head | |
369 | $ OTHERNODE=`hg log -r tip -T '{node}\n'` |
|
369 | $ OTHERNODE=`hg log -r tip -T '{node}\n'` | |
370 | $ hg log -r "$OTHERNODE" -T '{rev}\n' |
|
370 | $ hg log -r "$OTHERNODE" -T '{rev}\n' | |
371 | 5004 |
|
371 | 5004 | |
372 |
|
372 | |||
373 | $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup |
|
373 | $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup | |
374 |
|
374 | |||
375 | the nodemap should detect the changelog have been tampered with and recover. |
|
375 | the nodemap should detect the changelog have been tampered with and recover. | |
376 |
|
376 | |||
377 | $ hg debugnodemap --metadata |
|
377 | $ hg debugnodemap --metadata | |
378 | uid: ???????? (glob) |
|
378 | uid: ???????? (glob) | |
379 | tip-rev: 5002 |
|
379 | tip-rev: 5002 | |
380 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 |
|
380 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 | |
381 | data-length: 121536 (pure !) |
|
381 | data-length: 121536 (pure !) | |
382 | data-length: 121088 (rust !) |
|
382 | data-length: 121088 (rust !) | |
383 | data-length: 121088 (no-pure no-rust !) |
|
383 | data-length: 121088 (no-pure no-rust !) | |
384 | data-unused: 448 (pure !) |
|
384 | data-unused: 448 (pure !) | |
385 | data-unused: 0 (rust !) |
|
385 | data-unused: 0 (rust !) | |
386 | data-unused: 0 (no-pure no-rust !) |
|
386 | data-unused: 0 (no-pure no-rust !) | |
387 | data-unused: 0.000% (rust !) |
|
387 | data-unused: 0.000% (rust !) | |
388 | data-unused: 0.369% (pure !) |
|
388 | data-unused: 0.369% (pure !) | |
389 | data-unused: 0.000% (no-pure no-rust !) |
|
389 | data-unused: 0.000% (no-pure no-rust !) | |
390 |
|
390 | |||
391 | $ cp -f ../tmp-copies/* .hg/store/ |
|
391 | $ cp -f ../tmp-copies/* .hg/store/ | |
392 | $ hg debugnodemap --metadata |
|
392 | $ hg debugnodemap --metadata | |
393 | uid: ???????? (glob) |
|
393 | uid: ???????? (glob) | |
394 | tip-rev: 5002 |
|
394 | tip-rev: 5002 | |
395 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
395 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd | |
396 | data-length: 121088 |
|
396 | data-length: 121088 | |
397 | data-unused: 0 |
|
397 | data-unused: 0 | |
398 | data-unused: 0.000% |
|
398 | data-unused: 0.000% | |
399 | $ hg log -r "$OTHERNODE" -T '{rev}\n' |
|
399 | $ hg log -r "$OTHERNODE" -T '{rev}\n' | |
400 | 5002 |
|
400 | 5002 | |
401 |
|
401 | |||
402 | missing data file |
|
402 | missing data file | |
403 | ----------------- |
|
403 | ----------------- | |
404 |
|
404 | |||
405 | $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \ |
|
405 | $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \ | |
406 | > sed 's/uid: //'` |
|
406 | > sed 's/uid: //'` | |
407 | $ FILE=.hg/store/00changelog-"${UUID}".nd |
|
407 | $ FILE=.hg/store/00changelog-"${UUID}".nd | |
408 | $ mv $FILE ../tmp-data-file |
|
408 | $ mv $FILE ../tmp-data-file | |
409 | $ cp .hg/store/00changelog.n ../tmp-docket |
|
409 | $ cp .hg/store/00changelog.n ../tmp-docket | |
410 |
|
410 | |||
411 | mercurial don't crash |
|
411 | mercurial don't crash | |
412 |
|
412 | |||
413 | $ hg log -r . |
|
413 | $ hg log -r . | |
414 | changeset: 5002:b355ef8adce0 |
|
414 | changeset: 5002:b355ef8adce0 | |
415 | tag: tip |
|
415 | tag: tip | |
416 | parent: 4998:d918ad6d18d3 |
|
416 | parent: 4998:d918ad6d18d3 | |
417 | user: test |
|
417 | user: test | |
418 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
418 | date: Thu Jan 01 00:00:00 1970 +0000 | |
419 | summary: babar |
|
419 | summary: babar | |
420 |
|
420 | |||
421 | $ hg debugnodemap --metadata |
|
421 | $ hg debugnodemap --metadata | |
422 |
|
422 | |||
423 | $ hg debugupdatecache |
|
423 | $ hg debugupdatecache | |
424 | $ hg debugnodemap --metadata |
|
424 | $ hg debugnodemap --metadata | |
425 | uid: * (glob) |
|
425 | uid: * (glob) | |
426 | tip-rev: 5002 |
|
426 | tip-rev: 5002 | |
427 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 |
|
427 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 | |
428 | data-length: 121088 |
|
428 | data-length: 121088 | |
429 | data-unused: 0 |
|
429 | data-unused: 0 | |
430 | data-unused: 0.000% |
|
430 | data-unused: 0.000% | |
431 | $ mv ../tmp-data-file $FILE |
|
431 | $ mv ../tmp-data-file $FILE | |
432 | $ mv ../tmp-docket .hg/store/00changelog.n |
|
432 | $ mv ../tmp-docket .hg/store/00changelog.n | |
433 |
|
433 | |||
434 | Check transaction related property |
|
434 | Check transaction related property | |
435 | ================================== |
|
435 | ================================== | |
436 |
|
436 | |||
437 | An up to date nodemap should be available to shell hooks, |
|
437 | An up to date nodemap should be available to shell hooks, | |
438 |
|
438 | |||
439 | $ echo dsljfl > a |
|
439 | $ echo dsljfl > a | |
440 | $ hg add a |
|
440 | $ hg add a | |
441 | $ hg ci -m a |
|
441 | $ hg ci -m a | |
442 | $ hg debugnodemap --metadata |
|
442 | $ hg debugnodemap --metadata | |
443 | uid: ???????? (glob) |
|
443 | uid: ???????? (glob) | |
444 | tip-rev: 5003 |
|
444 | tip-rev: 5003 | |
445 | tip-node: a52c5079765b5865d97b993b303a18740113bbb2 |
|
445 | tip-node: a52c5079765b5865d97b993b303a18740113bbb2 | |
446 | data-length: 121088 |
|
446 | data-length: 121088 | |
447 | data-unused: 0 |
|
447 | data-unused: 0 | |
448 | data-unused: 0.000% |
|
448 | data-unused: 0.000% | |
449 | $ echo babar2 > babar |
|
449 | $ echo babar2 > babar | |
450 | $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata" |
|
450 | $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata" | |
451 | uid: ???????? (glob) |
|
451 | uid: ???????? (glob) | |
452 | tip-rev: 5004 |
|
452 | tip-rev: 5004 | |
453 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
453 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 | |
454 | data-length: 121280 (pure !) |
|
454 | data-length: 121280 (pure !) | |
455 | data-length: 121280 (rust !) |
|
455 | data-length: 121280 (rust !) | |
456 | data-length: 121088 (no-pure no-rust !) |
|
456 | data-length: 121088 (no-pure no-rust !) | |
457 | data-unused: 192 (pure !) |
|
457 | data-unused: 192 (pure !) | |
458 | data-unused: 192 (rust !) |
|
458 | data-unused: 192 (rust !) | |
459 | data-unused: 0 (no-pure no-rust !) |
|
459 | data-unused: 0 (no-pure no-rust !) | |
460 | data-unused: 0.158% (pure !) |
|
460 | data-unused: 0.158% (pure !) | |
461 | data-unused: 0.158% (rust !) |
|
461 | data-unused: 0.158% (rust !) | |
462 | data-unused: 0.000% (no-pure no-rust !) |
|
462 | data-unused: 0.000% (no-pure no-rust !) | |
463 | $ hg debugnodemap --metadata |
|
463 | $ hg debugnodemap --metadata | |
464 | uid: ???????? (glob) |
|
464 | uid: ???????? (glob) | |
465 | tip-rev: 5004 |
|
465 | tip-rev: 5004 | |
466 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
466 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 | |
467 | data-length: 121280 (pure !) |
|
467 | data-length: 121280 (pure !) | |
468 | data-length: 121280 (rust !) |
|
468 | data-length: 121280 (rust !) | |
469 | data-length: 121088 (no-pure no-rust !) |
|
469 | data-length: 121088 (no-pure no-rust !) | |
470 | data-unused: 192 (pure !) |
|
470 | data-unused: 192 (pure !) | |
471 | data-unused: 192 (rust !) |
|
471 | data-unused: 192 (rust !) | |
472 | data-unused: 0 (no-pure no-rust !) |
|
472 | data-unused: 0 (no-pure no-rust !) | |
473 | data-unused: 0.158% (pure !) |
|
473 | data-unused: 0.158% (pure !) | |
474 | data-unused: 0.158% (rust !) |
|
474 | data-unused: 0.158% (rust !) | |
475 | data-unused: 0.000% (no-pure no-rust !) |
|
475 | data-unused: 0.000% (no-pure no-rust !) | |
476 |
|
476 | |||
477 | Another process does not see the pending nodemap content during run. |
|
477 | Another process does not see the pending nodemap content during run. | |
478 |
|
478 | |||
479 | $ echo qpoasp > a |
|
479 | $ echo qpoasp > a | |
480 | $ hg ci -m a2 \ |
|
480 | $ hg ci -m a2 \ | |
481 | > --config "hooks.pretxnclose=sh \"$RUNTESTDIR/testlib/wait-on-file\" 20 sync-repo-read sync-txn-pending" \ |
|
481 | > --config "hooks.pretxnclose=sh \"$RUNTESTDIR/testlib/wait-on-file\" 20 sync-repo-read sync-txn-pending" \ | |
482 | > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 & |
|
482 | > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 & | |
483 |
|
483 | |||
484 | (read the repository while the commit transaction is pending) |
|
484 | (read the repository while the commit transaction is pending) | |
485 |
|
485 | |||
486 | $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \ |
|
486 | $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \ | |
487 | > hg debugnodemap --metadata && \ |
|
487 | > hg debugnodemap --metadata && \ | |
488 | > sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-close sync-repo-read |
|
488 | > sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-close sync-repo-read | |
489 | uid: ???????? (glob) |
|
489 | uid: ???????? (glob) | |
490 | tip-rev: 5004 |
|
490 | tip-rev: 5004 | |
491 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
491 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 | |
492 | data-length: 121280 (pure !) |
|
492 | data-length: 121280 (pure !) | |
493 | data-length: 121280 (rust !) |
|
493 | data-length: 121280 (rust !) | |
494 | data-length: 121088 (no-pure no-rust !) |
|
494 | data-length: 121088 (no-pure no-rust !) | |
495 | data-unused: 192 (pure !) |
|
495 | data-unused: 192 (pure !) | |
496 | data-unused: 192 (rust !) |
|
496 | data-unused: 192 (rust !) | |
497 | data-unused: 0 (no-pure no-rust !) |
|
497 | data-unused: 0 (no-pure no-rust !) | |
498 | data-unused: 0.158% (pure !) |
|
498 | data-unused: 0.158% (pure !) | |
499 | data-unused: 0.158% (rust !) |
|
499 | data-unused: 0.158% (rust !) | |
500 | data-unused: 0.000% (no-pure no-rust !) |
|
500 | data-unused: 0.000% (no-pure no-rust !) | |
501 | $ hg debugnodemap --metadata |
|
501 | $ hg debugnodemap --metadata | |
502 | uid: ???????? (glob) |
|
502 | uid: ???????? (glob) | |
503 | tip-rev: 5005 |
|
503 | tip-rev: 5005 | |
504 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
504 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
505 | data-length: 121536 (pure !) |
|
505 | data-length: 121536 (pure !) | |
506 | data-length: 121536 (rust !) |
|
506 | data-length: 121536 (rust !) | |
507 | data-length: 121088 (no-pure no-rust !) |
|
507 | data-length: 121088 (no-pure no-rust !) | |
508 | data-unused: 448 (pure !) |
|
508 | data-unused: 448 (pure !) | |
509 | data-unused: 448 (rust !) |
|
509 | data-unused: 448 (rust !) | |
510 | data-unused: 0 (no-pure no-rust !) |
|
510 | data-unused: 0 (no-pure no-rust !) | |
511 | data-unused: 0.369% (pure !) |
|
511 | data-unused: 0.369% (pure !) | |
512 | data-unused: 0.369% (rust !) |
|
512 | data-unused: 0.369% (rust !) | |
513 | data-unused: 0.000% (no-pure no-rust !) |
|
513 | data-unused: 0.000% (no-pure no-rust !) | |
514 |
|
514 | |||
515 | $ cat output.txt |
|
515 | $ cat output.txt | |
516 |
|
516 | |||
517 | Check that a failing transaction will properly revert the data |
|
517 | Check that a failing transaction will properly revert the data | |
518 |
|
518 | |||
519 | $ echo plakfe > a |
|
519 | $ echo plakfe > a | |
520 | $ f --size --sha256 .hg/store/00changelog-*.nd |
|
520 | $ f --size --sha256 .hg/store/00changelog-*.nd | |
521 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) |
|
521 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) | |
522 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) |
|
522 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) | |
523 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) |
|
523 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) | |
524 | $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py" |
|
524 | $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py" | |
525 | transaction abort! |
|
525 | transaction abort! | |
526 | rollback completed |
|
526 | rollback completed | |
527 | abort: This is a late abort |
|
527 | abort: This is a late abort | |
528 | [255] |
|
528 | [255] | |
529 | $ hg debugnodemap --metadata |
|
529 | $ hg debugnodemap --metadata | |
530 | uid: ???????? (glob) |
|
530 | uid: ???????? (glob) | |
531 | tip-rev: 5005 |
|
531 | tip-rev: 5005 | |
532 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
532 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
533 | data-length: 121536 (pure !) |
|
533 | data-length: 121536 (pure !) | |
534 | data-length: 121536 (rust !) |
|
534 | data-length: 121536 (rust !) | |
535 | data-length: 121088 (no-pure no-rust !) |
|
535 | data-length: 121088 (no-pure no-rust !) | |
536 | data-unused: 448 (pure !) |
|
536 | data-unused: 448 (pure !) | |
537 | data-unused: 448 (rust !) |
|
537 | data-unused: 448 (rust !) | |
538 | data-unused: 0 (no-pure no-rust !) |
|
538 | data-unused: 0 (no-pure no-rust !) | |
539 | data-unused: 0.369% (pure !) |
|
539 | data-unused: 0.369% (pure !) | |
540 | data-unused: 0.369% (rust !) |
|
540 | data-unused: 0.369% (rust !) | |
541 | data-unused: 0.000% (no-pure no-rust !) |
|
541 | data-unused: 0.000% (no-pure no-rust !) | |
542 | $ f --size --sha256 .hg/store/00changelog-*.nd |
|
542 | $ f --size --sha256 .hg/store/00changelog-*.nd | |
543 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) |
|
543 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) | |
544 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) |
|
544 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) | |
545 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) |
|
545 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) | |
546 |
|
546 | |||
547 | Check that removing content does not confuse the nodemap |
|
547 | Check that removing content does not confuse the nodemap | |
548 | -------------------------------------------------------- |
|
548 | -------------------------------------------------------- | |
549 |
|
549 | |||
550 | removing data with rollback |
|
550 | removing data with rollback | |
551 |
|
551 | |||
552 | $ echo aso > a |
|
552 | $ echo aso > a | |
553 | $ hg ci -m a4 |
|
553 | $ hg ci -m a4 | |
554 | $ hg rollback |
|
554 | $ hg rollback | |
555 | repository tip rolled back to revision 5005 (undo commit) |
|
555 | repository tip rolled back to revision 5005 (undo commit) | |
556 | working directory now based on revision 5005 |
|
556 | working directory now based on revision 5005 | |
557 | $ hg id -r . |
|
557 | $ hg id -r . | |
558 | 90d5d3ba2fc4 tip |
|
558 | 90d5d3ba2fc4 tip | |
559 |
|
559 | |||
560 | roming data with strip |
|
560 | roming data with strip | |
561 |
|
561 | |||
562 | $ echo aso > a |
|
562 | $ echo aso > a | |
563 | $ hg ci -m a4 |
|
563 | $ hg ci -m a4 | |
564 | $ hg --config extensions.strip= strip -r . --no-backup |
|
564 | $ hg --config extensions.strip= strip -r . --no-backup | |
565 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
565 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
566 | $ hg id -r . --traceback |
|
566 | $ hg id -r . --traceback | |
567 | 90d5d3ba2fc4 tip |
|
567 | 90d5d3ba2fc4 tip | |
568 |
|
568 | |||
569 | Test upgrade / downgrade |
|
569 | Test upgrade / downgrade | |
570 | ======================== |
|
570 | ======================== | |
571 |
|
571 | |||
572 | downgrading |
|
572 | downgrading | |
573 |
|
573 | |||
574 | $ cat << EOF >> .hg/hgrc |
|
574 | $ cat << EOF >> .hg/hgrc | |
575 | > [format] |
|
575 | > [format] | |
576 | > use-persistent-nodemap=no |
|
576 | > use-persistent-nodemap=no | |
577 | > EOF |
|
577 | > EOF | |
578 | $ hg debugformat -v |
|
578 | $ hg debugformat -v | |
579 | format-variant repo config default |
|
579 | format-variant repo config default | |
580 | fncache: yes yes yes |
|
580 | fncache: yes yes yes | |
581 | dirstate-v2: no no no |
|
581 | dirstate-v2: no no no | |
582 | dotencode: yes yes yes |
|
582 | dotencode: yes yes yes | |
583 | generaldelta: yes yes yes |
|
583 | generaldelta: yes yes yes | |
584 | share-safe: no no no |
|
584 | share-safe: no no no | |
585 | sparserevlog: yes yes yes |
|
585 | sparserevlog: yes yes yes | |
586 | persistent-nodemap: yes no no |
|
586 | persistent-nodemap: yes no no | |
587 | copies-sdc: no no no |
|
587 | copies-sdc: no no no | |
588 | revlog-v2: no no no |
|
588 | revlog-v2: no no no | |
589 | changelog-v2: no no no |
|
589 | changelog-v2: no no no | |
590 | plain-cl-delta: yes yes yes |
|
590 | plain-cl-delta: yes yes yes | |
591 | compression: zlib zlib zlib (no-zstd !) |
|
591 | compression: zlib zlib zlib (no-zstd !) | |
592 | compression: zstd zstd zstd (zstd !) |
|
592 | compression: zstd zstd zstd (zstd !) | |
593 | compression-level: default default default |
|
593 | compression-level: default default default | |
594 | $ hg debugupgraderepo --run --no-backup |
|
594 | $ hg debugupgraderepo --run --no-backup | |
595 | upgrade will perform the following actions: |
|
595 | upgrade will perform the following actions: | |
596 |
|
596 | |||
597 | requirements |
|
597 | requirements | |
598 | preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
598 | preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) | |
599 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) |
|
599 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) | |
600 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) |
|
600 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) | |
601 | removed: persistent-nodemap |
|
601 | removed: persistent-nodemap | |
602 |
|
602 | |||
603 | processed revlogs: |
|
603 | processed revlogs: | |
604 | - all-filelogs |
|
604 | - all-filelogs | |
605 | - changelog |
|
605 | - changelog | |
606 | - manifest |
|
606 | - manifest | |
607 |
|
607 | |||
608 | beginning upgrade... |
|
608 | beginning upgrade... | |
609 | repository locked and read-only |
|
609 | repository locked and read-only | |
610 | creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob) |
|
610 | creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob) | |
611 | (it is safe to interrupt this process any time before data migration completes) |
|
611 | (it is safe to interrupt this process any time before data migration completes) | |
612 | downgrading repository to not use persistent nodemap feature |
|
612 | downgrading repository to not use persistent nodemap feature | |
613 | removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob) |
|
613 | removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob) | |
614 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
614 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
615 | 00changelog-*.nd (glob) |
|
615 | 00changelog-*.nd (glob) | |
616 | 00manifest-*.nd (glob) |
|
616 | 00manifest-*.nd (glob) | |
617 | undo.backup.00changelog.n |
|
617 | undo.backup.00changelog.n | |
618 | undo.backup.00manifest.n |
|
618 | undo.backup.00manifest.n | |
619 | $ hg debugnodemap --metadata |
|
619 | $ hg debugnodemap --metadata | |
620 |
|
620 | |||
621 |
|
621 | |||
622 | upgrading |
|
622 | upgrading | |
623 |
|
623 | |||
624 | $ cat << EOF >> .hg/hgrc |
|
624 | $ cat << EOF >> .hg/hgrc | |
625 | > [format] |
|
625 | > [format] | |
626 | > use-persistent-nodemap=yes |
|
626 | > use-persistent-nodemap=yes | |
627 | > EOF |
|
627 | > EOF | |
628 | $ hg debugformat -v |
|
628 | $ hg debugformat -v | |
629 | format-variant repo config default |
|
629 | format-variant repo config default | |
630 | fncache: yes yes yes |
|
630 | fncache: yes yes yes | |
631 | dirstate-v2: no no no |
|
631 | dirstate-v2: no no no | |
632 | dotencode: yes yes yes |
|
632 | dotencode: yes yes yes | |
633 | generaldelta: yes yes yes |
|
633 | generaldelta: yes yes yes | |
634 | share-safe: no no no |
|
634 | share-safe: no no no | |
635 | sparserevlog: yes yes yes |
|
635 | sparserevlog: yes yes yes | |
636 | persistent-nodemap: no yes no |
|
636 | persistent-nodemap: no yes no | |
637 | copies-sdc: no no no |
|
637 | copies-sdc: no no no | |
638 | revlog-v2: no no no |
|
638 | revlog-v2: no no no | |
639 | changelog-v2: no no no |
|
639 | changelog-v2: no no no | |
640 | plain-cl-delta: yes yes yes |
|
640 | plain-cl-delta: yes yes yes | |
641 | compression: zlib zlib zlib (no-zstd !) |
|
641 | compression: zlib zlib zlib (no-zstd !) | |
642 | compression: zstd zstd zstd (zstd !) |
|
642 | compression: zstd zstd zstd (zstd !) | |
643 | compression-level: default default default |
|
643 | compression-level: default default default | |
644 | $ hg debugupgraderepo --run --no-backup |
|
644 | $ hg debugupgraderepo --run --no-backup | |
645 | upgrade will perform the following actions: |
|
645 | upgrade will perform the following actions: | |
646 |
|
646 | |||
647 | requirements |
|
647 | requirements | |
648 | preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
648 | preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) | |
649 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) |
|
649 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) | |
650 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) |
|
650 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) | |
651 | added: persistent-nodemap |
|
651 | added: persistent-nodemap | |
652 |
|
652 | |||
653 | persistent-nodemap |
|
653 | persistent-nodemap | |
654 | Speedup revision lookup by node id. |
|
654 | Speedup revision lookup by node id. | |
655 |
|
655 | |||
656 | processed revlogs: |
|
656 | processed revlogs: | |
657 | - all-filelogs |
|
657 | - all-filelogs | |
658 | - changelog |
|
658 | - changelog | |
659 | - manifest |
|
659 | - manifest | |
660 |
|
660 | |||
661 | beginning upgrade... |
|
661 | beginning upgrade... | |
662 | repository locked and read-only |
|
662 | repository locked and read-only | |
663 | creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob) |
|
663 | creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob) | |
664 | (it is safe to interrupt this process any time before data migration completes) |
|
664 | (it is safe to interrupt this process any time before data migration completes) | |
665 | upgrading repository to use persistent nodemap feature |
|
665 | upgrading repository to use persistent nodemap feature | |
666 | removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob) |
|
666 | removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob) | |
667 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
667 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
668 | 00changelog-*.nd (glob) |
|
668 | 00changelog-*.nd (glob) | |
669 | 00changelog.n |
|
669 | 00changelog.n | |
670 | 00manifest-*.nd (glob) |
|
670 | 00manifest-*.nd (glob) | |
671 | 00manifest.n |
|
671 | 00manifest.n | |
672 | undo.backup.00changelog.n |
|
672 | undo.backup.00changelog.n | |
673 | undo.backup.00manifest.n |
|
673 | undo.backup.00manifest.n | |
674 |
|
674 | |||
675 | $ hg debugnodemap --metadata |
|
675 | $ hg debugnodemap --metadata | |
676 | uid: * (glob) |
|
676 | uid: * (glob) | |
677 | tip-rev: 5005 |
|
677 | tip-rev: 5005 | |
678 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
678 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
679 | data-length: 121088 |
|
679 | data-length: 121088 | |
680 | data-unused: 0 |
|
680 | data-unused: 0 | |
681 | data-unused: 0.000% |
|
681 | data-unused: 0.000% | |
682 |
|
682 | |||
683 | Running unrelated upgrade |
|
683 | Running unrelated upgrade | |
684 |
|
684 | |||
685 | $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all |
|
685 | $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all | |
686 | upgrade will perform the following actions: |
|
686 | upgrade will perform the following actions: | |
687 |
|
687 | |||
688 | requirements |
|
688 | requirements | |
689 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
689 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store (no-zstd no-dirstate-v2 !) | |
690 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) |
|
690 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd no-dirstate-v2 !) | |
691 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) |
|
691 | preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd dirstate-v2 !) | |
692 |
|
692 | |||
693 | optimisations: re-delta-all |
|
693 | optimisations: re-delta-all | |
694 |
|
694 | |||
695 | processed revlogs: |
|
695 | processed revlogs: | |
696 | - all-filelogs |
|
696 | - all-filelogs | |
697 | - changelog |
|
697 | - changelog | |
698 | - manifest |
|
698 | - manifest | |
699 |
|
699 | |||
700 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
700 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
701 | 00changelog-*.nd (glob) |
|
701 | 00changelog-*.nd (glob) | |
702 | 00changelog.n |
|
702 | 00changelog.n | |
703 | 00manifest-*.nd (glob) |
|
703 | 00manifest-*.nd (glob) | |
704 | 00manifest.n |
|
704 | 00manifest.n | |
705 |
|
705 | |||
706 | $ hg debugnodemap --metadata |
|
706 | $ hg debugnodemap --metadata | |
707 | uid: * (glob) |
|
707 | uid: * (glob) | |
708 | tip-rev: 5005 |
|
708 | tip-rev: 5005 | |
709 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
709 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
710 | data-length: 121088 |
|
710 | data-length: 121088 | |
711 | data-unused: 0 |
|
711 | data-unused: 0 | |
712 | data-unused: 0.000% |
|
712 | data-unused: 0.000% | |
713 |
|
713 | |||
714 | Persistent nodemap and local/streaming clone |
|
714 | Persistent nodemap and local/streaming clone | |
715 | ============================================ |
|
715 | ============================================ | |
716 |
|
716 | |||
717 | $ cd .. |
|
717 | $ cd .. | |
718 |
|
718 | |||
719 | standard clone |
|
719 | standard clone | |
720 | -------------- |
|
720 | -------------- | |
721 |
|
721 | |||
722 | The persistent nodemap should exist after a streaming clone |
|
722 | The persistent nodemap should exist after a streaming clone | |
723 |
|
723 | |||
724 | $ hg clone --pull --quiet -U test-repo standard-clone |
|
724 | $ hg clone --pull --quiet -U test-repo standard-clone | |
725 | $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
725 | $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
726 | 00changelog-*.nd (glob) |
|
726 | 00changelog-*.nd (glob) | |
727 | 00changelog.n |
|
727 | 00changelog.n | |
728 | 00manifest-*.nd (glob) |
|
728 | 00manifest-*.nd (glob) | |
729 | 00manifest.n |
|
729 | 00manifest.n | |
730 | $ hg -R standard-clone debugnodemap --metadata |
|
730 | $ hg -R standard-clone debugnodemap --metadata | |
731 | uid: * (glob) |
|
731 | uid: * (glob) | |
732 | tip-rev: 5005 |
|
732 | tip-rev: 5005 | |
733 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
733 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
734 | data-length: 121088 |
|
734 | data-length: 121088 | |
735 | data-unused: 0 |
|
735 | data-unused: 0 | |
736 | data-unused: 0.000% |
|
736 | data-unused: 0.000% | |
737 |
|
737 | |||
738 |
|
738 | |||
739 | local clone |
|
739 | local clone | |
740 | ------------ |
|
740 | ------------ | |
741 |
|
741 | |||
742 | The persistent nodemap should exist after a streaming clone |
|
742 | The persistent nodemap should exist after a streaming clone | |
743 |
|
743 | |||
744 | $ hg clone -U test-repo local-clone |
|
744 | $ hg clone -U test-repo local-clone | |
745 | $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
745 | $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
746 | 00changelog-*.nd (glob) |
|
746 | 00changelog-*.nd (glob) | |
747 | 00changelog.n |
|
747 | 00changelog.n | |
748 | 00manifest-*.nd (glob) |
|
748 | 00manifest-*.nd (glob) | |
749 | 00manifest.n |
|
749 | 00manifest.n | |
750 | $ hg -R local-clone debugnodemap --metadata |
|
750 | $ hg -R local-clone debugnodemap --metadata | |
751 | uid: * (glob) |
|
751 | uid: * (glob) | |
752 | tip-rev: 5005 |
|
752 | tip-rev: 5005 | |
753 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
753 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
754 | data-length: 121088 |
|
754 | data-length: 121088 | |
755 | data-unused: 0 |
|
755 | data-unused: 0 | |
756 | data-unused: 0.000% |
|
756 | data-unused: 0.000% | |
757 |
|
757 | |||
758 | Test various corruption case |
|
758 | Test various corruption case | |
759 | ============================ |
|
759 | ============================ | |
760 |
|
760 | |||
761 | Missing datafile |
|
761 | Missing datafile | |
762 | ---------------- |
|
762 | ---------------- | |
763 |
|
763 | |||
764 | Test behavior with a missing datafile |
|
764 | Test behavior with a missing datafile | |
765 |
|
765 | |||
766 | $ hg clone --quiet --pull test-repo corruption-test-repo |
|
766 | $ hg clone --quiet --pull test-repo corruption-test-repo | |
767 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
767 | $ ls -1 corruption-test-repo/.hg/store/00changelog* | |
768 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) |
|
768 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) | |
769 | corruption-test-repo/.hg/store/00changelog.d |
|
769 | corruption-test-repo/.hg/store/00changelog.d | |
770 | corruption-test-repo/.hg/store/00changelog.i |
|
770 | corruption-test-repo/.hg/store/00changelog.i | |
771 | corruption-test-repo/.hg/store/00changelog.n |
|
771 | corruption-test-repo/.hg/store/00changelog.n | |
772 | $ rm corruption-test-repo/.hg/store/00changelog*.nd |
|
772 | $ rm corruption-test-repo/.hg/store/00changelog*.nd | |
773 | $ hg log -R corruption-test-repo -r . |
|
773 | $ hg log -R corruption-test-repo -r . | |
774 | changeset: 5005:90d5d3ba2fc4 |
|
774 | changeset: 5005:90d5d3ba2fc4 | |
775 | tag: tip |
|
775 | tag: tip | |
776 | user: test |
|
776 | user: test | |
777 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
777 | date: Thu Jan 01 00:00:00 1970 +0000 | |
778 | summary: a2 |
|
778 | summary: a2 | |
779 |
|
779 | |||
780 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
780 | $ ls -1 corruption-test-repo/.hg/store/00changelog* | |
781 | corruption-test-repo/.hg/store/00changelog.d |
|
781 | corruption-test-repo/.hg/store/00changelog.d | |
782 | corruption-test-repo/.hg/store/00changelog.i |
|
782 | corruption-test-repo/.hg/store/00changelog.i | |
783 | corruption-test-repo/.hg/store/00changelog.n |
|
783 | corruption-test-repo/.hg/store/00changelog.n | |
784 |
|
784 | |||
785 | Truncated data file |
|
785 | Truncated data file | |
786 | ------------------- |
|
786 | ------------------- | |
787 |
|
787 | |||
788 | Test behavior with a too short datafile |
|
788 | Test behavior with a too short datafile | |
789 |
|
789 | |||
790 | rebuild the missing data |
|
790 | rebuild the missing data | |
791 | $ hg -R corruption-test-repo debugupdatecache |
|
791 | $ hg -R corruption-test-repo debugupdatecache | |
792 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
792 | $ ls -1 corruption-test-repo/.hg/store/00changelog* | |
793 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) |
|
793 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) | |
794 | corruption-test-repo/.hg/store/00changelog.d |
|
794 | corruption-test-repo/.hg/store/00changelog.d | |
795 | corruption-test-repo/.hg/store/00changelog.i |
|
795 | corruption-test-repo/.hg/store/00changelog.i | |
796 | corruption-test-repo/.hg/store/00changelog.n |
|
796 | corruption-test-repo/.hg/store/00changelog.n | |
797 |
|
797 | |||
798 | truncate the file |
|
798 | truncate the file | |
799 |
|
799 | |||
800 | $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd` |
|
800 | $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd` | |
801 | $ f -s $datafilepath |
|
801 | $ f -s $datafilepath | |
802 | corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
802 | corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) | |
803 | $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp status=noxfer |
|
803 | $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp status=noxfer | |
804 | 10+0 records in |
|
804 | 10+0 records in | |
805 | 10+0 records out |
|
805 | 10+0 records out | |
806 | $ mv $datafilepath-tmp $datafilepath |
|
806 | $ mv $datafilepath-tmp $datafilepath | |
807 | $ f -s $datafilepath |
|
807 | $ f -s $datafilepath | |
808 | corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob) |
|
808 | corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob) | |
809 |
|
809 | |||
810 | Check that Mercurial reaction to this event |
|
810 | Check that Mercurial reaction to this event | |
811 |
|
811 | |||
812 | $ hg -R corruption-test-repo log -r . --traceback |
|
812 | $ hg -R corruption-test-repo log -r . --traceback | |
813 | changeset: 5005:90d5d3ba2fc4 |
|
813 | changeset: 5005:90d5d3ba2fc4 | |
814 | tag: tip |
|
814 | tag: tip | |
815 | user: test |
|
815 | user: test | |
816 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
816 | date: Thu Jan 01 00:00:00 1970 +0000 | |
817 | summary: a2 |
|
817 | summary: a2 | |
818 |
|
818 | |||
819 |
|
819 | |||
820 |
|
820 | |||
821 | stream clone |
|
821 | stream clone | |
822 | ============ |
|
822 | ============ | |
823 |
|
823 | |||
824 | The persistent nodemap should exist after a streaming clone |
|
824 | The persistent nodemap should exist after a streaming clone | |
825 |
|
825 | |||
826 | Simple case |
|
826 | Simple case | |
827 | ----------- |
|
827 | ----------- | |
828 |
|
828 | |||
829 | No race condition |
|
829 | No race condition | |
830 |
|
830 | |||
831 | $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)' |
|
831 | $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)' | |
832 | adding [s] 00manifest.n (62 bytes) |
|
832 | adding [s] 00manifest.n (62 bytes) | |
833 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
833 | adding [s] 00manifest-*.nd (118 KB) (glob) | |
834 | adding [s] 00changelog.n (62 bytes) |
|
834 | adding [s] 00changelog.n (62 bytes) | |
835 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
835 | adding [s] 00changelog-*.nd (118 KB) (glob) | |
836 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
836 | adding [s] 00manifest.d (452 KB) (no-zstd !) | |
837 | adding [s] 00manifest.d (491 KB) (zstd !) |
|
837 | adding [s] 00manifest.d (491 KB) (zstd !) | |
838 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
838 | adding [s] 00changelog.d (360 KB) (no-zstd !) | |
839 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
839 | adding [s] 00changelog.d (368 KB) (zstd !) | |
840 | adding [s] 00manifest.i (313 KB) |
|
840 | adding [s] 00manifest.i (313 KB) | |
841 | adding [s] 00changelog.i (313 KB) |
|
841 | adding [s] 00changelog.i (313 KB) | |
842 | $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
842 | $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' | |
843 | 00changelog-*.nd (glob) |
|
843 | 00changelog-*.nd (glob) | |
844 | 00changelog.n |
|
844 | 00changelog.n | |
845 | 00manifest-*.nd (glob) |
|
845 | 00manifest-*.nd (glob) | |
846 | 00manifest.n |
|
846 | 00manifest.n | |
847 | $ hg -R stream-clone debugnodemap --metadata |
|
847 | $ hg -R stream-clone debugnodemap --metadata | |
848 | uid: * (glob) |
|
848 | uid: * (glob) | |
849 | tip-rev: 5005 |
|
849 | tip-rev: 5005 | |
850 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
850 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
851 | data-length: 121088 |
|
851 | data-length: 121088 | |
852 | data-unused: 0 |
|
852 | data-unused: 0 | |
853 | data-unused: 0.000% |
|
853 | data-unused: 0.000% | |
854 |
|
854 | |||
855 | new data appened |
|
855 | new data appened | |
856 | ----------------- |
|
856 | ----------------- | |
857 |
|
857 | |||
858 | Other commit happening on the server during the stream clone |
|
858 | Other commit happening on the server during the stream clone | |
859 |
|
859 | |||
860 | setup the step-by-step stream cloning |
|
860 | setup the step-by-step stream cloning | |
861 |
|
861 | |||
862 | $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1" |
|
862 | $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1" | |
863 | $ export HG_TEST_STREAM_WALKED_FILE_1 |
|
863 | $ export HG_TEST_STREAM_WALKED_FILE_1 | |
864 | $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2" |
|
864 | $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2" | |
865 | $ export HG_TEST_STREAM_WALKED_FILE_2 |
|
865 | $ export HG_TEST_STREAM_WALKED_FILE_2 | |
866 | $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3" |
|
866 | $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3" | |
867 | $ export HG_TEST_STREAM_WALKED_FILE_3 |
|
867 | $ export HG_TEST_STREAM_WALKED_FILE_3 | |
868 | $ cat << EOF >> test-repo/.hg/hgrc |
|
868 | $ cat << EOF >> test-repo/.hg/hgrc | |
869 | > [extensions] |
|
869 | > [extensions] | |
870 | > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py |
|
870 | > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py | |
871 | > EOF |
|
871 | > EOF | |
872 |
|
872 | |||
873 | Check and record file state beforehand |
|
873 | Check and record file state beforehand | |
874 |
|
874 | |||
875 | $ f --size test-repo/.hg/store/00changelog* |
|
875 | $ f --size test-repo/.hg/store/00changelog* | |
876 | test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
876 | test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) | |
877 | test-repo/.hg/store/00changelog.d: size=376891 (zstd !) |
|
877 | test-repo/.hg/store/00changelog.d: size=376891 (zstd !) | |
878 | test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !) |
|
878 | test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !) | |
879 | test-repo/.hg/store/00changelog.i: size=320384 |
|
879 | test-repo/.hg/store/00changelog.i: size=320384 | |
880 | test-repo/.hg/store/00changelog.n: size=62 |
|
880 | test-repo/.hg/store/00changelog.n: size=62 | |
881 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt |
|
881 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt | |
882 | uid: * (glob) |
|
882 | uid: * (glob) | |
883 | tip-rev: 5005 |
|
883 | tip-rev: 5005 | |
884 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
884 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
885 | data-length: 121088 |
|
885 | data-length: 121088 | |
886 | data-unused: 0 |
|
886 | data-unused: 0 | |
887 | data-unused: 0.000% |
|
887 | data-unused: 0.000% | |
888 |
|
888 | |||
889 | Prepare a commit |
|
889 | Prepare a commit | |
890 |
|
890 | |||
891 | $ echo foo >> test-repo/foo |
|
891 | $ echo foo >> test-repo/foo | |
892 | $ hg -R test-repo/ add test-repo/foo |
|
892 | $ hg -R test-repo/ add test-repo/foo | |
893 |
|
893 | |||
894 | Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time. |
|
894 | Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time. | |
895 |
|
895 | |||
896 | $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone-race-1 --debug 2>> clone-output | egrep '00(changelog|manifest)' >> clone-output; touch $HG_TEST_STREAM_WALKED_FILE_3) & |
|
896 | $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone-race-1 --debug 2>> clone-output | egrep '00(changelog|manifest)' >> clone-output; touch $HG_TEST_STREAM_WALKED_FILE_3) & | |
897 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 |
|
897 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 | |
898 | $ hg -R test-repo/ commit -m foo |
|
898 | $ hg -R test-repo/ commit -m foo | |
899 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 |
|
899 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 | |
900 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 |
|
900 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 | |
901 | $ cat clone-output |
|
901 | $ cat clone-output | |
902 | adding [s] 00manifest.n (62 bytes) |
|
902 | adding [s] 00manifest.n (62 bytes) | |
903 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
903 | adding [s] 00manifest-*.nd (118 KB) (glob) | |
904 | adding [s] 00changelog.n (62 bytes) |
|
904 | adding [s] 00changelog.n (62 bytes) | |
905 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
905 | adding [s] 00changelog-*.nd (118 KB) (glob) | |
906 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
906 | adding [s] 00manifest.d (452 KB) (no-zstd !) | |
907 | adding [s] 00manifest.d (491 KB) (zstd !) |
|
907 | adding [s] 00manifest.d (491 KB) (zstd !) | |
908 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
908 | adding [s] 00changelog.d (360 KB) (no-zstd !) | |
909 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
909 | adding [s] 00changelog.d (368 KB) (zstd !) | |
910 | adding [s] 00manifest.i (313 KB) |
|
910 | adding [s] 00manifest.i (313 KB) | |
911 | adding [s] 00changelog.i (313 KB) |
|
911 | adding [s] 00changelog.i (313 KB) | |
912 |
|
912 | |||
913 | Check the result state |
|
913 | Check the result state | |
914 |
|
914 | |||
915 | $ f --size stream-clone-race-1/.hg/store/00changelog* |
|
915 | $ f --size stream-clone-race-1/.hg/store/00changelog* | |
916 | stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
916 | stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob) | |
917 | stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !) |
|
917 | stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !) | |
918 | stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd !) |
|
918 | stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd !) | |
919 | stream-clone-race-1/.hg/store/00changelog.i: size=320384 |
|
919 | stream-clone-race-1/.hg/store/00changelog.i: size=320384 | |
920 | stream-clone-race-1/.hg/store/00changelog.n: size=62 |
|
920 | stream-clone-race-1/.hg/store/00changelog.n: size=62 | |
921 |
|
921 | |||
922 | $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt |
|
922 | $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt | |
923 | uid: * (glob) |
|
923 | uid: * (glob) | |
924 | tip-rev: 5005 |
|
924 | tip-rev: 5005 | |
925 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
925 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
926 | data-length: 121088 |
|
926 | data-length: 121088 | |
927 | data-unused: 0 |
|
927 | data-unused: 0 | |
928 | data-unused: 0.000% |
|
928 | data-unused: 0.000% | |
929 |
|
929 | |||
930 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical |
|
930 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical | |
931 | (ie: the following diff should be empty) |
|
931 | (ie: the following diff should be empty) | |
932 |
|
932 | |||
933 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". |
|
933 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". | |
934 |
|
934 | |||
935 | #if no-rust no-pure |
|
935 | #if no-rust no-pure | |
936 | $ diff -u server-metadata.txt client-metadata.txt |
|
936 | $ diff -u server-metadata.txt client-metadata.txt | |
937 | --- server-metadata.txt * (glob) |
|
937 | --- server-metadata.txt * (glob) | |
938 | +++ client-metadata.txt * (glob) |
|
938 | +++ client-metadata.txt * (glob) | |
939 | @@ -1,4 +1,4 @@ |
|
939 | @@ -1,4 +1,4 @@ | |
940 | -uid: * (glob) |
|
940 | -uid: * (glob) | |
941 | +uid: * (glob) |
|
941 | +uid: * (glob) | |
942 | tip-rev: 5005 |
|
942 | tip-rev: 5005 | |
943 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
943 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe | |
944 | data-length: 121088 |
|
944 | data-length: 121088 | |
945 | [1] |
|
945 | [1] | |
946 | #else |
|
946 | #else | |
947 | $ diff -u server-metadata.txt client-metadata.txt |
|
947 | $ diff -u server-metadata.txt client-metadata.txt | |
948 | #endif |
|
948 | #endif | |
949 |
|
949 | |||
950 |
|
950 | |||
951 | Clean up after the test. |
|
951 | Clean up after the test. | |
952 |
|
952 | |||
953 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1" |
|
953 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1" | |
954 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2" |
|
954 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2" | |
955 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3" |
|
955 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3" | |
956 |
|
956 | |||
957 | full regeneration |
|
957 | full regeneration | |
958 | ----------------- |
|
958 | ----------------- | |
959 |
|
959 | |||
960 | A full nodemap is generated |
|
960 | A full nodemap is generated | |
961 |
|
961 | |||
962 | (ideally this test would append enough data to make sure the nodemap data file |
|
962 | (ideally this test would append enough data to make sure the nodemap data file | |
963 | get changed, however to make thing simpler we will force the regeneration for |
|
963 | get changed, however to make thing simpler we will force the regeneration for | |
964 | this test. |
|
964 | this test. | |
965 |
|
965 | |||
966 | Check the initial state |
|
966 | Check the initial state | |
967 |
|
967 | |||
968 | $ f --size test-repo/.hg/store/00changelog* |
|
968 | $ f --size test-repo/.hg/store/00changelog* | |
969 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) |
|
969 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) | |
970 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) |
|
970 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) | |
971 | test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) |
|
971 | test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) | |
972 | test-repo/.hg/store/00changelog.d: size=376950 (zstd !) |
|
972 | test-repo/.hg/store/00changelog.d: size=376950 (zstd !) | |
973 | test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !) |
|
973 | test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !) | |
974 | test-repo/.hg/store/00changelog.i: size=320448 |
|
974 | test-repo/.hg/store/00changelog.i: size=320448 | |
975 | test-repo/.hg/store/00changelog.n: size=62 |
|
975 | test-repo/.hg/store/00changelog.n: size=62 | |
976 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt |
|
976 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt | |
977 | uid: * (glob) |
|
977 | uid: * (glob) | |
978 | tip-rev: 5006 |
|
978 | tip-rev: 5006 | |
979 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
979 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b | |
980 | data-length: 121344 (rust !) |
|
980 | data-length: 121344 (rust !) | |
981 | data-length: 121344 (pure !) |
|
981 | data-length: 121344 (pure !) | |
982 | data-length: 121152 (no-rust no-pure !) |
|
982 | data-length: 121152 (no-rust no-pure !) | |
983 | data-unused: 192 (rust !) |
|
983 | data-unused: 192 (rust !) | |
984 | data-unused: 192 (pure !) |
|
984 | data-unused: 192 (pure !) | |
985 | data-unused: 0 (no-rust no-pure !) |
|
985 | data-unused: 0 (no-rust no-pure !) | |
986 | data-unused: 0.158% (rust !) |
|
986 | data-unused: 0.158% (rust !) | |
987 | data-unused: 0.158% (pure !) |
|
987 | data-unused: 0.158% (pure !) | |
988 | data-unused: 0.000% (no-rust no-pure !) |
|
988 | data-unused: 0.000% (no-rust no-pure !) | |
989 |
|
989 | |||
990 | Performe the mix of clone and full refresh of the nodemap, so that the files |
|
990 | Performe the mix of clone and full refresh of the nodemap, so that the files | |
991 | (and filenames) are different between listing time and actual transfer time. |
|
991 | (and filenames) are different between listing time and actual transfer time. | |
992 |
|
992 | |||
993 | $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone-race-2 --debug 2>> clone-output-2 | egrep '00(changelog|manifest)' >> clone-output-2; touch $HG_TEST_STREAM_WALKED_FILE_3) & |
|
993 | $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone-race-2 --debug 2>> clone-output-2 | egrep '00(changelog|manifest)' >> clone-output-2; touch $HG_TEST_STREAM_WALKED_FILE_3) & | |
994 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 |
|
994 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 | |
995 | $ rm test-repo/.hg/store/00changelog.n |
|
995 | $ rm test-repo/.hg/store/00changelog.n | |
996 | $ rm test-repo/.hg/store/00changelog-*.nd |
|
996 | $ rm test-repo/.hg/store/00changelog-*.nd | |
997 | $ hg -R test-repo/ debugupdatecache |
|
997 | $ hg -R test-repo/ debugupdatecache | |
998 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 |
|
998 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 | |
999 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 |
|
999 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 | |
|
1000 | ||||
|
1001 | (note: the stream clone code wronly pick the `undo.` files) | |||
|
1002 | ||||
1000 | $ cat clone-output-2 |
|
1003 | $ cat clone-output-2 | |
|
1004 | adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !) | |||
|
1005 | adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !) | |||
1001 | adding [s] 00manifest.n (62 bytes) |
|
1006 | adding [s] 00manifest.n (62 bytes) | |
1002 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
1007 | adding [s] 00manifest-*.nd (118 KB) (glob) | |
1003 | adding [s] 00changelog.n (62 bytes) |
|
1008 | adding [s] 00changelog.n (62 bytes) | |
1004 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
1009 | adding [s] 00changelog-*.nd (118 KB) (glob) | |
1005 | adding [s] 00manifest.d (492 KB) (zstd !) |
|
1010 | adding [s] 00manifest.d (492 KB) (zstd !) | |
1006 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
1011 | adding [s] 00manifest.d (452 KB) (no-zstd !) | |
1007 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
1012 | adding [s] 00changelog.d (360 KB) (no-zstd !) | |
1008 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
1013 | adding [s] 00changelog.d (368 KB) (zstd !) | |
1009 | adding [s] 00manifest.i (313 KB) |
|
1014 | adding [s] 00manifest.i (313 KB) | |
1010 | adding [s] 00changelog.i (313 KB) |
|
1015 | adding [s] 00changelog.i (313 KB) | |
1011 |
|
1016 | |||
1012 | Check the result. |
|
1017 | Check the result. | |
1013 |
|
1018 | |||
1014 | $ f --size stream-clone-race-2/.hg/store/00changelog* |
|
1019 | $ f --size stream-clone-race-2/.hg/store/00changelog* | |
1015 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) |
|
1020 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) | |
1016 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) |
|
1021 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) | |
1017 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) |
|
1022 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) | |
1018 | stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd !) |
|
1023 | stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd !) | |
1019 | stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !) |
|
1024 | stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !) | |
1020 | stream-clone-race-2/.hg/store/00changelog.i: size=320448 |
|
1025 | stream-clone-race-2/.hg/store/00changelog.i: size=320448 | |
1021 | stream-clone-race-2/.hg/store/00changelog.n: size=62 |
|
1026 | stream-clone-race-2/.hg/store/00changelog.n: size=62 | |
1022 |
|
1027 | |||
1023 | $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt |
|
1028 | $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt | |
1024 | uid: * (glob) |
|
1029 | uid: * (glob) | |
1025 | tip-rev: 5006 |
|
1030 | tip-rev: 5006 | |
1026 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
1031 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b | |
1027 | data-length: 121344 (rust !) |
|
1032 | data-length: 121344 (rust !) | |
1028 | data-unused: 192 (rust !) |
|
1033 | data-unused: 192 (rust !) | |
1029 | data-unused: 0.158% (rust !) |
|
1034 | data-unused: 0.158% (rust !) | |
1030 | data-length: 121152 (no-rust no-pure !) |
|
1035 | data-length: 121152 (no-rust no-pure !) | |
1031 | data-unused: 0 (no-rust no-pure !) |
|
1036 | data-unused: 0 (no-rust no-pure !) | |
1032 | data-unused: 0.000% (no-rust no-pure !) |
|
1037 | data-unused: 0.000% (no-rust no-pure !) | |
1033 | data-length: 121344 (pure !) |
|
1038 | data-length: 121344 (pure !) | |
1034 | data-unused: 192 (pure !) |
|
1039 | data-unused: 192 (pure !) | |
1035 | data-unused: 0.158% (pure !) |
|
1040 | data-unused: 0.158% (pure !) | |
1036 |
|
1041 | |||
1037 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical |
|
1042 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical | |
1038 | (ie: the following diff should be empty) |
|
1043 | (ie: the following diff should be empty) | |
1039 |
|
1044 | |||
1040 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". |
|
1045 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". | |
1041 |
|
1046 | |||
1042 | #if no-rust no-pure |
|
1047 | #if no-rust no-pure | |
1043 | $ diff -u server-metadata-2.txt client-metadata-2.txt |
|
1048 | $ diff -u server-metadata-2.txt client-metadata-2.txt | |
1044 | --- server-metadata-2.txt * (glob) |
|
1049 | --- server-metadata-2.txt * (glob) | |
1045 | +++ client-metadata-2.txt * (glob) |
|
1050 | +++ client-metadata-2.txt * (glob) | |
1046 | @@ -1,4 +1,4 @@ |
|
1051 | @@ -1,4 +1,4 @@ | |
1047 | -uid: * (glob) |
|
1052 | -uid: * (glob) | |
1048 | +uid: * (glob) |
|
1053 | +uid: * (glob) | |
1049 | tip-rev: 5006 |
|
1054 | tip-rev: 5006 | |
1050 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
1055 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b | |
1051 | data-length: 121152 |
|
1056 | data-length: 121152 | |
1052 | [1] |
|
1057 | [1] | |
1053 | #else |
|
1058 | #else | |
1054 | $ diff -u server-metadata-2.txt client-metadata-2.txt |
|
1059 | $ diff -u server-metadata-2.txt client-metadata-2.txt | |
1055 | #endif |
|
1060 | #endif | |
1056 |
|
1061 | |||
1057 | Clean up after the test |
|
1062 | Clean up after the test | |
1058 |
|
1063 | |||
1059 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_1 |
|
1064 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_1 | |
1060 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_2 |
|
1065 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_2 | |
1061 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_3 |
|
1066 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_3 | |
1062 |
|
1067 |
General Comments 0
You need to be logged in to leave comments.
Login now