##// END OF EJS Templates
walk: no longer ignore revlogs of files starting with `undo.` (issue6542)...
marmoute -
r48459:f030c7d2 default
parent child Browse files
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) and EXCLUDED.match(f) is None:
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 2 changesets with 1025 changes to 1025 files
214 added 3 changesets with 1086 changes to 1086 files
84 new changesets 96ee1d7354c4:c17445101a72
215 new changesets 96ee1d7354c4:7406a3463c3d
85
216
86 $ 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"
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 2 changesets with 1025 changes to 1025 files
281 added 3 changesets with 1086 changes to 1086 files
151 new changesets 96ee1d7354c4:c17445101a72
282 new changesets 96ee1d7354c4:7406a3463c3d
152
283
153 $ 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"
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
312 1088 files to transfer, 101 KB of data (no-zstd !)
182 transferred 96.3 KB in * seconds (*/sec) (glob) (no-zstd !)
313 transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !)
183 1027 files to transfer, 93.5 KB of data (zstd !)
314 1088 files to transfer, 98.4 KB of data (zstd !)
184 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1030 files to transfer, 96.5 KB of data (no-zstd !)
323 1091 files to transfer, 101 KB of data (no-zstd !)
193 transferred 96.5 KB in * seconds (*/sec) (glob) (no-zstd !)
324 transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !)
194 1030 files to transfer, 93.6 KB of data (zstd !)
325 1091 files to transfer, 98.5 KB of data (zstd !)
195 transferred 93.6 KB in * seconds (* */sec) (glob) (zstd !)
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=112262
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: 7f 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
353 0010: 80 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
223 0020: 05 09 04 0c 44 62 79 74 65 63 6f 75 6e 74 39 38 |....Dbytecount98|
354 0020: 06 09 04 0c 44 62 79 74 65 63 6f 75 6e 74 31 30 |....Dbytecount10|
224 0030: 37 37 35 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |775filecount1030|
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 65 |requirementsdote|
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 25 |ncode%2Cfncache%|
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 32 |2Cgeneraldelta%2|
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 72 |Crevlogv1%2Cspar|
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 65 |serevlog%2Cstore|
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 00 |....s.Bdata/0.i.|
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 00 |................|
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 80 |................|
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 69 |)c.I.#....Vg.g,i|
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 75 |..9............u|
365 00d0: 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 |i..9............|
235 00e0: 30 73 08 42 64 61 74 61 2f 31 2e 69 00 03 00 01 |0s.Bdata/1.i....|
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=109410
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: 99 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
373 0010: 9a 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
243 0020: 05 09 04 0c 5e 62 79 74 65 63 6f 75 6e 74 39 35 |....^bytecount95|
374 0020: 06 09 04 0c 5e 62 79 74 65 63 6f 75 6e 74 31 30 |....^bytecount10|
244 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030|
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 65 |requirementsdote|
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 25 |ncode%2Cfncache%|
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 32 |2Cgeneraldelta%2|
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 73 |Crevlog-compress|
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 6f |ion-zstd%2Crevlo|
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 6c |gv1%2Csparserevl|
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 08 |og%2Cstore....s.|
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 00 |Bdata/0.i.......|
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 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 23 |..........)c.I.#|
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 00 |....Vg.g,i..9...|
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 08 42 64 61 |.........u0s.Bda|
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=109431
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: ae 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
393 0010: af 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
263 0020: 05 09 04 0c 73 62 79 74 65 63 6f 75 6e 74 39 35 |....sbytecount95|
394 0020: 06 09 04 0c 73 62 79 74 65 63 6f 75 6e 74 31 30 |....sbytecount10|
264 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030|
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 65 |requirementsdote|
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 25 |ncode%2Cfncache%|
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 32 |2Cgeneraldelta%2|
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 65 |Cpersistent-node|
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 6d |map%2Crevlog-com|
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 43 |pression-zstd%2C|
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 73 |revlogv1%2Cspars|
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 00 |erevlog%2Cstore.|
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 03 |...s.Bdata/0.i..|
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 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 29 |...............)|
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 d1 |c.I.#....Vg.g,i.|
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
435 1088 files to transfer, 101 KB of data (no-zstd !)
305 transferred 96.3 KB in * seconds (*/sec) (glob) (no-zstd !)
436 transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !)
306 1027 files to transfer, 93.5 KB of data (zstd !)
437 1088 files to transfer, 98.4 KB of data (zstd !)
307 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1030 files to transfer, 96.5 KB of data (no-zstd !)
445 1091 files to transfer, 101 KB of data (no-zstd !)
315 transferred 96.5 KB in * seconds (* */sec) (glob) (no-zstd !)
446 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
316 1030 files to transfer, 93.6 KB of data (zstd !)
447 1091 files to transfer, 98.5 KB of data (zstd !)
317 transferred 93.6 KB in * seconds (* */sec) (glob) (zstd !)
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
460 1088 files to transfer, 101 KB of data (no-zstd !)
330 1027 files to transfer, 93.5 KB of data (zstd !)
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 96.3 KB in * seconds (*/sec) (glob) (no-zstd !)
464 transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !)
334 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1030 files to transfer, 96.5 KB of data (no-zstd !)
492 1091 files to transfer, 101 KB of data (no-zstd !)
362 1030 files to transfer, 93.6 KB of data (zstd !)
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 96.5 KB in * seconds (* */sec) (glob) (no-zstd !)
497 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
367 bundle2-input-part: total payload size 112094 (no-zstd !)
498 bundle2-input-part: total payload size 118382 (no-zstd !)
368 transferred 93.6 KB in * seconds (* */sec) (glob) (zstd !)
499 transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !)
369 bundle2-input-part: total payload size 109216 (zstd !)
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 1 changesets with 1 changes to 1 files
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
532 1088 files to transfer, 101 KB of data (no-zstd !)
402 transferred 96.3 KB in * seconds (*/sec) (glob) (no-zstd !)
533 transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !)
403 1027 files to transfer, 93.5 KB of data (zstd !)
534 1088 files to transfer, 98.4 KB of data (zstd !)
404 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1030 files to transfer, 96.5 KB of data (no-zstd !)
542 1091 files to transfer, 101 KB of data (no-zstd !)
412 transferred 96.5 KB in * seconds (* */sec) (glob) (no-zstd !)
543 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
413 1030 files to transfer, 93.6 KB of data (zstd !)
544 1091 files to transfer, 98.5 KB of data (zstd !)
414 transferred 93.6 KB in * seconds (* */sec) (glob) (zstd !)
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 1 changesets with 1 changes to 1 files
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 1 changesets with 1 changes to 1 files
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
684 1088 files to transfer, 101 KB of data (no-zstd !)
554 transferred 96.3 KB in * seconds (*) (glob) (no-zstd !)
685 transferred 101 KB in * seconds (*) (glob) (no-zstd !)
555 1027 files to transfer, 93.5 KB of data (zstd !)
686 1088 files to transfer, 98.4 KB of data (zstd !)
556 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1033 files to transfer, 96.6 KB of data (no-zstd !)
696 1094 files to transfer, 101 KB of data (no-zstd !)
566 transferred 96.6 KB in * seconds (* */sec) (glob) (no-zstd !)
697 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
567 1033 files to transfer, 93.8 KB of data (zstd !)
698 1094 files to transfer, 98.7 KB of data (zstd !)
568 transferred 93.8 KB in * seconds (* */sec) (glob) (zstd !)
699 transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !)
569 updating to branch default
700 updating to branch default
570 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1:c17445101a72
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
725 1088 files to transfer, 101 KB of data (no-zstd !)
588 transferred 96.3 KB in * seconds (*) (glob) (no-zstd !)
726 transferred 101 KB in * seconds (*) (glob) (no-zstd !)
589 1027 files to transfer, 93.5 KB of data (zstd !)
727 1088 files to transfer, 98.4 KB of data (zstd !)
590 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1033 files to transfer, 96.6 KB of data (no-zstd !)
737 1094 files to transfer, 101 KB of data (no-zstd !)
600 transferred 96.6 KB in * seconds (* */sec) (glob) (no-zstd !)
738 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
601 1033 files to transfer, 93.8 KB of data (zstd !)
739 1094 files to transfer, 98.7 KB of data (zstd !)
602 transferred 93.8 KB in * seconds (* */sec) (glob) (zstd !)
740 transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !)
603 updating to branch default
741 updating to branch default
604 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1027 files to transfer, 96.3 KB of data (no-zstd !)
772 1088 files to transfer, 101 KB of data (no-zstd !)
628 transferred 96.3 KB in * seconds (* */sec) (glob) (no-zstd !)
773 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
629 1027 files to transfer, 93.5 KB of data (zstd !)
774 1088 files to transfer, 98.4 KB of data (zstd !)
630 transferred 93.5 KB in * seconds (* */sec) (glob) (zstd !)
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 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1034 files to transfer, 96.7 KB of data (no-zstd !)
788 1095 files to transfer, 101 KB of data (no-zstd !)
643 transferred 96.7 KB in * seconds (* */sec) (glob) (no-zstd !)
789 transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !)
644 1034 files to transfer, 93.9 KB of data (zstd !)
790 1095 files to transfer, 98.7 KB of data (zstd !)
645 transferred 93.9 KB in * seconds (* */sec) (glob) (zstd !)
791 transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !)
646 updating to branch default
792 updating to branch default
647 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 1035 files to transfer, 97.1 KB of data (no-zstd !)
843 1096 files to transfer, 102 KB of data (no-zstd !)
690 transferred 97.1 KB in * seconds (* */sec) (glob) (no-zstd !)
844 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
691 1035 files to transfer, 94.3 KB of data (zstd !)
845 1096 files to transfer, 99.1 KB of data (zstd !)
692 transferred 94.3 KB in * seconds (* */sec) (glob) (zstd !)
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 $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution
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