##// END OF EJS Templates
verify: also check dirstate...
Raphaël Gomès -
r50721:c84844cd default
parent child Browse files
Show More
@@ -1,4743 +1,4738 b''
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2016 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
8
9 import binascii
9 import binascii
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import contextlib
12 import contextlib
13 import difflib
13 import difflib
14 import errno
14 import errno
15 import glob
15 import glob
16 import operator
16 import operator
17 import os
17 import os
18 import platform
18 import platform
19 import random
19 import random
20 import re
20 import re
21 import socket
21 import socket
22 import ssl
22 import ssl
23 import stat
23 import stat
24 import subprocess
24 import subprocess
25 import sys
25 import sys
26 import time
26 import time
27
27
28 from .i18n import _
28 from .i18n import _
29 from .node import (
29 from .node import (
30 bin,
30 bin,
31 hex,
31 hex,
32 nullrev,
32 nullrev,
33 short,
33 short,
34 )
34 )
35 from .pycompat import (
35 from .pycompat import (
36 getattr,
36 getattr,
37 open,
37 open,
38 )
38 )
39 from . import (
39 from . import (
40 bundle2,
40 bundle2,
41 bundlerepo,
41 bundlerepo,
42 changegroup,
42 changegroup,
43 cmdutil,
43 cmdutil,
44 color,
44 color,
45 context,
45 context,
46 copies,
46 copies,
47 dagparser,
47 dagparser,
48 dirstateutils,
48 dirstateutils,
49 encoding,
49 encoding,
50 error,
50 error,
51 exchange,
51 exchange,
52 extensions,
52 extensions,
53 filemerge,
53 filemerge,
54 filesetlang,
54 filesetlang,
55 formatter,
55 formatter,
56 hg,
56 hg,
57 httppeer,
57 httppeer,
58 localrepo,
58 localrepo,
59 lock as lockmod,
59 lock as lockmod,
60 logcmdutil,
60 logcmdutil,
61 mergestate as mergestatemod,
61 mergestate as mergestatemod,
62 metadata,
62 metadata,
63 obsolete,
63 obsolete,
64 obsutil,
64 obsutil,
65 pathutil,
65 pathutil,
66 phases,
66 phases,
67 policy,
67 policy,
68 pvec,
68 pvec,
69 pycompat,
69 pycompat,
70 registrar,
70 registrar,
71 repair,
71 repair,
72 repoview,
72 repoview,
73 requirements,
73 requirements,
74 revlog,
74 revlog,
75 revset,
75 revset,
76 revsetlang,
76 revsetlang,
77 scmutil,
77 scmutil,
78 setdiscovery,
78 setdiscovery,
79 simplemerge,
79 simplemerge,
80 sshpeer,
80 sshpeer,
81 sslutil,
81 sslutil,
82 streamclone,
82 streamclone,
83 strip,
83 strip,
84 tags as tagsmod,
84 tags as tagsmod,
85 templater,
85 templater,
86 treediscovery,
86 treediscovery,
87 upgrade,
87 upgrade,
88 url as urlmod,
88 url as urlmod,
89 util,
89 util,
90 verify,
90 vfs as vfsmod,
91 vfs as vfsmod,
91 wireprotoframing,
92 wireprotoframing,
92 wireprotoserver,
93 wireprotoserver,
93 )
94 )
94 from .interfaces import repository
95 from .interfaces import repository
95 from .utils import (
96 from .utils import (
96 cborutil,
97 cborutil,
97 compression,
98 compression,
98 dateutil,
99 dateutil,
99 procutil,
100 procutil,
100 stringutil,
101 stringutil,
101 urlutil,
102 urlutil,
102 )
103 )
103
104
104 from .revlogutils import (
105 from .revlogutils import (
105 constants as revlog_constants,
106 constants as revlog_constants,
106 debug as revlog_debug,
107 debug as revlog_debug,
107 deltas as deltautil,
108 deltas as deltautil,
108 nodemap,
109 nodemap,
109 rewrite,
110 rewrite,
110 sidedata,
111 sidedata,
111 )
112 )
112
113
113 release = lockmod.release
114 release = lockmod.release
114
115
115 table = {}
116 table = {}
116 table.update(strip.command._table)
117 table.update(strip.command._table)
117 command = registrar.command(table)
118 command = registrar.command(table)
118
119
119
120
120 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
121 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
121 def debugancestor(ui, repo, *args):
122 def debugancestor(ui, repo, *args):
122 """find the ancestor revision of two revisions in a given index"""
123 """find the ancestor revision of two revisions in a given index"""
123 if len(args) == 3:
124 if len(args) == 3:
124 index, rev1, rev2 = args
125 index, rev1, rev2 = args
125 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
126 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
126 lookup = r.lookup
127 lookup = r.lookup
127 elif len(args) == 2:
128 elif len(args) == 2:
128 if not repo:
129 if not repo:
129 raise error.Abort(
130 raise error.Abort(
130 _(b'there is no Mercurial repository here (.hg not found)')
131 _(b'there is no Mercurial repository here (.hg not found)')
131 )
132 )
132 rev1, rev2 = args
133 rev1, rev2 = args
133 r = repo.changelog
134 r = repo.changelog
134 lookup = repo.lookup
135 lookup = repo.lookup
135 else:
136 else:
136 raise error.Abort(_(b'either two or three arguments required'))
137 raise error.Abort(_(b'either two or three arguments required'))
137 a = r.ancestor(lookup(rev1), lookup(rev2))
138 a = r.ancestor(lookup(rev1), lookup(rev2))
138 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
139 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
139
140
140
141
141 @command(b'debugantivirusrunning', [])
142 @command(b'debugantivirusrunning', [])
142 def debugantivirusrunning(ui, repo):
143 def debugantivirusrunning(ui, repo):
143 """attempt to trigger an antivirus scanner to see if one is active"""
144 """attempt to trigger an antivirus scanner to see if one is active"""
144 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
145 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
145 f.write(
146 f.write(
146 util.b85decode(
147 util.b85decode(
147 # This is a base85-armored version of the EICAR test file. See
148 # This is a base85-armored version of the EICAR test file. See
148 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
149 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
149 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
150 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
150 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
151 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
151 )
152 )
152 )
153 )
153 # Give an AV engine time to scan the file.
154 # Give an AV engine time to scan the file.
154 time.sleep(2)
155 time.sleep(2)
155 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
156 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
156
157
157
158
158 @command(b'debugapplystreamclonebundle', [], b'FILE')
159 @command(b'debugapplystreamclonebundle', [], b'FILE')
159 def debugapplystreamclonebundle(ui, repo, fname):
160 def debugapplystreamclonebundle(ui, repo, fname):
160 """apply a stream clone bundle file"""
161 """apply a stream clone bundle file"""
161 f = hg.openpath(ui, fname)
162 f = hg.openpath(ui, fname)
162 gen = exchange.readbundle(ui, f, fname)
163 gen = exchange.readbundle(ui, f, fname)
163 gen.apply(repo)
164 gen.apply(repo)
164
165
165
166
166 @command(
167 @command(
167 b'debugbuilddag',
168 b'debugbuilddag',
168 [
169 [
169 (
170 (
170 b'm',
171 b'm',
171 b'mergeable-file',
172 b'mergeable-file',
172 None,
173 None,
173 _(b'add single file mergeable changes'),
174 _(b'add single file mergeable changes'),
174 ),
175 ),
175 (
176 (
176 b'o',
177 b'o',
177 b'overwritten-file',
178 b'overwritten-file',
178 None,
179 None,
179 _(b'add single file all revs overwrite'),
180 _(b'add single file all revs overwrite'),
180 ),
181 ),
181 (b'n', b'new-file', None, _(b'add new file at each rev')),
182 (b'n', b'new-file', None, _(b'add new file at each rev')),
182 (
183 (
183 b'',
184 b'',
184 b'from-existing',
185 b'from-existing',
185 None,
186 None,
186 _(b'continue from a non-empty repository'),
187 _(b'continue from a non-empty repository'),
187 ),
188 ),
188 ],
189 ],
189 _(b'[OPTION]... [TEXT]'),
190 _(b'[OPTION]... [TEXT]'),
190 )
191 )
191 def debugbuilddag(
192 def debugbuilddag(
192 ui,
193 ui,
193 repo,
194 repo,
194 text=None,
195 text=None,
195 mergeable_file=False,
196 mergeable_file=False,
196 overwritten_file=False,
197 overwritten_file=False,
197 new_file=False,
198 new_file=False,
198 from_existing=False,
199 from_existing=False,
199 ):
200 ):
200 """builds a repo with a given DAG from scratch in the current empty repo
201 """builds a repo with a given DAG from scratch in the current empty repo
201
202
202 The description of the DAG is read from stdin if not given on the
203 The description of the DAG is read from stdin if not given on the
203 command line.
204 command line.
204
205
205 Elements:
206 Elements:
206
207
207 - "+n" is a linear run of n nodes based on the current default parent
208 - "+n" is a linear run of n nodes based on the current default parent
208 - "." is a single node based on the current default parent
209 - "." is a single node based on the current default parent
209 - "$" resets the default parent to null (implied at the start);
210 - "$" resets the default parent to null (implied at the start);
210 otherwise the default parent is always the last node created
211 otherwise the default parent is always the last node created
211 - "<p" sets the default parent to the backref p
212 - "<p" sets the default parent to the backref p
212 - "*p" is a fork at parent p, which is a backref
213 - "*p" is a fork at parent p, which is a backref
213 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
214 - "/p2" is a merge of the preceding node and p2
215 - "/p2" is a merge of the preceding node and p2
215 - ":tag" defines a local tag for the preceding node
216 - ":tag" defines a local tag for the preceding node
216 - "@branch" sets the named branch for subsequent nodes
217 - "@branch" sets the named branch for subsequent nodes
217 - "#...\\n" is a comment up to the end of the line
218 - "#...\\n" is a comment up to the end of the line
218
219
219 Whitespace between the above elements is ignored.
220 Whitespace between the above elements is ignored.
220
221
221 A backref is either
222 A backref is either
222
223
223 - a number n, which references the node curr-n, where curr is the current
224 - a number n, which references the node curr-n, where curr is the current
224 node, or
225 node, or
225 - the name of a local tag you placed earlier using ":tag", or
226 - the name of a local tag you placed earlier using ":tag", or
226 - empty to denote the default parent.
227 - empty to denote the default parent.
227
228
228 All string valued-elements are either strictly alphanumeric, or must
229 All string valued-elements are either strictly alphanumeric, or must
229 be enclosed in double quotes ("..."), with "\\" as escape character.
230 be enclosed in double quotes ("..."), with "\\" as escape character.
230 """
231 """
231
232
232 if text is None:
233 if text is None:
233 ui.status(_(b"reading DAG from stdin\n"))
234 ui.status(_(b"reading DAG from stdin\n"))
234 text = ui.fin.read()
235 text = ui.fin.read()
235
236
236 cl = repo.changelog
237 cl = repo.changelog
237 if len(cl) > 0 and not from_existing:
238 if len(cl) > 0 and not from_existing:
238 raise error.Abort(_(b'repository is not empty'))
239 raise error.Abort(_(b'repository is not empty'))
239
240
240 # determine number of revs in DAG
241 # determine number of revs in DAG
241 total = 0
242 total = 0
242 for type, data in dagparser.parsedag(text):
243 for type, data in dagparser.parsedag(text):
243 if type == b'n':
244 if type == b'n':
244 total += 1
245 total += 1
245
246
246 if mergeable_file:
247 if mergeable_file:
247 linesperrev = 2
248 linesperrev = 2
248 # make a file with k lines per rev
249 # make a file with k lines per rev
249 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
250 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
250 initialmergedlines.append(b"")
251 initialmergedlines.append(b"")
251
252
252 tags = []
253 tags = []
253 progress = ui.makeprogress(
254 progress = ui.makeprogress(
254 _(b'building'), unit=_(b'revisions'), total=total
255 _(b'building'), unit=_(b'revisions'), total=total
255 )
256 )
256 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
257 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
257 at = -1
258 at = -1
258 atbranch = b'default'
259 atbranch = b'default'
259 nodeids = []
260 nodeids = []
260 id = 0
261 id = 0
261 progress.update(id)
262 progress.update(id)
262 for type, data in dagparser.parsedag(text):
263 for type, data in dagparser.parsedag(text):
263 if type == b'n':
264 if type == b'n':
264 ui.note((b'node %s\n' % pycompat.bytestr(data)))
265 ui.note((b'node %s\n' % pycompat.bytestr(data)))
265 id, ps = data
266 id, ps = data
266
267
267 files = []
268 files = []
268 filecontent = {}
269 filecontent = {}
269
270
270 p2 = None
271 p2 = None
271 if mergeable_file:
272 if mergeable_file:
272 fn = b"mf"
273 fn = b"mf"
273 p1 = repo[ps[0]]
274 p1 = repo[ps[0]]
274 if len(ps) > 1:
275 if len(ps) > 1:
275 p2 = repo[ps[1]]
276 p2 = repo[ps[1]]
276 pa = p1.ancestor(p2)
277 pa = p1.ancestor(p2)
277 base, local, other = [
278 base, local, other = [
278 x[fn].data() for x in (pa, p1, p2)
279 x[fn].data() for x in (pa, p1, p2)
279 ]
280 ]
280 m3 = simplemerge.Merge3Text(base, local, other)
281 m3 = simplemerge.Merge3Text(base, local, other)
281 ml = [
282 ml = [
282 l.strip()
283 l.strip()
283 for l in simplemerge.render_minimized(m3)[0]
284 for l in simplemerge.render_minimized(m3)[0]
284 ]
285 ]
285 ml.append(b"")
286 ml.append(b"")
286 elif at > 0:
287 elif at > 0:
287 ml = p1[fn].data().split(b"\n")
288 ml = p1[fn].data().split(b"\n")
288 else:
289 else:
289 ml = initialmergedlines
290 ml = initialmergedlines
290 ml[id * linesperrev] += b" r%i" % id
291 ml[id * linesperrev] += b" r%i" % id
291 mergedtext = b"\n".join(ml)
292 mergedtext = b"\n".join(ml)
292 files.append(fn)
293 files.append(fn)
293 filecontent[fn] = mergedtext
294 filecontent[fn] = mergedtext
294
295
295 if overwritten_file:
296 if overwritten_file:
296 fn = b"of"
297 fn = b"of"
297 files.append(fn)
298 files.append(fn)
298 filecontent[fn] = b"r%i\n" % id
299 filecontent[fn] = b"r%i\n" % id
299
300
300 if new_file:
301 if new_file:
301 fn = b"nf%i" % id
302 fn = b"nf%i" % id
302 files.append(fn)
303 files.append(fn)
303 filecontent[fn] = b"r%i\n" % id
304 filecontent[fn] = b"r%i\n" % id
304 if len(ps) > 1:
305 if len(ps) > 1:
305 if not p2:
306 if not p2:
306 p2 = repo[ps[1]]
307 p2 = repo[ps[1]]
307 for fn in p2:
308 for fn in p2:
308 if fn.startswith(b"nf"):
309 if fn.startswith(b"nf"):
309 files.append(fn)
310 files.append(fn)
310 filecontent[fn] = p2[fn].data()
311 filecontent[fn] = p2[fn].data()
311
312
312 def fctxfn(repo, cx, path):
313 def fctxfn(repo, cx, path):
313 if path in filecontent:
314 if path in filecontent:
314 return context.memfilectx(
315 return context.memfilectx(
315 repo, cx, path, filecontent[path]
316 repo, cx, path, filecontent[path]
316 )
317 )
317 return None
318 return None
318
319
319 if len(ps) == 0 or ps[0] < 0:
320 if len(ps) == 0 or ps[0] < 0:
320 pars = [None, None]
321 pars = [None, None]
321 elif len(ps) == 1:
322 elif len(ps) == 1:
322 pars = [nodeids[ps[0]], None]
323 pars = [nodeids[ps[0]], None]
323 else:
324 else:
324 pars = [nodeids[p] for p in ps]
325 pars = [nodeids[p] for p in ps]
325 cx = context.memctx(
326 cx = context.memctx(
326 repo,
327 repo,
327 pars,
328 pars,
328 b"r%i" % id,
329 b"r%i" % id,
329 files,
330 files,
330 fctxfn,
331 fctxfn,
331 date=(id, 0),
332 date=(id, 0),
332 user=b"debugbuilddag",
333 user=b"debugbuilddag",
333 extra={b'branch': atbranch},
334 extra={b'branch': atbranch},
334 )
335 )
335 nodeid = repo.commitctx(cx)
336 nodeid = repo.commitctx(cx)
336 nodeids.append(nodeid)
337 nodeids.append(nodeid)
337 at = id
338 at = id
338 elif type == b'l':
339 elif type == b'l':
339 id, name = data
340 id, name = data
340 ui.note((b'tag %s\n' % name))
341 ui.note((b'tag %s\n' % name))
341 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
342 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
342 elif type == b'a':
343 elif type == b'a':
343 ui.note((b'branch %s\n' % data))
344 ui.note((b'branch %s\n' % data))
344 atbranch = data
345 atbranch = data
345 progress.update(id)
346 progress.update(id)
346
347
347 if tags:
348 if tags:
348 repo.vfs.write(b"localtags", b"".join(tags))
349 repo.vfs.write(b"localtags", b"".join(tags))
349
350
350
351
351 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
352 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
352 indent_string = b' ' * indent
353 indent_string = b' ' * indent
353 if all:
354 if all:
354 ui.writenoi18n(
355 ui.writenoi18n(
355 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
356 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
356 % indent_string
357 % indent_string
357 )
358 )
358
359
359 def showchunks(named):
360 def showchunks(named):
360 ui.write(b"\n%s%s\n" % (indent_string, named))
361 ui.write(b"\n%s%s\n" % (indent_string, named))
361 for deltadata in gen.deltaiter():
362 for deltadata in gen.deltaiter():
362 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
363 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
363 ui.write(
364 ui.write(
364 b"%s%s %s %s %s %s %d\n"
365 b"%s%s %s %s %s %s %d\n"
365 % (
366 % (
366 indent_string,
367 indent_string,
367 hex(node),
368 hex(node),
368 hex(p1),
369 hex(p1),
369 hex(p2),
370 hex(p2),
370 hex(cs),
371 hex(cs),
371 hex(deltabase),
372 hex(deltabase),
372 len(delta),
373 len(delta),
373 )
374 )
374 )
375 )
375
376
376 gen.changelogheader()
377 gen.changelogheader()
377 showchunks(b"changelog")
378 showchunks(b"changelog")
378 gen.manifestheader()
379 gen.manifestheader()
379 showchunks(b"manifest")
380 showchunks(b"manifest")
380 for chunkdata in iter(gen.filelogheader, {}):
381 for chunkdata in iter(gen.filelogheader, {}):
381 fname = chunkdata[b'filename']
382 fname = chunkdata[b'filename']
382 showchunks(fname)
383 showchunks(fname)
383 else:
384 else:
384 if isinstance(gen, bundle2.unbundle20):
385 if isinstance(gen, bundle2.unbundle20):
385 raise error.Abort(_(b'use debugbundle2 for this file'))
386 raise error.Abort(_(b'use debugbundle2 for this file'))
386 gen.changelogheader()
387 gen.changelogheader()
387 for deltadata in gen.deltaiter():
388 for deltadata in gen.deltaiter():
388 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
389 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
389 ui.write(b"%s%s\n" % (indent_string, hex(node)))
390 ui.write(b"%s%s\n" % (indent_string, hex(node)))
390
391
391
392
392 def _debugobsmarkers(ui, part, indent=0, **opts):
393 def _debugobsmarkers(ui, part, indent=0, **opts):
393 """display version and markers contained in 'data'"""
394 """display version and markers contained in 'data'"""
394 opts = pycompat.byteskwargs(opts)
395 opts = pycompat.byteskwargs(opts)
395 data = part.read()
396 data = part.read()
396 indent_string = b' ' * indent
397 indent_string = b' ' * indent
397 try:
398 try:
398 version, markers = obsolete._readmarkers(data)
399 version, markers = obsolete._readmarkers(data)
399 except error.UnknownVersion as exc:
400 except error.UnknownVersion as exc:
400 msg = b"%sunsupported version: %s (%d bytes)\n"
401 msg = b"%sunsupported version: %s (%d bytes)\n"
401 msg %= indent_string, exc.version, len(data)
402 msg %= indent_string, exc.version, len(data)
402 ui.write(msg)
403 ui.write(msg)
403 else:
404 else:
404 msg = b"%sversion: %d (%d bytes)\n"
405 msg = b"%sversion: %d (%d bytes)\n"
405 msg %= indent_string, version, len(data)
406 msg %= indent_string, version, len(data)
406 ui.write(msg)
407 ui.write(msg)
407 fm = ui.formatter(b'debugobsolete', opts)
408 fm = ui.formatter(b'debugobsolete', opts)
408 for rawmarker in sorted(markers):
409 for rawmarker in sorted(markers):
409 m = obsutil.marker(None, rawmarker)
410 m = obsutil.marker(None, rawmarker)
410 fm.startitem()
411 fm.startitem()
411 fm.plain(indent_string)
412 fm.plain(indent_string)
412 cmdutil.showmarker(fm, m)
413 cmdutil.showmarker(fm, m)
413 fm.end()
414 fm.end()
414
415
415
416
416 def _debugphaseheads(ui, data, indent=0):
417 def _debugphaseheads(ui, data, indent=0):
417 """display version and markers contained in 'data'"""
418 """display version and markers contained in 'data'"""
418 indent_string = b' ' * indent
419 indent_string = b' ' * indent
419 headsbyphase = phases.binarydecode(data)
420 headsbyphase = phases.binarydecode(data)
420 for phase in phases.allphases:
421 for phase in phases.allphases:
421 for head in headsbyphase[phase]:
422 for head in headsbyphase[phase]:
422 ui.write(indent_string)
423 ui.write(indent_string)
423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
424 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
424
425
425
426
426 def _quasirepr(thing):
427 def _quasirepr(thing):
427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
428 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
428 return b'{%s}' % (
429 return b'{%s}' % (
429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
430 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
430 )
431 )
431 return pycompat.bytestr(repr(thing))
432 return pycompat.bytestr(repr(thing))
432
433
433
434
434 def _debugbundle2(ui, gen, all=None, **opts):
435 def _debugbundle2(ui, gen, all=None, **opts):
435 """lists the contents of a bundle2"""
436 """lists the contents of a bundle2"""
436 if not isinstance(gen, bundle2.unbundle20):
437 if not isinstance(gen, bundle2.unbundle20):
437 raise error.Abort(_(b'not a bundle2 file'))
438 raise error.Abort(_(b'not a bundle2 file'))
438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
439 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
439 parttypes = opts.get('part_type', [])
440 parttypes = opts.get('part_type', [])
440 for part in gen.iterparts():
441 for part in gen.iterparts():
441 if parttypes and part.type not in parttypes:
442 if parttypes and part.type not in parttypes:
442 continue
443 continue
443 msg = b'%s -- %s (mandatory: %r)\n'
444 msg = b'%s -- %s (mandatory: %r)\n'
444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
445 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
445 if part.type == b'changegroup':
446 if part.type == b'changegroup':
446 version = part.params.get(b'version', b'01')
447 version = part.params.get(b'version', b'01')
447 cg = changegroup.getunbundler(version, part, b'UN')
448 cg = changegroup.getunbundler(version, part, b'UN')
448 if not ui.quiet:
449 if not ui.quiet:
449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
450 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
450 if part.type == b'obsmarkers':
451 if part.type == b'obsmarkers':
451 if not ui.quiet:
452 if not ui.quiet:
452 _debugobsmarkers(ui, part, indent=4, **opts)
453 _debugobsmarkers(ui, part, indent=4, **opts)
453 if part.type == b'phase-heads':
454 if part.type == b'phase-heads':
454 if not ui.quiet:
455 if not ui.quiet:
455 _debugphaseheads(ui, part, indent=4)
456 _debugphaseheads(ui, part, indent=4)
456
457
457
458
458 @command(
459 @command(
459 b'debugbundle',
460 b'debugbundle',
460 [
461 [
461 (b'a', b'all', None, _(b'show all details')),
462 (b'a', b'all', None, _(b'show all details')),
462 (b'', b'part-type', [], _(b'show only the named part type')),
463 (b'', b'part-type', [], _(b'show only the named part type')),
463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
464 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
464 ],
465 ],
465 _(b'FILE'),
466 _(b'FILE'),
466 norepo=True,
467 norepo=True,
467 )
468 )
468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
469 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
469 """lists the contents of a bundle"""
470 """lists the contents of a bundle"""
470 with hg.openpath(ui, bundlepath) as f:
471 with hg.openpath(ui, bundlepath) as f:
471 if spec:
472 if spec:
472 spec = exchange.getbundlespec(ui, f)
473 spec = exchange.getbundlespec(ui, f)
473 ui.write(b'%s\n' % spec)
474 ui.write(b'%s\n' % spec)
474 return
475 return
475
476
476 gen = exchange.readbundle(ui, f, bundlepath)
477 gen = exchange.readbundle(ui, f, bundlepath)
477 if isinstance(gen, bundle2.unbundle20):
478 if isinstance(gen, bundle2.unbundle20):
478 return _debugbundle2(ui, gen, all=all, **opts)
479 return _debugbundle2(ui, gen, all=all, **opts)
479 _debugchangegroup(ui, gen, all=all, **opts)
480 _debugchangegroup(ui, gen, all=all, **opts)
480
481
481
482
482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
483 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
483 def debugcapabilities(ui, path, **opts):
484 def debugcapabilities(ui, path, **opts):
484 """lists the capabilities of a remote peer"""
485 """lists the capabilities of a remote peer"""
485 opts = pycompat.byteskwargs(opts)
486 opts = pycompat.byteskwargs(opts)
486 peer = hg.peer(ui, opts, path)
487 peer = hg.peer(ui, opts, path)
487 try:
488 try:
488 caps = peer.capabilities()
489 caps = peer.capabilities()
489 ui.writenoi18n(b'Main capabilities:\n')
490 ui.writenoi18n(b'Main capabilities:\n')
490 for c in sorted(caps):
491 for c in sorted(caps):
491 ui.write(b' %s\n' % c)
492 ui.write(b' %s\n' % c)
492 b2caps = bundle2.bundle2caps(peer)
493 b2caps = bundle2.bundle2caps(peer)
493 if b2caps:
494 if b2caps:
494 ui.writenoi18n(b'Bundle2 capabilities:\n')
495 ui.writenoi18n(b'Bundle2 capabilities:\n')
495 for key, values in sorted(b2caps.items()):
496 for key, values in sorted(b2caps.items()):
496 ui.write(b' %s\n' % key)
497 ui.write(b' %s\n' % key)
497 for v in values:
498 for v in values:
498 ui.write(b' %s\n' % v)
499 ui.write(b' %s\n' % v)
499 finally:
500 finally:
500 peer.close()
501 peer.close()
501
502
502
503
503 @command(
504 @command(
504 b'debugchangedfiles',
505 b'debugchangedfiles',
505 [
506 [
506 (
507 (
507 b'',
508 b'',
508 b'compute',
509 b'compute',
509 False,
510 False,
510 b"compute information instead of reading it from storage",
511 b"compute information instead of reading it from storage",
511 ),
512 ),
512 ],
513 ],
513 b'REV',
514 b'REV',
514 )
515 )
515 def debugchangedfiles(ui, repo, rev, **opts):
516 def debugchangedfiles(ui, repo, rev, **opts):
516 """list the stored files changes for a revision"""
517 """list the stored files changes for a revision"""
517 ctx = logcmdutil.revsingle(repo, rev, None)
518 ctx = logcmdutil.revsingle(repo, rev, None)
518 files = None
519 files = None
519
520
520 if opts['compute']:
521 if opts['compute']:
521 files = metadata.compute_all_files_changes(ctx)
522 files = metadata.compute_all_files_changes(ctx)
522 else:
523 else:
523 sd = repo.changelog.sidedata(ctx.rev())
524 sd = repo.changelog.sidedata(ctx.rev())
524 files_block = sd.get(sidedata.SD_FILES)
525 files_block = sd.get(sidedata.SD_FILES)
525 if files_block is not None:
526 if files_block is not None:
526 files = metadata.decode_files_sidedata(sd)
527 files = metadata.decode_files_sidedata(sd)
527 if files is not None:
528 if files is not None:
528 for f in sorted(files.touched):
529 for f in sorted(files.touched):
529 if f in files.added:
530 if f in files.added:
530 action = b"added"
531 action = b"added"
531 elif f in files.removed:
532 elif f in files.removed:
532 action = b"removed"
533 action = b"removed"
533 elif f in files.merged:
534 elif f in files.merged:
534 action = b"merged"
535 action = b"merged"
535 elif f in files.salvaged:
536 elif f in files.salvaged:
536 action = b"salvaged"
537 action = b"salvaged"
537 else:
538 else:
538 action = b"touched"
539 action = b"touched"
539
540
540 copy_parent = b""
541 copy_parent = b""
541 copy_source = b""
542 copy_source = b""
542 if f in files.copied_from_p1:
543 if f in files.copied_from_p1:
543 copy_parent = b"p1"
544 copy_parent = b"p1"
544 copy_source = files.copied_from_p1[f]
545 copy_source = files.copied_from_p1[f]
545 elif f in files.copied_from_p2:
546 elif f in files.copied_from_p2:
546 copy_parent = b"p2"
547 copy_parent = b"p2"
547 copy_source = files.copied_from_p2[f]
548 copy_source = files.copied_from_p2[f]
548
549
549 data = (action, copy_parent, f, copy_source)
550 data = (action, copy_parent, f, copy_source)
550 template = b"%-8s %2s: %s, %s;\n"
551 template = b"%-8s %2s: %s, %s;\n"
551 ui.write(template % data)
552 ui.write(template % data)
552
553
553
554
554 @command(b'debugcheckstate', [], b'')
555 @command(b'debugcheckstate', [], b'')
555 def debugcheckstate(ui, repo):
556 def debugcheckstate(ui, repo):
556 """validate the correctness of the current dirstate"""
557 """validate the correctness of the current dirstate"""
557 parent1, parent2 = repo.dirstate.parents()
558 errors = verify.verifier(repo)._verify_dirstate()
558 m1 = repo[parent1].manifest()
559 m2 = repo[parent2].manifest()
560 errors = 0
561 for err in repo.dirstate.verify(m1, m2):
562 ui.warn(err)
563 errors += 1
564 if errors:
559 if errors:
565 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
560 errstr = _(b"dirstate inconsistent with current parent's manifest")
566 raise error.Abort(errstr)
561 raise error.Abort(errstr)
567
562
568
563
569 @command(
564 @command(
570 b'debugcolor',
565 b'debugcolor',
571 [(b'', b'style', None, _(b'show all configured styles'))],
566 [(b'', b'style', None, _(b'show all configured styles'))],
572 b'hg debugcolor',
567 b'hg debugcolor',
573 )
568 )
574 def debugcolor(ui, repo, **opts):
569 def debugcolor(ui, repo, **opts):
575 """show available color, effects or style"""
570 """show available color, effects or style"""
576 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
571 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
577 if opts.get('style'):
572 if opts.get('style'):
578 return _debugdisplaystyle(ui)
573 return _debugdisplaystyle(ui)
579 else:
574 else:
580 return _debugdisplaycolor(ui)
575 return _debugdisplaycolor(ui)
581
576
582
577
583 def _debugdisplaycolor(ui):
578 def _debugdisplaycolor(ui):
584 ui = ui.copy()
579 ui = ui.copy()
585 ui._styles.clear()
580 ui._styles.clear()
586 for effect in color._activeeffects(ui).keys():
581 for effect in color._activeeffects(ui).keys():
587 ui._styles[effect] = effect
582 ui._styles[effect] = effect
588 if ui._terminfoparams:
583 if ui._terminfoparams:
589 for k, v in ui.configitems(b'color'):
584 for k, v in ui.configitems(b'color'):
590 if k.startswith(b'color.'):
585 if k.startswith(b'color.'):
591 ui._styles[k] = k[6:]
586 ui._styles[k] = k[6:]
592 elif k.startswith(b'terminfo.'):
587 elif k.startswith(b'terminfo.'):
593 ui._styles[k] = k[9:]
588 ui._styles[k] = k[9:]
594 ui.write(_(b'available colors:\n'))
589 ui.write(_(b'available colors:\n'))
595 # sort label with a '_' after the other to group '_background' entry.
590 # sort label with a '_' after the other to group '_background' entry.
596 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
591 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
597 for colorname, label in items:
592 for colorname, label in items:
598 ui.write(b'%s\n' % colorname, label=label)
593 ui.write(b'%s\n' % colorname, label=label)
599
594
600
595
601 def _debugdisplaystyle(ui):
596 def _debugdisplaystyle(ui):
602 ui.write(_(b'available style:\n'))
597 ui.write(_(b'available style:\n'))
603 if not ui._styles:
598 if not ui._styles:
604 return
599 return
605 width = max(len(s) for s in ui._styles)
600 width = max(len(s) for s in ui._styles)
606 for label, effects in sorted(ui._styles.items()):
601 for label, effects in sorted(ui._styles.items()):
607 ui.write(b'%s' % label, label=label)
602 ui.write(b'%s' % label, label=label)
608 if effects:
603 if effects:
609 # 50
604 # 50
610 ui.write(b': ')
605 ui.write(b': ')
611 ui.write(b' ' * (max(0, width - len(label))))
606 ui.write(b' ' * (max(0, width - len(label))))
612 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
607 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
613 ui.write(b'\n')
608 ui.write(b'\n')
614
609
615
610
616 @command(b'debugcreatestreamclonebundle', [], b'FILE')
611 @command(b'debugcreatestreamclonebundle', [], b'FILE')
617 def debugcreatestreamclonebundle(ui, repo, fname):
612 def debugcreatestreamclonebundle(ui, repo, fname):
618 """create a stream clone bundle file
613 """create a stream clone bundle file
619
614
620 Stream bundles are special bundles that are essentially archives of
615 Stream bundles are special bundles that are essentially archives of
621 revlog files. They are commonly used for cloning very quickly.
616 revlog files. They are commonly used for cloning very quickly.
622 """
617 """
623 # TODO we may want to turn this into an abort when this functionality
618 # TODO we may want to turn this into an abort when this functionality
624 # is moved into `hg bundle`.
619 # is moved into `hg bundle`.
625 if phases.hassecret(repo):
620 if phases.hassecret(repo):
626 ui.warn(
621 ui.warn(
627 _(
622 _(
628 b'(warning: stream clone bundle will contain secret '
623 b'(warning: stream clone bundle will contain secret '
629 b'revisions)\n'
624 b'revisions)\n'
630 )
625 )
631 )
626 )
632
627
633 requirements, gen = streamclone.generatebundlev1(repo)
628 requirements, gen = streamclone.generatebundlev1(repo)
634 changegroup.writechunks(ui, gen, fname)
629 changegroup.writechunks(ui, gen, fname)
635
630
636 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
631 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
637
632
638
633
639 @command(
634 @command(
640 b'debugdag',
635 b'debugdag',
641 [
636 [
642 (b't', b'tags', None, _(b'use tags as labels')),
637 (b't', b'tags', None, _(b'use tags as labels')),
643 (b'b', b'branches', None, _(b'annotate with branch names')),
638 (b'b', b'branches', None, _(b'annotate with branch names')),
644 (b'', b'dots', None, _(b'use dots for runs')),
639 (b'', b'dots', None, _(b'use dots for runs')),
645 (b's', b'spaces', None, _(b'separate elements by spaces')),
640 (b's', b'spaces', None, _(b'separate elements by spaces')),
646 ],
641 ],
647 _(b'[OPTION]... [FILE [REV]...]'),
642 _(b'[OPTION]... [FILE [REV]...]'),
648 optionalrepo=True,
643 optionalrepo=True,
649 )
644 )
650 def debugdag(ui, repo, file_=None, *revs, **opts):
645 def debugdag(ui, repo, file_=None, *revs, **opts):
651 """format the changelog or an index DAG as a concise textual description
646 """format the changelog or an index DAG as a concise textual description
652
647
653 If you pass a revlog index, the revlog's DAG is emitted. If you list
648 If you pass a revlog index, the revlog's DAG is emitted. If you list
654 revision numbers, they get labeled in the output as rN.
649 revision numbers, they get labeled in the output as rN.
655
650
656 Otherwise, the changelog DAG of the current repo is emitted.
651 Otherwise, the changelog DAG of the current repo is emitted.
657 """
652 """
658 spaces = opts.get('spaces')
653 spaces = opts.get('spaces')
659 dots = opts.get('dots')
654 dots = opts.get('dots')
660 if file_:
655 if file_:
661 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
656 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
662 revs = {int(r) for r in revs}
657 revs = {int(r) for r in revs}
663
658
664 def events():
659 def events():
665 for r in rlog:
660 for r in rlog:
666 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
661 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
667 if r in revs:
662 if r in revs:
668 yield b'l', (r, b"r%i" % r)
663 yield b'l', (r, b"r%i" % r)
669
664
670 elif repo:
665 elif repo:
671 cl = repo.changelog
666 cl = repo.changelog
672 tags = opts.get('tags')
667 tags = opts.get('tags')
673 branches = opts.get('branches')
668 branches = opts.get('branches')
674 if tags:
669 if tags:
675 labels = {}
670 labels = {}
676 for l, n in repo.tags().items():
671 for l, n in repo.tags().items():
677 labels.setdefault(cl.rev(n), []).append(l)
672 labels.setdefault(cl.rev(n), []).append(l)
678
673
679 def events():
674 def events():
680 b = b"default"
675 b = b"default"
681 for r in cl:
676 for r in cl:
682 if branches:
677 if branches:
683 newb = cl.read(cl.node(r))[5][b'branch']
678 newb = cl.read(cl.node(r))[5][b'branch']
684 if newb != b:
679 if newb != b:
685 yield b'a', newb
680 yield b'a', newb
686 b = newb
681 b = newb
687 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
682 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
688 if tags:
683 if tags:
689 ls = labels.get(r)
684 ls = labels.get(r)
690 if ls:
685 if ls:
691 for l in ls:
686 for l in ls:
692 yield b'l', (r, l)
687 yield b'l', (r, l)
693
688
694 else:
689 else:
695 raise error.Abort(_(b'need repo for changelog dag'))
690 raise error.Abort(_(b'need repo for changelog dag'))
696
691
697 for line in dagparser.dagtextlines(
692 for line in dagparser.dagtextlines(
698 events(),
693 events(),
699 addspaces=spaces,
694 addspaces=spaces,
700 wraplabels=True,
695 wraplabels=True,
701 wrapannotations=True,
696 wrapannotations=True,
702 wrapnonlinear=dots,
697 wrapnonlinear=dots,
703 usedots=dots,
698 usedots=dots,
704 maxlinewidth=70,
699 maxlinewidth=70,
705 ):
700 ):
706 ui.write(line)
701 ui.write(line)
707 ui.write(b"\n")
702 ui.write(b"\n")
708
703
709
704
710 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
705 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
711 def debugdata(ui, repo, file_, rev=None, **opts):
706 def debugdata(ui, repo, file_, rev=None, **opts):
712 """dump the contents of a data file revision"""
707 """dump the contents of a data file revision"""
713 opts = pycompat.byteskwargs(opts)
708 opts = pycompat.byteskwargs(opts)
714 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
709 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
715 if rev is not None:
710 if rev is not None:
716 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
711 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
717 file_, rev = None, file_
712 file_, rev = None, file_
718 elif rev is None:
713 elif rev is None:
719 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
714 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
720 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
715 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
721 try:
716 try:
722 ui.write(r.rawdata(r.lookup(rev)))
717 ui.write(r.rawdata(r.lookup(rev)))
723 except KeyError:
718 except KeyError:
724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
719 raise error.Abort(_(b'invalid revision identifier %s') % rev)
725
720
726
721
727 @command(
722 @command(
728 b'debugdate',
723 b'debugdate',
729 [(b'e', b'extended', None, _(b'try extended date formats'))],
724 [(b'e', b'extended', None, _(b'try extended date formats'))],
730 _(b'[-e] DATE [RANGE]'),
725 _(b'[-e] DATE [RANGE]'),
731 norepo=True,
726 norepo=True,
732 optionalrepo=True,
727 optionalrepo=True,
733 )
728 )
734 def debugdate(ui, date, range=None, **opts):
729 def debugdate(ui, date, range=None, **opts):
735 """parse and display a date"""
730 """parse and display a date"""
736 if opts["extended"]:
731 if opts["extended"]:
737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
732 d = dateutil.parsedate(date, dateutil.extendeddateformats)
738 else:
733 else:
739 d = dateutil.parsedate(date)
734 d = dateutil.parsedate(date)
740 ui.writenoi18n(b"internal: %d %d\n" % d)
735 ui.writenoi18n(b"internal: %d %d\n" % d)
741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
736 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
742 if range:
737 if range:
743 m = dateutil.matchdate(range)
738 m = dateutil.matchdate(range)
744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
739 ui.writenoi18n(b"match: %s\n" % m(d[0]))
745
740
746
741
747 @command(
742 @command(
748 b'debugdeltachain',
743 b'debugdeltachain',
749 cmdutil.debugrevlogopts + cmdutil.formatteropts,
744 cmdutil.debugrevlogopts + cmdutil.formatteropts,
750 _(b'-c|-m|FILE'),
745 _(b'-c|-m|FILE'),
751 optionalrepo=True,
746 optionalrepo=True,
752 )
747 )
753 def debugdeltachain(ui, repo, file_=None, **opts):
748 def debugdeltachain(ui, repo, file_=None, **opts):
754 """dump information about delta chains in a revlog
749 """dump information about delta chains in a revlog
755
750
756 Output can be templatized. Available template keywords are:
751 Output can be templatized. Available template keywords are:
757
752
758 :``rev``: revision number
753 :``rev``: revision number
759 :``p1``: parent 1 revision number (for reference)
754 :``p1``: parent 1 revision number (for reference)
760 :``p2``: parent 2 revision number (for reference)
755 :``p2``: parent 2 revision number (for reference)
761 :``chainid``: delta chain identifier (numbered by unique base)
756 :``chainid``: delta chain identifier (numbered by unique base)
762 :``chainlen``: delta chain length to this revision
757 :``chainlen``: delta chain length to this revision
763 :``prevrev``: previous revision in delta chain
758 :``prevrev``: previous revision in delta chain
764 :``deltatype``: role of delta / how it was computed
759 :``deltatype``: role of delta / how it was computed
765 - base: a full snapshot
760 - base: a full snapshot
766 - snap: an intermediate snapshot
761 - snap: an intermediate snapshot
767 - p1: a delta against the first parent
762 - p1: a delta against the first parent
768 - p2: a delta against the second parent
763 - p2: a delta against the second parent
769 - skip1: a delta against the same base as p1
764 - skip1: a delta against the same base as p1
770 (when p1 has empty delta
765 (when p1 has empty delta
771 - skip2: a delta against the same base as p2
766 - skip2: a delta against the same base as p2
772 (when p2 has empty delta
767 (when p2 has empty delta
773 - prev: a delta against the previous revision
768 - prev: a delta against the previous revision
774 - other: a delta against an arbitrary revision
769 - other: a delta against an arbitrary revision
775 :``compsize``: compressed size of revision
770 :``compsize``: compressed size of revision
776 :``uncompsize``: uncompressed size of revision
771 :``uncompsize``: uncompressed size of revision
777 :``chainsize``: total size of compressed revisions in chain
772 :``chainsize``: total size of compressed revisions in chain
778 :``chainratio``: total chain size divided by uncompressed revision size
773 :``chainratio``: total chain size divided by uncompressed revision size
779 (new delta chains typically start at ratio 2.00)
774 (new delta chains typically start at ratio 2.00)
780 :``lindist``: linear distance from base revision in delta chain to end
775 :``lindist``: linear distance from base revision in delta chain to end
781 of this revision
776 of this revision
782 :``extradist``: total size of revisions not part of this delta chain from
777 :``extradist``: total size of revisions not part of this delta chain from
783 base of delta chain to end of this revision; a measurement
778 base of delta chain to end of this revision; a measurement
784 of how much extra data we need to read/seek across to read
779 of how much extra data we need to read/seek across to read
785 the delta chain for this revision
780 the delta chain for this revision
786 :``extraratio``: extradist divided by chainsize; another representation of
781 :``extraratio``: extradist divided by chainsize; another representation of
787 how much unrelated data is needed to load this delta chain
782 how much unrelated data is needed to load this delta chain
788
783
789 If the repository is configured to use the sparse read, additional keywords
784 If the repository is configured to use the sparse read, additional keywords
790 are available:
785 are available:
791
786
792 :``readsize``: total size of data read from the disk for a revision
787 :``readsize``: total size of data read from the disk for a revision
793 (sum of the sizes of all the blocks)
788 (sum of the sizes of all the blocks)
794 :``largestblock``: size of the largest block of data read from the disk
789 :``largestblock``: size of the largest block of data read from the disk
795 :``readdensity``: density of useful bytes in the data read from the disk
790 :``readdensity``: density of useful bytes in the data read from the disk
796 :``srchunks``: in how many data hunks the whole revision would be read
791 :``srchunks``: in how many data hunks the whole revision would be read
797
792
798 The sparse read can be enabled with experimental.sparse-read = True
793 The sparse read can be enabled with experimental.sparse-read = True
799 """
794 """
800 opts = pycompat.byteskwargs(opts)
795 opts = pycompat.byteskwargs(opts)
801 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
796 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
802 index = r.index
797 index = r.index
803 start = r.start
798 start = r.start
804 length = r.length
799 length = r.length
805 generaldelta = r._generaldelta
800 generaldelta = r._generaldelta
806 withsparseread = getattr(r, '_withsparseread', False)
801 withsparseread = getattr(r, '_withsparseread', False)
807
802
808 # security to avoid crash on corrupted revlogs
803 # security to avoid crash on corrupted revlogs
809 total_revs = len(index)
804 total_revs = len(index)
810
805
811 def revinfo(rev):
806 def revinfo(rev):
812 e = index[rev]
807 e = index[rev]
813 compsize = e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
808 compsize = e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
814 uncompsize = e[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
809 uncompsize = e[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
815 chainsize = 0
810 chainsize = 0
816
811
817 base = e[revlog_constants.ENTRY_DELTA_BASE]
812 base = e[revlog_constants.ENTRY_DELTA_BASE]
818 p1 = e[revlog_constants.ENTRY_PARENT_1]
813 p1 = e[revlog_constants.ENTRY_PARENT_1]
819 p2 = e[revlog_constants.ENTRY_PARENT_2]
814 p2 = e[revlog_constants.ENTRY_PARENT_2]
820
815
821 # If the parents of a revision has an empty delta, we never try to delta
816 # If the parents of a revision has an empty delta, we never try to delta
822 # against that parent, but directly against the delta base of that
817 # against that parent, but directly against the delta base of that
823 # parent (recursively). It avoids adding a useless entry in the chain.
818 # parent (recursively). It avoids adding a useless entry in the chain.
824 #
819 #
825 # However we need to detect that as a special case for delta-type, that
820 # However we need to detect that as a special case for delta-type, that
826 # is not simply "other".
821 # is not simply "other".
827 p1_base = p1
822 p1_base = p1
828 if p1 != nullrev and p1 < total_revs:
823 if p1 != nullrev and p1 < total_revs:
829 e1 = index[p1]
824 e1 = index[p1]
830 while e1[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
825 while e1[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
831 new_base = e1[revlog_constants.ENTRY_DELTA_BASE]
826 new_base = e1[revlog_constants.ENTRY_DELTA_BASE]
832 if (
827 if (
833 new_base == p1_base
828 new_base == p1_base
834 or new_base == nullrev
829 or new_base == nullrev
835 or new_base >= total_revs
830 or new_base >= total_revs
836 ):
831 ):
837 break
832 break
838 p1_base = new_base
833 p1_base = new_base
839 e1 = index[p1_base]
834 e1 = index[p1_base]
840 p2_base = p2
835 p2_base = p2
841 if p2 != nullrev and p2 < total_revs:
836 if p2 != nullrev and p2 < total_revs:
842 e2 = index[p2]
837 e2 = index[p2]
843 while e2[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
838 while e2[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
844 new_base = e2[revlog_constants.ENTRY_DELTA_BASE]
839 new_base = e2[revlog_constants.ENTRY_DELTA_BASE]
845 if (
840 if (
846 new_base == p2_base
841 new_base == p2_base
847 or new_base == nullrev
842 or new_base == nullrev
848 or new_base >= total_revs
843 or new_base >= total_revs
849 ):
844 ):
850 break
845 break
851 p2_base = new_base
846 p2_base = new_base
852 e2 = index[p2_base]
847 e2 = index[p2_base]
853
848
854 if generaldelta:
849 if generaldelta:
855 if base == p1:
850 if base == p1:
856 deltatype = b'p1'
851 deltatype = b'p1'
857 elif base == p2:
852 elif base == p2:
858 deltatype = b'p2'
853 deltatype = b'p2'
859 elif base == rev:
854 elif base == rev:
860 deltatype = b'base'
855 deltatype = b'base'
861 elif base == p1_base:
856 elif base == p1_base:
862 deltatype = b'skip1'
857 deltatype = b'skip1'
863 elif base == p2_base:
858 elif base == p2_base:
864 deltatype = b'skip2'
859 deltatype = b'skip2'
865 elif r.issnapshot(rev):
860 elif r.issnapshot(rev):
866 deltatype = b'snap'
861 deltatype = b'snap'
867 elif base == rev - 1:
862 elif base == rev - 1:
868 deltatype = b'prev'
863 deltatype = b'prev'
869 else:
864 else:
870 deltatype = b'other'
865 deltatype = b'other'
871 else:
866 else:
872 if base == rev:
867 if base == rev:
873 deltatype = b'base'
868 deltatype = b'base'
874 else:
869 else:
875 deltatype = b'prev'
870 deltatype = b'prev'
876
871
877 chain = r._deltachain(rev)[0]
872 chain = r._deltachain(rev)[0]
878 for iterrev in chain:
873 for iterrev in chain:
879 e = index[iterrev]
874 e = index[iterrev]
880 chainsize += e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
875 chainsize += e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
881
876
882 return p1, p2, compsize, uncompsize, deltatype, chain, chainsize
877 return p1, p2, compsize, uncompsize, deltatype, chain, chainsize
883
878
884 fm = ui.formatter(b'debugdeltachain', opts)
879 fm = ui.formatter(b'debugdeltachain', opts)
885
880
886 fm.plain(
881 fm.plain(
887 b' rev p1 p2 chain# chainlen prev delta '
882 b' rev p1 p2 chain# chainlen prev delta '
888 b'size rawsize chainsize ratio lindist extradist '
883 b'size rawsize chainsize ratio lindist extradist '
889 b'extraratio'
884 b'extraratio'
890 )
885 )
891 if withsparseread:
886 if withsparseread:
892 fm.plain(b' readsize largestblk rddensity srchunks')
887 fm.plain(b' readsize largestblk rddensity srchunks')
893 fm.plain(b'\n')
888 fm.plain(b'\n')
894
889
895 chainbases = {}
890 chainbases = {}
896 for rev in r:
891 for rev in r:
897 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
892 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
898 chainbase = chain[0]
893 chainbase = chain[0]
899 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
894 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
900 basestart = start(chainbase)
895 basestart = start(chainbase)
901 revstart = start(rev)
896 revstart = start(rev)
902 lineardist = revstart + comp - basestart
897 lineardist = revstart + comp - basestart
903 extradist = lineardist - chainsize
898 extradist = lineardist - chainsize
904 try:
899 try:
905 prevrev = chain[-2]
900 prevrev = chain[-2]
906 except IndexError:
901 except IndexError:
907 prevrev = -1
902 prevrev = -1
908
903
909 if uncomp != 0:
904 if uncomp != 0:
910 chainratio = float(chainsize) / float(uncomp)
905 chainratio = float(chainsize) / float(uncomp)
911 else:
906 else:
912 chainratio = chainsize
907 chainratio = chainsize
913
908
914 if chainsize != 0:
909 if chainsize != 0:
915 extraratio = float(extradist) / float(chainsize)
910 extraratio = float(extradist) / float(chainsize)
916 else:
911 else:
917 extraratio = extradist
912 extraratio = extradist
918
913
919 fm.startitem()
914 fm.startitem()
920 fm.write(
915 fm.write(
921 b'rev p1 p2 chainid chainlen prevrev deltatype compsize '
916 b'rev p1 p2 chainid chainlen prevrev deltatype compsize '
922 b'uncompsize chainsize chainratio lindist extradist '
917 b'uncompsize chainsize chainratio lindist extradist '
923 b'extraratio',
918 b'extraratio',
924 b'%7d %7d %7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
919 b'%7d %7d %7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
925 rev,
920 rev,
926 p1,
921 p1,
927 p2,
922 p2,
928 chainid,
923 chainid,
929 len(chain),
924 len(chain),
930 prevrev,
925 prevrev,
931 deltatype,
926 deltatype,
932 comp,
927 comp,
933 uncomp,
928 uncomp,
934 chainsize,
929 chainsize,
935 chainratio,
930 chainratio,
936 lineardist,
931 lineardist,
937 extradist,
932 extradist,
938 extraratio,
933 extraratio,
939 rev=rev,
934 rev=rev,
940 chainid=chainid,
935 chainid=chainid,
941 chainlen=len(chain),
936 chainlen=len(chain),
942 prevrev=prevrev,
937 prevrev=prevrev,
943 deltatype=deltatype,
938 deltatype=deltatype,
944 compsize=comp,
939 compsize=comp,
945 uncompsize=uncomp,
940 uncompsize=uncomp,
946 chainsize=chainsize,
941 chainsize=chainsize,
947 chainratio=chainratio,
942 chainratio=chainratio,
948 lindist=lineardist,
943 lindist=lineardist,
949 extradist=extradist,
944 extradist=extradist,
950 extraratio=extraratio,
945 extraratio=extraratio,
951 )
946 )
952 if withsparseread:
947 if withsparseread:
953 readsize = 0
948 readsize = 0
954 largestblock = 0
949 largestblock = 0
955 srchunks = 0
950 srchunks = 0
956
951
957 for revschunk in deltautil.slicechunk(r, chain):
952 for revschunk in deltautil.slicechunk(r, chain):
958 srchunks += 1
953 srchunks += 1
959 blkend = start(revschunk[-1]) + length(revschunk[-1])
954 blkend = start(revschunk[-1]) + length(revschunk[-1])
960 blksize = blkend - start(revschunk[0])
955 blksize = blkend - start(revschunk[0])
961
956
962 readsize += blksize
957 readsize += blksize
963 if largestblock < blksize:
958 if largestblock < blksize:
964 largestblock = blksize
959 largestblock = blksize
965
960
966 if readsize:
961 if readsize:
967 readdensity = float(chainsize) / float(readsize)
962 readdensity = float(chainsize) / float(readsize)
968 else:
963 else:
969 readdensity = 1
964 readdensity = 1
970
965
971 fm.write(
966 fm.write(
972 b'readsize largestblock readdensity srchunks',
967 b'readsize largestblock readdensity srchunks',
973 b' %10d %10d %9.5f %8d',
968 b' %10d %10d %9.5f %8d',
974 readsize,
969 readsize,
975 largestblock,
970 largestblock,
976 readdensity,
971 readdensity,
977 srchunks,
972 srchunks,
978 readsize=readsize,
973 readsize=readsize,
979 largestblock=largestblock,
974 largestblock=largestblock,
980 readdensity=readdensity,
975 readdensity=readdensity,
981 srchunks=srchunks,
976 srchunks=srchunks,
982 )
977 )
983
978
984 fm.plain(b'\n')
979 fm.plain(b'\n')
985
980
986 fm.end()
981 fm.end()
987
982
988
983
989 @command(
984 @command(
990 b'debug-delta-find',
985 b'debug-delta-find',
991 cmdutil.debugrevlogopts
986 cmdutil.debugrevlogopts
992 + cmdutil.formatteropts
987 + cmdutil.formatteropts
993 + [
988 + [
994 (
989 (
995 b'',
990 b'',
996 b'source',
991 b'source',
997 b'full',
992 b'full',
998 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
993 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
999 ),
994 ),
1000 ],
995 ],
1001 _(b'-c|-m|FILE REV'),
996 _(b'-c|-m|FILE REV'),
1002 optionalrepo=True,
997 optionalrepo=True,
1003 )
998 )
1004 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
999 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
1005 """display the computation to get to a valid delta for storing REV
1000 """display the computation to get to a valid delta for storing REV
1006
1001
1007 This command will replay the process used to find the "best" delta to store
1002 This command will replay the process used to find the "best" delta to store
1008 a revision and display information about all the steps used to get to that
1003 a revision and display information about all the steps used to get to that
1009 result.
1004 result.
1010
1005
1011 By default, the process is fed with a the full-text for the revision. This
1006 By default, the process is fed with a the full-text for the revision. This
1012 can be controlled with the --source flag.
1007 can be controlled with the --source flag.
1013
1008
1014 The revision use the revision number of the target storage (not changelog
1009 The revision use the revision number of the target storage (not changelog
1015 revision number).
1010 revision number).
1016
1011
1017 note: the process is initiated from a full text of the revision to store.
1012 note: the process is initiated from a full text of the revision to store.
1018 """
1013 """
1019 opts = pycompat.byteskwargs(opts)
1014 opts = pycompat.byteskwargs(opts)
1020 if arg_2 is None:
1015 if arg_2 is None:
1021 file_ = None
1016 file_ = None
1022 rev = arg_1
1017 rev = arg_1
1023 else:
1018 else:
1024 file_ = arg_1
1019 file_ = arg_1
1025 rev = arg_2
1020 rev = arg_2
1026
1021
1027 rev = int(rev)
1022 rev = int(rev)
1028
1023
1029 revlog = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
1024 revlog = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
1030 p1r, p2r = revlog.parentrevs(rev)
1025 p1r, p2r = revlog.parentrevs(rev)
1031
1026
1032 if source == b'full':
1027 if source == b'full':
1033 base_rev = nullrev
1028 base_rev = nullrev
1034 elif source == b'storage':
1029 elif source == b'storage':
1035 base_rev = revlog.deltaparent(rev)
1030 base_rev = revlog.deltaparent(rev)
1036 elif source == b'p1':
1031 elif source == b'p1':
1037 base_rev = p1r
1032 base_rev = p1r
1038 elif source == b'p2':
1033 elif source == b'p2':
1039 base_rev = p2r
1034 base_rev = p2r
1040 elif source == b'prev':
1035 elif source == b'prev':
1041 base_rev = rev - 1
1036 base_rev = rev - 1
1042 else:
1037 else:
1043 raise error.InputError(b"invalid --source value: %s" % source)
1038 raise error.InputError(b"invalid --source value: %s" % source)
1044
1039
1045 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
1040 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
1046
1041
1047
1042
1048 @command(
1043 @command(
1049 b'debugdirstate|debugstate',
1044 b'debugdirstate|debugstate',
1050 [
1045 [
1051 (
1046 (
1052 b'',
1047 b'',
1053 b'nodates',
1048 b'nodates',
1054 None,
1049 None,
1055 _(b'do not display the saved mtime (DEPRECATED)'),
1050 _(b'do not display the saved mtime (DEPRECATED)'),
1056 ),
1051 ),
1057 (b'', b'dates', True, _(b'display the saved mtime')),
1052 (b'', b'dates', True, _(b'display the saved mtime')),
1058 (b'', b'datesort', None, _(b'sort by saved mtime')),
1053 (b'', b'datesort', None, _(b'sort by saved mtime')),
1059 (
1054 (
1060 b'',
1055 b'',
1061 b'docket',
1056 b'docket',
1062 False,
1057 False,
1063 _(b'display the docket (metadata file) instead'),
1058 _(b'display the docket (metadata file) instead'),
1064 ),
1059 ),
1065 (
1060 (
1066 b'',
1061 b'',
1067 b'all',
1062 b'all',
1068 False,
1063 False,
1069 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
1064 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
1070 ),
1065 ),
1071 ],
1066 ],
1072 _(b'[OPTION]...'),
1067 _(b'[OPTION]...'),
1073 )
1068 )
1074 def debugstate(ui, repo, **opts):
1069 def debugstate(ui, repo, **opts):
1075 """show the contents of the current dirstate"""
1070 """show the contents of the current dirstate"""
1076
1071
1077 if opts.get("docket"):
1072 if opts.get("docket"):
1078 if not repo.dirstate._use_dirstate_v2:
1073 if not repo.dirstate._use_dirstate_v2:
1079 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1074 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1080
1075
1081 docket = repo.dirstate._map.docket
1076 docket = repo.dirstate._map.docket
1082 (
1077 (
1083 start_offset,
1078 start_offset,
1084 root_nodes,
1079 root_nodes,
1085 nodes_with_entry,
1080 nodes_with_entry,
1086 nodes_with_copy,
1081 nodes_with_copy,
1087 unused_bytes,
1082 unused_bytes,
1088 _unused,
1083 _unused,
1089 ignore_pattern,
1084 ignore_pattern,
1090 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1085 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1091
1086
1092 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1087 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1093 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1088 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1094 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1089 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1095 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1090 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1096 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1091 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1097 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1092 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1098 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1093 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1099 ui.write(
1094 ui.write(
1100 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1095 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1101 )
1096 )
1102 return
1097 return
1103
1098
1104 nodates = not opts['dates']
1099 nodates = not opts['dates']
1105 if opts.get('nodates') is not None:
1100 if opts.get('nodates') is not None:
1106 nodates = True
1101 nodates = True
1107 datesort = opts.get('datesort')
1102 datesort = opts.get('datesort')
1108
1103
1109 if datesort:
1104 if datesort:
1110
1105
1111 def keyfunc(entry):
1106 def keyfunc(entry):
1112 filename, _state, _mode, _size, mtime = entry
1107 filename, _state, _mode, _size, mtime = entry
1113 return (mtime, filename)
1108 return (mtime, filename)
1114
1109
1115 else:
1110 else:
1116 keyfunc = None # sort by filename
1111 keyfunc = None # sort by filename
1117 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1112 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1118 entries.sort(key=keyfunc)
1113 entries.sort(key=keyfunc)
1119 for entry in entries:
1114 for entry in entries:
1120 filename, state, mode, size, mtime = entry
1115 filename, state, mode, size, mtime = entry
1121 if mtime == -1:
1116 if mtime == -1:
1122 timestr = b'unset '
1117 timestr = b'unset '
1123 elif nodates:
1118 elif nodates:
1124 timestr = b'set '
1119 timestr = b'set '
1125 else:
1120 else:
1126 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1121 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1127 timestr = encoding.strtolocal(timestr)
1122 timestr = encoding.strtolocal(timestr)
1128 if mode & 0o20000:
1123 if mode & 0o20000:
1129 mode = b'lnk'
1124 mode = b'lnk'
1130 else:
1125 else:
1131 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1126 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1132 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1127 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1133 for f in repo.dirstate.copies():
1128 for f in repo.dirstate.copies():
1134 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1129 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1135
1130
1136
1131
1137 @command(
1132 @command(
1138 b'debugdirstateignorepatternshash',
1133 b'debugdirstateignorepatternshash',
1139 [],
1134 [],
1140 _(b''),
1135 _(b''),
1141 )
1136 )
1142 def debugdirstateignorepatternshash(ui, repo, **opts):
1137 def debugdirstateignorepatternshash(ui, repo, **opts):
1143 """show the hash of ignore patterns stored in dirstate if v2,
1138 """show the hash of ignore patterns stored in dirstate if v2,
1144 or nothing for dirstate-v2
1139 or nothing for dirstate-v2
1145 """
1140 """
1146 if repo.dirstate._use_dirstate_v2:
1141 if repo.dirstate._use_dirstate_v2:
1147 docket = repo.dirstate._map.docket
1142 docket = repo.dirstate._map.docket
1148 hash_len = 20 # 160 bits for SHA-1
1143 hash_len = 20 # 160 bits for SHA-1
1149 hash_bytes = docket.tree_metadata[-hash_len:]
1144 hash_bytes = docket.tree_metadata[-hash_len:]
1150 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1145 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1151
1146
1152
1147
1153 @command(
1148 @command(
1154 b'debugdiscovery',
1149 b'debugdiscovery',
1155 [
1150 [
1156 (b'', b'old', None, _(b'use old-style discovery')),
1151 (b'', b'old', None, _(b'use old-style discovery')),
1157 (
1152 (
1158 b'',
1153 b'',
1159 b'nonheads',
1154 b'nonheads',
1160 None,
1155 None,
1161 _(b'use old-style discovery with non-heads included'),
1156 _(b'use old-style discovery with non-heads included'),
1162 ),
1157 ),
1163 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1158 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1164 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1159 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1165 (
1160 (
1166 b'',
1161 b'',
1167 b'local-as-revs',
1162 b'local-as-revs',
1168 b"",
1163 b"",
1169 b'treat local has having these revisions only',
1164 b'treat local has having these revisions only',
1170 ),
1165 ),
1171 (
1166 (
1172 b'',
1167 b'',
1173 b'remote-as-revs',
1168 b'remote-as-revs',
1174 b"",
1169 b"",
1175 b'use local as remote, with only these revisions',
1170 b'use local as remote, with only these revisions',
1176 ),
1171 ),
1177 ]
1172 ]
1178 + cmdutil.remoteopts
1173 + cmdutil.remoteopts
1179 + cmdutil.formatteropts,
1174 + cmdutil.formatteropts,
1180 _(b'[--rev REV] [OTHER]'),
1175 _(b'[--rev REV] [OTHER]'),
1181 )
1176 )
1182 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1177 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1183 """runs the changeset discovery protocol in isolation
1178 """runs the changeset discovery protocol in isolation
1184
1179
1185 The local peer can be "replaced" by a subset of the local repository by
1180 The local peer can be "replaced" by a subset of the local repository by
1186 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1181 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1187 can be "replaced" by a subset of the local repository using the
1182 can be "replaced" by a subset of the local repository using the
1188 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1183 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1189 discovery situations.
1184 discovery situations.
1190
1185
1191 The following developer oriented config are relevant for people playing with this command:
1186 The following developer oriented config are relevant for people playing with this command:
1192
1187
1193 * devel.discovery.exchange-heads=True
1188 * devel.discovery.exchange-heads=True
1194
1189
1195 If False, the discovery will not start with
1190 If False, the discovery will not start with
1196 remote head fetching and local head querying.
1191 remote head fetching and local head querying.
1197
1192
1198 * devel.discovery.grow-sample=True
1193 * devel.discovery.grow-sample=True
1199
1194
1200 If False, the sample size used in set discovery will not be increased
1195 If False, the sample size used in set discovery will not be increased
1201 through the process
1196 through the process
1202
1197
1203 * devel.discovery.grow-sample.dynamic=True
1198 * devel.discovery.grow-sample.dynamic=True
1204
1199
1205 When discovery.grow-sample.dynamic is True, the default, the sample size is
1200 When discovery.grow-sample.dynamic is True, the default, the sample size is
1206 adapted to the shape of the undecided set (it is set to the max of:
1201 adapted to the shape of the undecided set (it is set to the max of:
1207 <target-size>, len(roots(undecided)), len(heads(undecided)
1202 <target-size>, len(roots(undecided)), len(heads(undecided)
1208
1203
1209 * devel.discovery.grow-sample.rate=1.05
1204 * devel.discovery.grow-sample.rate=1.05
1210
1205
1211 the rate at which the sample grow
1206 the rate at which the sample grow
1212
1207
1213 * devel.discovery.randomize=True
1208 * devel.discovery.randomize=True
1214
1209
1215 If andom sampling during discovery are deterministic. It is meant for
1210 If andom sampling during discovery are deterministic. It is meant for
1216 integration tests.
1211 integration tests.
1217
1212
1218 * devel.discovery.sample-size=200
1213 * devel.discovery.sample-size=200
1219
1214
1220 Control the initial size of the discovery sample
1215 Control the initial size of the discovery sample
1221
1216
1222 * devel.discovery.sample-size.initial=100
1217 * devel.discovery.sample-size.initial=100
1223
1218
1224 Control the initial size of the discovery for initial change
1219 Control the initial size of the discovery for initial change
1225 """
1220 """
1226 opts = pycompat.byteskwargs(opts)
1221 opts = pycompat.byteskwargs(opts)
1227 unfi = repo.unfiltered()
1222 unfi = repo.unfiltered()
1228
1223
1229 # setup potential extra filtering
1224 # setup potential extra filtering
1230 local_revs = opts[b"local_as_revs"]
1225 local_revs = opts[b"local_as_revs"]
1231 remote_revs = opts[b"remote_as_revs"]
1226 remote_revs = opts[b"remote_as_revs"]
1232
1227
1233 # make sure tests are repeatable
1228 # make sure tests are repeatable
1234 random.seed(int(opts[b'seed']))
1229 random.seed(int(opts[b'seed']))
1235
1230
1236 if not remote_revs:
1231 if not remote_revs:
1237 path = urlutil.get_unique_pull_path_obj(
1232 path = urlutil.get_unique_pull_path_obj(
1238 b'debugdiscovery', ui, remoteurl
1233 b'debugdiscovery', ui, remoteurl
1239 )
1234 )
1240 branches = (path.branch, [])
1235 branches = (path.branch, [])
1241 remote = hg.peer(repo, opts, path)
1236 remote = hg.peer(repo, opts, path)
1242 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1237 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1243 else:
1238 else:
1244 branches = (None, [])
1239 branches = (None, [])
1245 remote_filtered_revs = logcmdutil.revrange(
1240 remote_filtered_revs = logcmdutil.revrange(
1246 unfi, [b"not (::(%s))" % remote_revs]
1241 unfi, [b"not (::(%s))" % remote_revs]
1247 )
1242 )
1248 remote_filtered_revs = frozenset(remote_filtered_revs)
1243 remote_filtered_revs = frozenset(remote_filtered_revs)
1249
1244
1250 def remote_func(x):
1245 def remote_func(x):
1251 return remote_filtered_revs
1246 return remote_filtered_revs
1252
1247
1253 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1248 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1254
1249
1255 remote = repo.peer()
1250 remote = repo.peer()
1256 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1251 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1257
1252
1258 if local_revs:
1253 if local_revs:
1259 local_filtered_revs = logcmdutil.revrange(
1254 local_filtered_revs = logcmdutil.revrange(
1260 unfi, [b"not (::(%s))" % local_revs]
1255 unfi, [b"not (::(%s))" % local_revs]
1261 )
1256 )
1262 local_filtered_revs = frozenset(local_filtered_revs)
1257 local_filtered_revs = frozenset(local_filtered_revs)
1263
1258
1264 def local_func(x):
1259 def local_func(x):
1265 return local_filtered_revs
1260 return local_filtered_revs
1266
1261
1267 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1262 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1268 repo = repo.filtered(b'debug-discovery-local-filter')
1263 repo = repo.filtered(b'debug-discovery-local-filter')
1269
1264
1270 data = {}
1265 data = {}
1271 if opts.get(b'old'):
1266 if opts.get(b'old'):
1272
1267
1273 def doit(pushedrevs, remoteheads, remote=remote):
1268 def doit(pushedrevs, remoteheads, remote=remote):
1274 if not util.safehasattr(remote, b'branches'):
1269 if not util.safehasattr(remote, b'branches'):
1275 # enable in-client legacy support
1270 # enable in-client legacy support
1276 remote = localrepo.locallegacypeer(remote.local())
1271 remote = localrepo.locallegacypeer(remote.local())
1277 if remote_revs:
1272 if remote_revs:
1278 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1273 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1279 remote._repo = r
1274 remote._repo = r
1280 common, _in, hds = treediscovery.findcommonincoming(
1275 common, _in, hds = treediscovery.findcommonincoming(
1281 repo, remote, force=True, audit=data
1276 repo, remote, force=True, audit=data
1282 )
1277 )
1283 common = set(common)
1278 common = set(common)
1284 if not opts.get(b'nonheads'):
1279 if not opts.get(b'nonheads'):
1285 ui.writenoi18n(
1280 ui.writenoi18n(
1286 b"unpruned common: %s\n"
1281 b"unpruned common: %s\n"
1287 % b" ".join(sorted(short(n) for n in common))
1282 % b" ".join(sorted(short(n) for n in common))
1288 )
1283 )
1289
1284
1290 clnode = repo.changelog.node
1285 clnode = repo.changelog.node
1291 common = repo.revs(b'heads(::%ln)', common)
1286 common = repo.revs(b'heads(::%ln)', common)
1292 common = {clnode(r) for r in common}
1287 common = {clnode(r) for r in common}
1293 return common, hds
1288 return common, hds
1294
1289
1295 else:
1290 else:
1296
1291
1297 def doit(pushedrevs, remoteheads, remote=remote):
1292 def doit(pushedrevs, remoteheads, remote=remote):
1298 nodes = None
1293 nodes = None
1299 if pushedrevs:
1294 if pushedrevs:
1300 revs = logcmdutil.revrange(repo, pushedrevs)
1295 revs = logcmdutil.revrange(repo, pushedrevs)
1301 nodes = [repo[r].node() for r in revs]
1296 nodes = [repo[r].node() for r in revs]
1302 common, any, hds = setdiscovery.findcommonheads(
1297 common, any, hds = setdiscovery.findcommonheads(
1303 ui,
1298 ui,
1304 repo,
1299 repo,
1305 remote,
1300 remote,
1306 ancestorsof=nodes,
1301 ancestorsof=nodes,
1307 audit=data,
1302 audit=data,
1308 abortwhenunrelated=False,
1303 abortwhenunrelated=False,
1309 )
1304 )
1310 return common, hds
1305 return common, hds
1311
1306
1312 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1307 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1313 localrevs = opts[b'rev']
1308 localrevs = opts[b'rev']
1314
1309
1315 fm = ui.formatter(b'debugdiscovery', opts)
1310 fm = ui.formatter(b'debugdiscovery', opts)
1316 if fm.strict_format:
1311 if fm.strict_format:
1317
1312
1318 @contextlib.contextmanager
1313 @contextlib.contextmanager
1319 def may_capture_output():
1314 def may_capture_output():
1320 ui.pushbuffer()
1315 ui.pushbuffer()
1321 yield
1316 yield
1322 data[b'output'] = ui.popbuffer()
1317 data[b'output'] = ui.popbuffer()
1323
1318
1324 else:
1319 else:
1325 may_capture_output = util.nullcontextmanager
1320 may_capture_output = util.nullcontextmanager
1326 with may_capture_output():
1321 with may_capture_output():
1327 with util.timedcm('debug-discovery') as t:
1322 with util.timedcm('debug-discovery') as t:
1328 common, hds = doit(localrevs, remoterevs)
1323 common, hds = doit(localrevs, remoterevs)
1329
1324
1330 # compute all statistics
1325 # compute all statistics
1331 if len(common) == 1 and repo.nullid in common:
1326 if len(common) == 1 and repo.nullid in common:
1332 common = set()
1327 common = set()
1333 heads_common = set(common)
1328 heads_common = set(common)
1334 heads_remote = set(hds)
1329 heads_remote = set(hds)
1335 heads_local = set(repo.heads())
1330 heads_local = set(repo.heads())
1336 # note: they cannot be a local or remote head that is in common and not
1331 # note: they cannot be a local or remote head that is in common and not
1337 # itself a head of common.
1332 # itself a head of common.
1338 heads_common_local = heads_common & heads_local
1333 heads_common_local = heads_common & heads_local
1339 heads_common_remote = heads_common & heads_remote
1334 heads_common_remote = heads_common & heads_remote
1340 heads_common_both = heads_common & heads_remote & heads_local
1335 heads_common_both = heads_common & heads_remote & heads_local
1341
1336
1342 all = repo.revs(b'all()')
1337 all = repo.revs(b'all()')
1343 common = repo.revs(b'::%ln', common)
1338 common = repo.revs(b'::%ln', common)
1344 roots_common = repo.revs(b'roots(::%ld)', common)
1339 roots_common = repo.revs(b'roots(::%ld)', common)
1345 missing = repo.revs(b'not ::%ld', common)
1340 missing = repo.revs(b'not ::%ld', common)
1346 heads_missing = repo.revs(b'heads(%ld)', missing)
1341 heads_missing = repo.revs(b'heads(%ld)', missing)
1347 roots_missing = repo.revs(b'roots(%ld)', missing)
1342 roots_missing = repo.revs(b'roots(%ld)', missing)
1348 assert len(common) + len(missing) == len(all)
1343 assert len(common) + len(missing) == len(all)
1349
1344
1350 initial_undecided = repo.revs(
1345 initial_undecided = repo.revs(
1351 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1346 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1352 )
1347 )
1353 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1348 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1354 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1349 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1355 common_initial_undecided = initial_undecided & common
1350 common_initial_undecided = initial_undecided & common
1356 missing_initial_undecided = initial_undecided & missing
1351 missing_initial_undecided = initial_undecided & missing
1357
1352
1358 data[b'elapsed'] = t.elapsed
1353 data[b'elapsed'] = t.elapsed
1359 data[b'nb-common-heads'] = len(heads_common)
1354 data[b'nb-common-heads'] = len(heads_common)
1360 data[b'nb-common-heads-local'] = len(heads_common_local)
1355 data[b'nb-common-heads-local'] = len(heads_common_local)
1361 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1356 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1362 data[b'nb-common-heads-both'] = len(heads_common_both)
1357 data[b'nb-common-heads-both'] = len(heads_common_both)
1363 data[b'nb-common-roots'] = len(roots_common)
1358 data[b'nb-common-roots'] = len(roots_common)
1364 data[b'nb-head-local'] = len(heads_local)
1359 data[b'nb-head-local'] = len(heads_local)
1365 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1360 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1366 data[b'nb-head-remote'] = len(heads_remote)
1361 data[b'nb-head-remote'] = len(heads_remote)
1367 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1362 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1368 heads_common_remote
1363 heads_common_remote
1369 )
1364 )
1370 data[b'nb-revs'] = len(all)
1365 data[b'nb-revs'] = len(all)
1371 data[b'nb-revs-common'] = len(common)
1366 data[b'nb-revs-common'] = len(common)
1372 data[b'nb-revs-missing'] = len(missing)
1367 data[b'nb-revs-missing'] = len(missing)
1373 data[b'nb-missing-heads'] = len(heads_missing)
1368 data[b'nb-missing-heads'] = len(heads_missing)
1374 data[b'nb-missing-roots'] = len(roots_missing)
1369 data[b'nb-missing-roots'] = len(roots_missing)
1375 data[b'nb-ini_und'] = len(initial_undecided)
1370 data[b'nb-ini_und'] = len(initial_undecided)
1376 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1371 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1377 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1372 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1378 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1373 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1379 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1374 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1380
1375
1381 fm.startitem()
1376 fm.startitem()
1382 fm.data(**pycompat.strkwargs(data))
1377 fm.data(**pycompat.strkwargs(data))
1383 # display discovery summary
1378 # display discovery summary
1384 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1379 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1385 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1380 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1386 if b'total-round-trips-heads' in data:
1381 if b'total-round-trips-heads' in data:
1387 fm.plain(
1382 fm.plain(
1388 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1383 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1389 )
1384 )
1390 if b'total-round-trips-branches' in data:
1385 if b'total-round-trips-branches' in data:
1391 fm.plain(
1386 fm.plain(
1392 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1387 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1393 % data
1388 % data
1394 )
1389 )
1395 if b'total-round-trips-between' in data:
1390 if b'total-round-trips-between' in data:
1396 fm.plain(
1391 fm.plain(
1397 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1392 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1398 )
1393 )
1399 fm.plain(b"queries: %(total-queries)9d\n" % data)
1394 fm.plain(b"queries: %(total-queries)9d\n" % data)
1400 if b'total-queries-branches' in data:
1395 if b'total-queries-branches' in data:
1401 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1396 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1402 if b'total-queries-between' in data:
1397 if b'total-queries-between' in data:
1403 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1398 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1404 fm.plain(b"heads summary:\n")
1399 fm.plain(b"heads summary:\n")
1405 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1400 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1406 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1401 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1407 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1402 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1408 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1403 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1409 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1404 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1410 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1405 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1411 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1406 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1412 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1407 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1413 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1408 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1414 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1409 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1415 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1410 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1416 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1411 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1417 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1412 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1418 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1413 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1419 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1414 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1420 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1415 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1421 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1416 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1422 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1417 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1423 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1418 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1424 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1419 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1425 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1420 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1426 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1421 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1427
1422
1428 if ui.verbose:
1423 if ui.verbose:
1429 fm.plain(
1424 fm.plain(
1430 b"common heads: %s\n"
1425 b"common heads: %s\n"
1431 % b" ".join(sorted(short(n) for n in heads_common))
1426 % b" ".join(sorted(short(n) for n in heads_common))
1432 )
1427 )
1433 fm.end()
1428 fm.end()
1434
1429
1435
1430
1436 _chunksize = 4 << 10
1431 _chunksize = 4 << 10
1437
1432
1438
1433
1439 @command(
1434 @command(
1440 b'debugdownload',
1435 b'debugdownload',
1441 [
1436 [
1442 (b'o', b'output', b'', _(b'path')),
1437 (b'o', b'output', b'', _(b'path')),
1443 ],
1438 ],
1444 optionalrepo=True,
1439 optionalrepo=True,
1445 )
1440 )
1446 def debugdownload(ui, repo, url, output=None, **opts):
1441 def debugdownload(ui, repo, url, output=None, **opts):
1447 """download a resource using Mercurial logic and config"""
1442 """download a resource using Mercurial logic and config"""
1448 fh = urlmod.open(ui, url, output)
1443 fh = urlmod.open(ui, url, output)
1449
1444
1450 dest = ui
1445 dest = ui
1451 if output:
1446 if output:
1452 dest = open(output, b"wb", _chunksize)
1447 dest = open(output, b"wb", _chunksize)
1453 try:
1448 try:
1454 data = fh.read(_chunksize)
1449 data = fh.read(_chunksize)
1455 while data:
1450 while data:
1456 dest.write(data)
1451 dest.write(data)
1457 data = fh.read(_chunksize)
1452 data = fh.read(_chunksize)
1458 finally:
1453 finally:
1459 if output:
1454 if output:
1460 dest.close()
1455 dest.close()
1461
1456
1462
1457
1463 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1458 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1464 def debugextensions(ui, repo, **opts):
1459 def debugextensions(ui, repo, **opts):
1465 '''show information about active extensions'''
1460 '''show information about active extensions'''
1466 opts = pycompat.byteskwargs(opts)
1461 opts = pycompat.byteskwargs(opts)
1467 exts = extensions.extensions(ui)
1462 exts = extensions.extensions(ui)
1468 hgver = util.version()
1463 hgver = util.version()
1469 fm = ui.formatter(b'debugextensions', opts)
1464 fm = ui.formatter(b'debugextensions', opts)
1470 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1465 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1471 isinternal = extensions.ismoduleinternal(extmod)
1466 isinternal = extensions.ismoduleinternal(extmod)
1472 extsource = None
1467 extsource = None
1473
1468
1474 if util.safehasattr(extmod, '__file__'):
1469 if util.safehasattr(extmod, '__file__'):
1475 extsource = pycompat.fsencode(extmod.__file__)
1470 extsource = pycompat.fsencode(extmod.__file__)
1476 elif getattr(sys, 'oxidized', False):
1471 elif getattr(sys, 'oxidized', False):
1477 extsource = pycompat.sysexecutable
1472 extsource = pycompat.sysexecutable
1478 if isinternal:
1473 if isinternal:
1479 exttestedwith = [] # never expose magic string to users
1474 exttestedwith = [] # never expose magic string to users
1480 else:
1475 else:
1481 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1476 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1482 extbuglink = getattr(extmod, 'buglink', None)
1477 extbuglink = getattr(extmod, 'buglink', None)
1483
1478
1484 fm.startitem()
1479 fm.startitem()
1485
1480
1486 if ui.quiet or ui.verbose:
1481 if ui.quiet or ui.verbose:
1487 fm.write(b'name', b'%s\n', extname)
1482 fm.write(b'name', b'%s\n', extname)
1488 else:
1483 else:
1489 fm.write(b'name', b'%s', extname)
1484 fm.write(b'name', b'%s', extname)
1490 if isinternal or hgver in exttestedwith:
1485 if isinternal or hgver in exttestedwith:
1491 fm.plain(b'\n')
1486 fm.plain(b'\n')
1492 elif not exttestedwith:
1487 elif not exttestedwith:
1493 fm.plain(_(b' (untested!)\n'))
1488 fm.plain(_(b' (untested!)\n'))
1494 else:
1489 else:
1495 lasttestedversion = exttestedwith[-1]
1490 lasttestedversion = exttestedwith[-1]
1496 fm.plain(b' (%s!)\n' % lasttestedversion)
1491 fm.plain(b' (%s!)\n' % lasttestedversion)
1497
1492
1498 fm.condwrite(
1493 fm.condwrite(
1499 ui.verbose and extsource,
1494 ui.verbose and extsource,
1500 b'source',
1495 b'source',
1501 _(b' location: %s\n'),
1496 _(b' location: %s\n'),
1502 extsource or b"",
1497 extsource or b"",
1503 )
1498 )
1504
1499
1505 if ui.verbose:
1500 if ui.verbose:
1506 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1501 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1507 fm.data(bundled=isinternal)
1502 fm.data(bundled=isinternal)
1508
1503
1509 fm.condwrite(
1504 fm.condwrite(
1510 ui.verbose and exttestedwith,
1505 ui.verbose and exttestedwith,
1511 b'testedwith',
1506 b'testedwith',
1512 _(b' tested with: %s\n'),
1507 _(b' tested with: %s\n'),
1513 fm.formatlist(exttestedwith, name=b'ver'),
1508 fm.formatlist(exttestedwith, name=b'ver'),
1514 )
1509 )
1515
1510
1516 fm.condwrite(
1511 fm.condwrite(
1517 ui.verbose and extbuglink,
1512 ui.verbose and extbuglink,
1518 b'buglink',
1513 b'buglink',
1519 _(b' bug reporting: %s\n'),
1514 _(b' bug reporting: %s\n'),
1520 extbuglink or b"",
1515 extbuglink or b"",
1521 )
1516 )
1522
1517
1523 fm.end()
1518 fm.end()
1524
1519
1525
1520
1526 @command(
1521 @command(
1527 b'debugfileset',
1522 b'debugfileset',
1528 [
1523 [
1529 (
1524 (
1530 b'r',
1525 b'r',
1531 b'rev',
1526 b'rev',
1532 b'',
1527 b'',
1533 _(b'apply the filespec on this revision'),
1528 _(b'apply the filespec on this revision'),
1534 _(b'REV'),
1529 _(b'REV'),
1535 ),
1530 ),
1536 (
1531 (
1537 b'',
1532 b'',
1538 b'all-files',
1533 b'all-files',
1539 False,
1534 False,
1540 _(b'test files from all revisions and working directory'),
1535 _(b'test files from all revisions and working directory'),
1541 ),
1536 ),
1542 (
1537 (
1543 b's',
1538 b's',
1544 b'show-matcher',
1539 b'show-matcher',
1545 None,
1540 None,
1546 _(b'print internal representation of matcher'),
1541 _(b'print internal representation of matcher'),
1547 ),
1542 ),
1548 (
1543 (
1549 b'p',
1544 b'p',
1550 b'show-stage',
1545 b'show-stage',
1551 [],
1546 [],
1552 _(b'print parsed tree at the given stage'),
1547 _(b'print parsed tree at the given stage'),
1553 _(b'NAME'),
1548 _(b'NAME'),
1554 ),
1549 ),
1555 ],
1550 ],
1556 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1551 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1557 )
1552 )
1558 def debugfileset(ui, repo, expr, **opts):
1553 def debugfileset(ui, repo, expr, **opts):
1559 '''parse and apply a fileset specification'''
1554 '''parse and apply a fileset specification'''
1560 from . import fileset
1555 from . import fileset
1561
1556
1562 fileset.symbols # force import of fileset so we have predicates to optimize
1557 fileset.symbols # force import of fileset so we have predicates to optimize
1563 opts = pycompat.byteskwargs(opts)
1558 opts = pycompat.byteskwargs(opts)
1564 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
1559 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
1565
1560
1566 stages = [
1561 stages = [
1567 (b'parsed', pycompat.identity),
1562 (b'parsed', pycompat.identity),
1568 (b'analyzed', filesetlang.analyze),
1563 (b'analyzed', filesetlang.analyze),
1569 (b'optimized', filesetlang.optimize),
1564 (b'optimized', filesetlang.optimize),
1570 ]
1565 ]
1571 stagenames = {n for n, f in stages}
1566 stagenames = {n for n, f in stages}
1572
1567
1573 showalways = set()
1568 showalways = set()
1574 if ui.verbose and not opts[b'show_stage']:
1569 if ui.verbose and not opts[b'show_stage']:
1575 # show parsed tree by --verbose (deprecated)
1570 # show parsed tree by --verbose (deprecated)
1576 showalways.add(b'parsed')
1571 showalways.add(b'parsed')
1577 if opts[b'show_stage'] == [b'all']:
1572 if opts[b'show_stage'] == [b'all']:
1578 showalways.update(stagenames)
1573 showalways.update(stagenames)
1579 else:
1574 else:
1580 for n in opts[b'show_stage']:
1575 for n in opts[b'show_stage']:
1581 if n not in stagenames:
1576 if n not in stagenames:
1582 raise error.Abort(_(b'invalid stage name: %s') % n)
1577 raise error.Abort(_(b'invalid stage name: %s') % n)
1583 showalways.update(opts[b'show_stage'])
1578 showalways.update(opts[b'show_stage'])
1584
1579
1585 tree = filesetlang.parse(expr)
1580 tree = filesetlang.parse(expr)
1586 for n, f in stages:
1581 for n, f in stages:
1587 tree = f(tree)
1582 tree = f(tree)
1588 if n in showalways:
1583 if n in showalways:
1589 if opts[b'show_stage'] or n != b'parsed':
1584 if opts[b'show_stage'] or n != b'parsed':
1590 ui.write(b"* %s:\n" % n)
1585 ui.write(b"* %s:\n" % n)
1591 ui.write(filesetlang.prettyformat(tree), b"\n")
1586 ui.write(filesetlang.prettyformat(tree), b"\n")
1592
1587
1593 files = set()
1588 files = set()
1594 if opts[b'all_files']:
1589 if opts[b'all_files']:
1595 for r in repo:
1590 for r in repo:
1596 c = repo[r]
1591 c = repo[r]
1597 files.update(c.files())
1592 files.update(c.files())
1598 files.update(c.substate)
1593 files.update(c.substate)
1599 if opts[b'all_files'] or ctx.rev() is None:
1594 if opts[b'all_files'] or ctx.rev() is None:
1600 wctx = repo[None]
1595 wctx = repo[None]
1601 files.update(
1596 files.update(
1602 repo.dirstate.walk(
1597 repo.dirstate.walk(
1603 scmutil.matchall(repo),
1598 scmutil.matchall(repo),
1604 subrepos=list(wctx.substate),
1599 subrepos=list(wctx.substate),
1605 unknown=True,
1600 unknown=True,
1606 ignored=True,
1601 ignored=True,
1607 )
1602 )
1608 )
1603 )
1609 files.update(wctx.substate)
1604 files.update(wctx.substate)
1610 else:
1605 else:
1611 files.update(ctx.files())
1606 files.update(ctx.files())
1612 files.update(ctx.substate)
1607 files.update(ctx.substate)
1613
1608
1614 m = ctx.matchfileset(repo.getcwd(), expr)
1609 m = ctx.matchfileset(repo.getcwd(), expr)
1615 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1610 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1616 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1611 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1617 for f in sorted(files):
1612 for f in sorted(files):
1618 if not m(f):
1613 if not m(f):
1619 continue
1614 continue
1620 ui.write(b"%s\n" % f)
1615 ui.write(b"%s\n" % f)
1621
1616
1622
1617
1623 @command(
1618 @command(
1624 b"debug-repair-issue6528",
1619 b"debug-repair-issue6528",
1625 [
1620 [
1626 (
1621 (
1627 b'',
1622 b'',
1628 b'to-report',
1623 b'to-report',
1629 b'',
1624 b'',
1630 _(b'build a report of affected revisions to this file'),
1625 _(b'build a report of affected revisions to this file'),
1631 _(b'FILE'),
1626 _(b'FILE'),
1632 ),
1627 ),
1633 (
1628 (
1634 b'',
1629 b'',
1635 b'from-report',
1630 b'from-report',
1636 b'',
1631 b'',
1637 _(b'repair revisions listed in this report file'),
1632 _(b'repair revisions listed in this report file'),
1638 _(b'FILE'),
1633 _(b'FILE'),
1639 ),
1634 ),
1640 (
1635 (
1641 b'',
1636 b'',
1642 b'paranoid',
1637 b'paranoid',
1643 False,
1638 False,
1644 _(b'check that both detection methods do the same thing'),
1639 _(b'check that both detection methods do the same thing'),
1645 ),
1640 ),
1646 ]
1641 ]
1647 + cmdutil.dryrunopts,
1642 + cmdutil.dryrunopts,
1648 )
1643 )
1649 def debug_repair_issue6528(ui, repo, **opts):
1644 def debug_repair_issue6528(ui, repo, **opts):
1650 """find affected revisions and repair them. See issue6528 for more details.
1645 """find affected revisions and repair them. See issue6528 for more details.
1651
1646
1652 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1647 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1653 computation of affected revisions for a given repository across clones.
1648 computation of affected revisions for a given repository across clones.
1654 The report format is line-based (with empty lines ignored):
1649 The report format is line-based (with empty lines ignored):
1655
1650
1656 ```
1651 ```
1657 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1652 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1658 ```
1653 ```
1659
1654
1660 There can be multiple broken revisions per filelog, they are separated by
1655 There can be multiple broken revisions per filelog, they are separated by
1661 a comma with no spaces. The only space is between the revision(s) and the
1656 a comma with no spaces. The only space is between the revision(s) and the
1662 filename.
1657 filename.
1663
1658
1664 Note that this does *not* mean that this repairs future affected revisions,
1659 Note that this does *not* mean that this repairs future affected revisions,
1665 that needs a separate fix at the exchange level that was introduced in
1660 that needs a separate fix at the exchange level that was introduced in
1666 Mercurial 5.9.1.
1661 Mercurial 5.9.1.
1667
1662
1668 There is a `--paranoid` flag to test that the fast implementation is correct
1663 There is a `--paranoid` flag to test that the fast implementation is correct
1669 by checking it against the slow implementation. Since this matter is quite
1664 by checking it against the slow implementation. Since this matter is quite
1670 urgent and testing every edge-case is probably quite costly, we use this
1665 urgent and testing every edge-case is probably quite costly, we use this
1671 method to test on large repositories as a fuzzing method of sorts.
1666 method to test on large repositories as a fuzzing method of sorts.
1672 """
1667 """
1673 cmdutil.check_incompatible_arguments(
1668 cmdutil.check_incompatible_arguments(
1674 opts, 'to_report', ['from_report', 'dry_run']
1669 opts, 'to_report', ['from_report', 'dry_run']
1675 )
1670 )
1676 dry_run = opts.get('dry_run')
1671 dry_run = opts.get('dry_run')
1677 to_report = opts.get('to_report')
1672 to_report = opts.get('to_report')
1678 from_report = opts.get('from_report')
1673 from_report = opts.get('from_report')
1679 paranoid = opts.get('paranoid')
1674 paranoid = opts.get('paranoid')
1680 # TODO maybe add filelog pattern and revision pattern parameters to help
1675 # TODO maybe add filelog pattern and revision pattern parameters to help
1681 # narrow down the search for users that know what they're looking for?
1676 # narrow down the search for users that know what they're looking for?
1682
1677
1683 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1678 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1684 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1679 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1685 raise error.Abort(_(msg))
1680 raise error.Abort(_(msg))
1686
1681
1687 rewrite.repair_issue6528(
1682 rewrite.repair_issue6528(
1688 ui,
1683 ui,
1689 repo,
1684 repo,
1690 dry_run=dry_run,
1685 dry_run=dry_run,
1691 to_report=to_report,
1686 to_report=to_report,
1692 from_report=from_report,
1687 from_report=from_report,
1693 paranoid=paranoid,
1688 paranoid=paranoid,
1694 )
1689 )
1695
1690
1696
1691
1697 @command(b'debugformat', [] + cmdutil.formatteropts)
1692 @command(b'debugformat', [] + cmdutil.formatteropts)
1698 def debugformat(ui, repo, **opts):
1693 def debugformat(ui, repo, **opts):
1699 """display format information about the current repository
1694 """display format information about the current repository
1700
1695
1701 Use --verbose to get extra information about current config value and
1696 Use --verbose to get extra information about current config value and
1702 Mercurial default."""
1697 Mercurial default."""
1703 opts = pycompat.byteskwargs(opts)
1698 opts = pycompat.byteskwargs(opts)
1704 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1699 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1705 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1700 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1706
1701
1707 def makeformatname(name):
1702 def makeformatname(name):
1708 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1703 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1709
1704
1710 fm = ui.formatter(b'debugformat', opts)
1705 fm = ui.formatter(b'debugformat', opts)
1711 if fm.isplain():
1706 if fm.isplain():
1712
1707
1713 def formatvalue(value):
1708 def formatvalue(value):
1714 if util.safehasattr(value, b'startswith'):
1709 if util.safehasattr(value, b'startswith'):
1715 return value
1710 return value
1716 if value:
1711 if value:
1717 return b'yes'
1712 return b'yes'
1718 else:
1713 else:
1719 return b'no'
1714 return b'no'
1720
1715
1721 else:
1716 else:
1722 formatvalue = pycompat.identity
1717 formatvalue = pycompat.identity
1723
1718
1724 fm.plain(b'format-variant')
1719 fm.plain(b'format-variant')
1725 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1720 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1726 fm.plain(b' repo')
1721 fm.plain(b' repo')
1727 if ui.verbose:
1722 if ui.verbose:
1728 fm.plain(b' config default')
1723 fm.plain(b' config default')
1729 fm.plain(b'\n')
1724 fm.plain(b'\n')
1730 for fv in upgrade.allformatvariant:
1725 for fv in upgrade.allformatvariant:
1731 fm.startitem()
1726 fm.startitem()
1732 repovalue = fv.fromrepo(repo)
1727 repovalue = fv.fromrepo(repo)
1733 configvalue = fv.fromconfig(repo)
1728 configvalue = fv.fromconfig(repo)
1734
1729
1735 if repovalue != configvalue:
1730 if repovalue != configvalue:
1736 namelabel = b'formatvariant.name.mismatchconfig'
1731 namelabel = b'formatvariant.name.mismatchconfig'
1737 repolabel = b'formatvariant.repo.mismatchconfig'
1732 repolabel = b'formatvariant.repo.mismatchconfig'
1738 elif repovalue != fv.default:
1733 elif repovalue != fv.default:
1739 namelabel = b'formatvariant.name.mismatchdefault'
1734 namelabel = b'formatvariant.name.mismatchdefault'
1740 repolabel = b'formatvariant.repo.mismatchdefault'
1735 repolabel = b'formatvariant.repo.mismatchdefault'
1741 else:
1736 else:
1742 namelabel = b'formatvariant.name.uptodate'
1737 namelabel = b'formatvariant.name.uptodate'
1743 repolabel = b'formatvariant.repo.uptodate'
1738 repolabel = b'formatvariant.repo.uptodate'
1744
1739
1745 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1740 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1746 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1741 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1747 if fv.default != configvalue:
1742 if fv.default != configvalue:
1748 configlabel = b'formatvariant.config.special'
1743 configlabel = b'formatvariant.config.special'
1749 else:
1744 else:
1750 configlabel = b'formatvariant.config.default'
1745 configlabel = b'formatvariant.config.default'
1751 fm.condwrite(
1746 fm.condwrite(
1752 ui.verbose,
1747 ui.verbose,
1753 b'config',
1748 b'config',
1754 b' %6s',
1749 b' %6s',
1755 formatvalue(configvalue),
1750 formatvalue(configvalue),
1756 label=configlabel,
1751 label=configlabel,
1757 )
1752 )
1758 fm.condwrite(
1753 fm.condwrite(
1759 ui.verbose,
1754 ui.verbose,
1760 b'default',
1755 b'default',
1761 b' %7s',
1756 b' %7s',
1762 formatvalue(fv.default),
1757 formatvalue(fv.default),
1763 label=b'formatvariant.default',
1758 label=b'formatvariant.default',
1764 )
1759 )
1765 fm.plain(b'\n')
1760 fm.plain(b'\n')
1766 fm.end()
1761 fm.end()
1767
1762
1768
1763
1769 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1764 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1770 def debugfsinfo(ui, path=b"."):
1765 def debugfsinfo(ui, path=b"."):
1771 """show information detected about current filesystem"""
1766 """show information detected about current filesystem"""
1772 ui.writenoi18n(b'path: %s\n' % path)
1767 ui.writenoi18n(b'path: %s\n' % path)
1773 ui.writenoi18n(
1768 ui.writenoi18n(
1774 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1769 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1775 )
1770 )
1776 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1771 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1777 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1772 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1778 ui.writenoi18n(
1773 ui.writenoi18n(
1779 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1774 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1780 )
1775 )
1781 ui.writenoi18n(
1776 ui.writenoi18n(
1782 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1777 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1783 )
1778 )
1784 casesensitive = b'(unknown)'
1779 casesensitive = b'(unknown)'
1785 try:
1780 try:
1786 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1781 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1787 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1782 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1788 except OSError:
1783 except OSError:
1789 pass
1784 pass
1790 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1785 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1791
1786
1792
1787
1793 @command(
1788 @command(
1794 b'debuggetbundle',
1789 b'debuggetbundle',
1795 [
1790 [
1796 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1791 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1797 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1792 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1798 (
1793 (
1799 b't',
1794 b't',
1800 b'type',
1795 b'type',
1801 b'bzip2',
1796 b'bzip2',
1802 _(b'bundle compression type to use'),
1797 _(b'bundle compression type to use'),
1803 _(b'TYPE'),
1798 _(b'TYPE'),
1804 ),
1799 ),
1805 ],
1800 ],
1806 _(b'REPO FILE [-H|-C ID]...'),
1801 _(b'REPO FILE [-H|-C ID]...'),
1807 norepo=True,
1802 norepo=True,
1808 )
1803 )
1809 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1804 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1810 """retrieves a bundle from a repo
1805 """retrieves a bundle from a repo
1811
1806
1812 Every ID must be a full-length hex node id string. Saves the bundle to the
1807 Every ID must be a full-length hex node id string. Saves the bundle to the
1813 given file.
1808 given file.
1814 """
1809 """
1815 opts = pycompat.byteskwargs(opts)
1810 opts = pycompat.byteskwargs(opts)
1816 repo = hg.peer(ui, opts, repopath)
1811 repo = hg.peer(ui, opts, repopath)
1817 if not repo.capable(b'getbundle'):
1812 if not repo.capable(b'getbundle'):
1818 raise error.Abort(b"getbundle() not supported by target repository")
1813 raise error.Abort(b"getbundle() not supported by target repository")
1819 args = {}
1814 args = {}
1820 if common:
1815 if common:
1821 args['common'] = [bin(s) for s in common]
1816 args['common'] = [bin(s) for s in common]
1822 if head:
1817 if head:
1823 args['heads'] = [bin(s) for s in head]
1818 args['heads'] = [bin(s) for s in head]
1824 # TODO: get desired bundlecaps from command line.
1819 # TODO: get desired bundlecaps from command line.
1825 args['bundlecaps'] = None
1820 args['bundlecaps'] = None
1826 bundle = repo.getbundle(b'debug', **args)
1821 bundle = repo.getbundle(b'debug', **args)
1827
1822
1828 bundletype = opts.get(b'type', b'bzip2').lower()
1823 bundletype = opts.get(b'type', b'bzip2').lower()
1829 btypes = {
1824 btypes = {
1830 b'none': b'HG10UN',
1825 b'none': b'HG10UN',
1831 b'bzip2': b'HG10BZ',
1826 b'bzip2': b'HG10BZ',
1832 b'gzip': b'HG10GZ',
1827 b'gzip': b'HG10GZ',
1833 b'bundle2': b'HG20',
1828 b'bundle2': b'HG20',
1834 }
1829 }
1835 bundletype = btypes.get(bundletype)
1830 bundletype = btypes.get(bundletype)
1836 if bundletype not in bundle2.bundletypes:
1831 if bundletype not in bundle2.bundletypes:
1837 raise error.Abort(_(b'unknown bundle type specified with --type'))
1832 raise error.Abort(_(b'unknown bundle type specified with --type'))
1838 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1833 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1839
1834
1840
1835
1841 @command(b'debugignore', [], b'[FILE]')
1836 @command(b'debugignore', [], b'[FILE]')
1842 def debugignore(ui, repo, *files, **opts):
1837 def debugignore(ui, repo, *files, **opts):
1843 """display the combined ignore pattern and information about ignored files
1838 """display the combined ignore pattern and information about ignored files
1844
1839
1845 With no argument display the combined ignore pattern.
1840 With no argument display the combined ignore pattern.
1846
1841
1847 Given space separated file names, shows if the given file is ignored and
1842 Given space separated file names, shows if the given file is ignored and
1848 if so, show the ignore rule (file and line number) that matched it.
1843 if so, show the ignore rule (file and line number) that matched it.
1849 """
1844 """
1850 ignore = repo.dirstate._ignore
1845 ignore = repo.dirstate._ignore
1851 if not files:
1846 if not files:
1852 # Show all the patterns
1847 # Show all the patterns
1853 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1848 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1854 else:
1849 else:
1855 m = scmutil.match(repo[None], pats=files)
1850 m = scmutil.match(repo[None], pats=files)
1856 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1851 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1857 for f in m.files():
1852 for f in m.files():
1858 nf = util.normpath(f)
1853 nf = util.normpath(f)
1859 ignored = None
1854 ignored = None
1860 ignoredata = None
1855 ignoredata = None
1861 if nf != b'.':
1856 if nf != b'.':
1862 if ignore(nf):
1857 if ignore(nf):
1863 ignored = nf
1858 ignored = nf
1864 ignoredata = repo.dirstate._ignorefileandline(nf)
1859 ignoredata = repo.dirstate._ignorefileandline(nf)
1865 else:
1860 else:
1866 for p in pathutil.finddirs(nf):
1861 for p in pathutil.finddirs(nf):
1867 if ignore(p):
1862 if ignore(p):
1868 ignored = p
1863 ignored = p
1869 ignoredata = repo.dirstate._ignorefileandline(p)
1864 ignoredata = repo.dirstate._ignorefileandline(p)
1870 break
1865 break
1871 if ignored:
1866 if ignored:
1872 if ignored == nf:
1867 if ignored == nf:
1873 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1868 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1874 else:
1869 else:
1875 ui.write(
1870 ui.write(
1876 _(
1871 _(
1877 b"%s is ignored because of "
1872 b"%s is ignored because of "
1878 b"containing directory %s\n"
1873 b"containing directory %s\n"
1879 )
1874 )
1880 % (uipathfn(f), ignored)
1875 % (uipathfn(f), ignored)
1881 )
1876 )
1882 ignorefile, lineno, line = ignoredata
1877 ignorefile, lineno, line = ignoredata
1883 ui.write(
1878 ui.write(
1884 _(b"(ignore rule in %s, line %d: '%s')\n")
1879 _(b"(ignore rule in %s, line %d: '%s')\n")
1885 % (ignorefile, lineno, line)
1880 % (ignorefile, lineno, line)
1886 )
1881 )
1887 else:
1882 else:
1888 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1883 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1889
1884
1890
1885
1891 @command(
1886 @command(
1892 b'debug-revlog-index|debugindex',
1887 b'debug-revlog-index|debugindex',
1893 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1888 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1894 _(b'-c|-m|FILE'),
1889 _(b'-c|-m|FILE'),
1895 )
1890 )
1896 def debugindex(ui, repo, file_=None, **opts):
1891 def debugindex(ui, repo, file_=None, **opts):
1897 """dump index data for a revlog"""
1892 """dump index data for a revlog"""
1898 opts = pycompat.byteskwargs(opts)
1893 opts = pycompat.byteskwargs(opts)
1899 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1894 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1900
1895
1901 fm = ui.formatter(b'debugindex', opts)
1896 fm = ui.formatter(b'debugindex', opts)
1902
1897
1903 revlog = getattr(store, b'_revlog', store)
1898 revlog = getattr(store, b'_revlog', store)
1904
1899
1905 return revlog_debug.debug_index(
1900 return revlog_debug.debug_index(
1906 ui,
1901 ui,
1907 repo,
1902 repo,
1908 formatter=fm,
1903 formatter=fm,
1909 revlog=revlog,
1904 revlog=revlog,
1910 full_node=ui.debugflag,
1905 full_node=ui.debugflag,
1911 )
1906 )
1912
1907
1913
1908
1914 @command(
1909 @command(
1915 b'debugindexdot',
1910 b'debugindexdot',
1916 cmdutil.debugrevlogopts,
1911 cmdutil.debugrevlogopts,
1917 _(b'-c|-m|FILE'),
1912 _(b'-c|-m|FILE'),
1918 optionalrepo=True,
1913 optionalrepo=True,
1919 )
1914 )
1920 def debugindexdot(ui, repo, file_=None, **opts):
1915 def debugindexdot(ui, repo, file_=None, **opts):
1921 """dump an index DAG as a graphviz dot file"""
1916 """dump an index DAG as a graphviz dot file"""
1922 opts = pycompat.byteskwargs(opts)
1917 opts = pycompat.byteskwargs(opts)
1923 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1918 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1924 ui.writenoi18n(b"digraph G {\n")
1919 ui.writenoi18n(b"digraph G {\n")
1925 for i in r:
1920 for i in r:
1926 node = r.node(i)
1921 node = r.node(i)
1927 pp = r.parents(node)
1922 pp = r.parents(node)
1928 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1923 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1929 if pp[1] != repo.nullid:
1924 if pp[1] != repo.nullid:
1930 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1925 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1931 ui.write(b"}\n")
1926 ui.write(b"}\n")
1932
1927
1933
1928
1934 @command(b'debugindexstats', [])
1929 @command(b'debugindexstats', [])
1935 def debugindexstats(ui, repo):
1930 def debugindexstats(ui, repo):
1936 """show stats related to the changelog index"""
1931 """show stats related to the changelog index"""
1937 repo.changelog.shortest(repo.nullid, 1)
1932 repo.changelog.shortest(repo.nullid, 1)
1938 index = repo.changelog.index
1933 index = repo.changelog.index
1939 if not util.safehasattr(index, b'stats'):
1934 if not util.safehasattr(index, b'stats'):
1940 raise error.Abort(_(b'debugindexstats only works with native code'))
1935 raise error.Abort(_(b'debugindexstats only works with native code'))
1941 for k, v in sorted(index.stats().items()):
1936 for k, v in sorted(index.stats().items()):
1942 ui.write(b'%s: %d\n' % (k, v))
1937 ui.write(b'%s: %d\n' % (k, v))
1943
1938
1944
1939
1945 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1940 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1946 def debuginstall(ui, **opts):
1941 def debuginstall(ui, **opts):
1947 """test Mercurial installation
1942 """test Mercurial installation
1948
1943
1949 Returns 0 on success.
1944 Returns 0 on success.
1950 """
1945 """
1951 opts = pycompat.byteskwargs(opts)
1946 opts = pycompat.byteskwargs(opts)
1952
1947
1953 problems = 0
1948 problems = 0
1954
1949
1955 fm = ui.formatter(b'debuginstall', opts)
1950 fm = ui.formatter(b'debuginstall', opts)
1956 fm.startitem()
1951 fm.startitem()
1957
1952
1958 # encoding might be unknown or wrong. don't translate these messages.
1953 # encoding might be unknown or wrong. don't translate these messages.
1959 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1954 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1960 err = None
1955 err = None
1961 try:
1956 try:
1962 codecs.lookup(pycompat.sysstr(encoding.encoding))
1957 codecs.lookup(pycompat.sysstr(encoding.encoding))
1963 except LookupError as inst:
1958 except LookupError as inst:
1964 err = stringutil.forcebytestr(inst)
1959 err = stringutil.forcebytestr(inst)
1965 problems += 1
1960 problems += 1
1966 fm.condwrite(
1961 fm.condwrite(
1967 err,
1962 err,
1968 b'encodingerror',
1963 b'encodingerror',
1969 b" %s\n (check that your locale is properly set)\n",
1964 b" %s\n (check that your locale is properly set)\n",
1970 err,
1965 err,
1971 )
1966 )
1972
1967
1973 # Python
1968 # Python
1974 pythonlib = None
1969 pythonlib = None
1975 if util.safehasattr(os, '__file__'):
1970 if util.safehasattr(os, '__file__'):
1976 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1971 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1977 elif getattr(sys, 'oxidized', False):
1972 elif getattr(sys, 'oxidized', False):
1978 pythonlib = pycompat.sysexecutable
1973 pythonlib = pycompat.sysexecutable
1979
1974
1980 fm.write(
1975 fm.write(
1981 b'pythonexe',
1976 b'pythonexe',
1982 _(b"checking Python executable (%s)\n"),
1977 _(b"checking Python executable (%s)\n"),
1983 pycompat.sysexecutable or _(b"unknown"),
1978 pycompat.sysexecutable or _(b"unknown"),
1984 )
1979 )
1985 fm.write(
1980 fm.write(
1986 b'pythonimplementation',
1981 b'pythonimplementation',
1987 _(b"checking Python implementation (%s)\n"),
1982 _(b"checking Python implementation (%s)\n"),
1988 pycompat.sysbytes(platform.python_implementation()),
1983 pycompat.sysbytes(platform.python_implementation()),
1989 )
1984 )
1990 fm.write(
1985 fm.write(
1991 b'pythonver',
1986 b'pythonver',
1992 _(b"checking Python version (%s)\n"),
1987 _(b"checking Python version (%s)\n"),
1993 (b"%d.%d.%d" % sys.version_info[:3]),
1988 (b"%d.%d.%d" % sys.version_info[:3]),
1994 )
1989 )
1995 fm.write(
1990 fm.write(
1996 b'pythonlib',
1991 b'pythonlib',
1997 _(b"checking Python lib (%s)...\n"),
1992 _(b"checking Python lib (%s)...\n"),
1998 pythonlib or _(b"unknown"),
1993 pythonlib or _(b"unknown"),
1999 )
1994 )
2000
1995
2001 try:
1996 try:
2002 from . import rustext # pytype: disable=import-error
1997 from . import rustext # pytype: disable=import-error
2003
1998
2004 rustext.__doc__ # trigger lazy import
1999 rustext.__doc__ # trigger lazy import
2005 except ImportError:
2000 except ImportError:
2006 rustext = None
2001 rustext = None
2007
2002
2008 security = set(sslutil.supportedprotocols)
2003 security = set(sslutil.supportedprotocols)
2009 if sslutil.hassni:
2004 if sslutil.hassni:
2010 security.add(b'sni')
2005 security.add(b'sni')
2011
2006
2012 fm.write(
2007 fm.write(
2013 b'pythonsecurity',
2008 b'pythonsecurity',
2014 _(b"checking Python security support (%s)\n"),
2009 _(b"checking Python security support (%s)\n"),
2015 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
2010 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
2016 )
2011 )
2017
2012
2018 # These are warnings, not errors. So don't increment problem count. This
2013 # These are warnings, not errors. So don't increment problem count. This
2019 # may change in the future.
2014 # may change in the future.
2020 if b'tls1.2' not in security:
2015 if b'tls1.2' not in security:
2021 fm.plain(
2016 fm.plain(
2022 _(
2017 _(
2023 b' TLS 1.2 not supported by Python install; '
2018 b' TLS 1.2 not supported by Python install; '
2024 b'network connections lack modern security\n'
2019 b'network connections lack modern security\n'
2025 )
2020 )
2026 )
2021 )
2027 if b'sni' not in security:
2022 if b'sni' not in security:
2028 fm.plain(
2023 fm.plain(
2029 _(
2024 _(
2030 b' SNI not supported by Python install; may have '
2025 b' SNI not supported by Python install; may have '
2031 b'connectivity issues with some servers\n'
2026 b'connectivity issues with some servers\n'
2032 )
2027 )
2033 )
2028 )
2034
2029
2035 fm.plain(
2030 fm.plain(
2036 _(
2031 _(
2037 b"checking Rust extensions (%s)\n"
2032 b"checking Rust extensions (%s)\n"
2038 % (b'missing' if rustext is None else b'installed')
2033 % (b'missing' if rustext is None else b'installed')
2039 ),
2034 ),
2040 )
2035 )
2041
2036
2042 # TODO print CA cert info
2037 # TODO print CA cert info
2043
2038
2044 # hg version
2039 # hg version
2045 hgver = util.version()
2040 hgver = util.version()
2046 fm.write(
2041 fm.write(
2047 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
2042 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
2048 )
2043 )
2049 fm.write(
2044 fm.write(
2050 b'hgverextra',
2045 b'hgverextra',
2051 _(b"checking Mercurial custom build (%s)\n"),
2046 _(b"checking Mercurial custom build (%s)\n"),
2052 b'+'.join(hgver.split(b'+')[1:]),
2047 b'+'.join(hgver.split(b'+')[1:]),
2053 )
2048 )
2054
2049
2055 # compiled modules
2050 # compiled modules
2056 hgmodules = None
2051 hgmodules = None
2057 if util.safehasattr(sys.modules[__name__], '__file__'):
2052 if util.safehasattr(sys.modules[__name__], '__file__'):
2058 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
2053 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
2059 elif getattr(sys, 'oxidized', False):
2054 elif getattr(sys, 'oxidized', False):
2060 hgmodules = pycompat.sysexecutable
2055 hgmodules = pycompat.sysexecutable
2061
2056
2062 fm.write(
2057 fm.write(
2063 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
2058 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
2064 )
2059 )
2065 fm.write(
2060 fm.write(
2066 b'hgmodules',
2061 b'hgmodules',
2067 _(b"checking installed modules (%s)...\n"),
2062 _(b"checking installed modules (%s)...\n"),
2068 hgmodules or _(b"unknown"),
2063 hgmodules or _(b"unknown"),
2069 )
2064 )
2070
2065
2071 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
2066 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
2072 rustext = rustandc # for now, that's the only case
2067 rustext = rustandc # for now, that's the only case
2073 cext = policy.policy in (b'c', b'allow') or rustandc
2068 cext = policy.policy in (b'c', b'allow') or rustandc
2074 nopure = cext or rustext
2069 nopure = cext or rustext
2075 if nopure:
2070 if nopure:
2076 err = None
2071 err = None
2077 try:
2072 try:
2078 if cext:
2073 if cext:
2079 from .cext import ( # pytype: disable=import-error
2074 from .cext import ( # pytype: disable=import-error
2080 base85,
2075 base85,
2081 bdiff,
2076 bdiff,
2082 mpatch,
2077 mpatch,
2083 osutil,
2078 osutil,
2084 )
2079 )
2085
2080
2086 # quiet pyflakes
2081 # quiet pyflakes
2087 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2082 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2088 if rustext:
2083 if rustext:
2089 from .rustext import ( # pytype: disable=import-error
2084 from .rustext import ( # pytype: disable=import-error
2090 ancestor,
2085 ancestor,
2091 dirstate,
2086 dirstate,
2092 )
2087 )
2093
2088
2094 dir(ancestor), dir(dirstate) # quiet pyflakes
2089 dir(ancestor), dir(dirstate) # quiet pyflakes
2095 except Exception as inst:
2090 except Exception as inst:
2096 err = stringutil.forcebytestr(inst)
2091 err = stringutil.forcebytestr(inst)
2097 problems += 1
2092 problems += 1
2098 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2093 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2099
2094
2100 compengines = util.compengines._engines.values()
2095 compengines = util.compengines._engines.values()
2101 fm.write(
2096 fm.write(
2102 b'compengines',
2097 b'compengines',
2103 _(b'checking registered compression engines (%s)\n'),
2098 _(b'checking registered compression engines (%s)\n'),
2104 fm.formatlist(
2099 fm.formatlist(
2105 sorted(e.name() for e in compengines),
2100 sorted(e.name() for e in compengines),
2106 name=b'compengine',
2101 name=b'compengine',
2107 fmt=b'%s',
2102 fmt=b'%s',
2108 sep=b', ',
2103 sep=b', ',
2109 ),
2104 ),
2110 )
2105 )
2111 fm.write(
2106 fm.write(
2112 b'compenginesavail',
2107 b'compenginesavail',
2113 _(b'checking available compression engines (%s)\n'),
2108 _(b'checking available compression engines (%s)\n'),
2114 fm.formatlist(
2109 fm.formatlist(
2115 sorted(e.name() for e in compengines if e.available()),
2110 sorted(e.name() for e in compengines if e.available()),
2116 name=b'compengine',
2111 name=b'compengine',
2117 fmt=b'%s',
2112 fmt=b'%s',
2118 sep=b', ',
2113 sep=b', ',
2119 ),
2114 ),
2120 )
2115 )
2121 wirecompengines = compression.compengines.supportedwireengines(
2116 wirecompengines = compression.compengines.supportedwireengines(
2122 compression.SERVERROLE
2117 compression.SERVERROLE
2123 )
2118 )
2124 fm.write(
2119 fm.write(
2125 b'compenginesserver',
2120 b'compenginesserver',
2126 _(
2121 _(
2127 b'checking available compression engines '
2122 b'checking available compression engines '
2128 b'for wire protocol (%s)\n'
2123 b'for wire protocol (%s)\n'
2129 ),
2124 ),
2130 fm.formatlist(
2125 fm.formatlist(
2131 [e.name() for e in wirecompengines if e.wireprotosupport()],
2126 [e.name() for e in wirecompengines if e.wireprotosupport()],
2132 name=b'compengine',
2127 name=b'compengine',
2133 fmt=b'%s',
2128 fmt=b'%s',
2134 sep=b', ',
2129 sep=b', ',
2135 ),
2130 ),
2136 )
2131 )
2137 re2 = b'missing'
2132 re2 = b'missing'
2138 if util._re2:
2133 if util._re2:
2139 re2 = b'available'
2134 re2 = b'available'
2140 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2135 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2141 fm.data(re2=bool(util._re2))
2136 fm.data(re2=bool(util._re2))
2142
2137
2143 # templates
2138 # templates
2144 p = templater.templatedir()
2139 p = templater.templatedir()
2145 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2140 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2146 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2141 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2147 if p:
2142 if p:
2148 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2143 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2149 if m:
2144 if m:
2150 # template found, check if it is working
2145 # template found, check if it is working
2151 err = None
2146 err = None
2152 try:
2147 try:
2153 templater.templater.frommapfile(m)
2148 templater.templater.frommapfile(m)
2154 except Exception as inst:
2149 except Exception as inst:
2155 err = stringutil.forcebytestr(inst)
2150 err = stringutil.forcebytestr(inst)
2156 p = None
2151 p = None
2157 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2152 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2158 else:
2153 else:
2159 p = None
2154 p = None
2160 fm.condwrite(
2155 fm.condwrite(
2161 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2156 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2162 )
2157 )
2163 fm.condwrite(
2158 fm.condwrite(
2164 not m,
2159 not m,
2165 b'defaulttemplatenotfound',
2160 b'defaulttemplatenotfound',
2166 _(b" template '%s' not found\n"),
2161 _(b" template '%s' not found\n"),
2167 b"default",
2162 b"default",
2168 )
2163 )
2169 if not p:
2164 if not p:
2170 problems += 1
2165 problems += 1
2171 fm.condwrite(
2166 fm.condwrite(
2172 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2167 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2173 )
2168 )
2174
2169
2175 # editor
2170 # editor
2176 editor = ui.geteditor()
2171 editor = ui.geteditor()
2177 editor = util.expandpath(editor)
2172 editor = util.expandpath(editor)
2178 editorbin = procutil.shellsplit(editor)[0]
2173 editorbin = procutil.shellsplit(editor)[0]
2179 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2174 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2180 cmdpath = procutil.findexe(editorbin)
2175 cmdpath = procutil.findexe(editorbin)
2181 fm.condwrite(
2176 fm.condwrite(
2182 not cmdpath and editor == b'vi',
2177 not cmdpath and editor == b'vi',
2183 b'vinotfound',
2178 b'vinotfound',
2184 _(
2179 _(
2185 b" No commit editor set and can't find %s in PATH\n"
2180 b" No commit editor set and can't find %s in PATH\n"
2186 b" (specify a commit editor in your configuration"
2181 b" (specify a commit editor in your configuration"
2187 b" file)\n"
2182 b" file)\n"
2188 ),
2183 ),
2189 not cmdpath and editor == b'vi' and editorbin,
2184 not cmdpath and editor == b'vi' and editorbin,
2190 )
2185 )
2191 fm.condwrite(
2186 fm.condwrite(
2192 not cmdpath and editor != b'vi',
2187 not cmdpath and editor != b'vi',
2193 b'editornotfound',
2188 b'editornotfound',
2194 _(
2189 _(
2195 b" Can't find editor '%s' in PATH\n"
2190 b" Can't find editor '%s' in PATH\n"
2196 b" (specify a commit editor in your configuration"
2191 b" (specify a commit editor in your configuration"
2197 b" file)\n"
2192 b" file)\n"
2198 ),
2193 ),
2199 not cmdpath and editorbin,
2194 not cmdpath and editorbin,
2200 )
2195 )
2201 if not cmdpath and editor != b'vi':
2196 if not cmdpath and editor != b'vi':
2202 problems += 1
2197 problems += 1
2203
2198
2204 # check username
2199 # check username
2205 username = None
2200 username = None
2206 err = None
2201 err = None
2207 try:
2202 try:
2208 username = ui.username()
2203 username = ui.username()
2209 except error.Abort as e:
2204 except error.Abort as e:
2210 err = e.message
2205 err = e.message
2211 problems += 1
2206 problems += 1
2212
2207
2213 fm.condwrite(
2208 fm.condwrite(
2214 username, b'username', _(b"checking username (%s)\n"), username
2209 username, b'username', _(b"checking username (%s)\n"), username
2215 )
2210 )
2216 fm.condwrite(
2211 fm.condwrite(
2217 err,
2212 err,
2218 b'usernameerror',
2213 b'usernameerror',
2219 _(
2214 _(
2220 b"checking username...\n %s\n"
2215 b"checking username...\n %s\n"
2221 b" (specify a username in your configuration file)\n"
2216 b" (specify a username in your configuration file)\n"
2222 ),
2217 ),
2223 err,
2218 err,
2224 )
2219 )
2225
2220
2226 for name, mod in extensions.extensions():
2221 for name, mod in extensions.extensions():
2227 handler = getattr(mod, 'debuginstall', None)
2222 handler = getattr(mod, 'debuginstall', None)
2228 if handler is not None:
2223 if handler is not None:
2229 problems += handler(ui, fm)
2224 problems += handler(ui, fm)
2230
2225
2231 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2226 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2232 if not problems:
2227 if not problems:
2233 fm.data(problems=problems)
2228 fm.data(problems=problems)
2234 fm.condwrite(
2229 fm.condwrite(
2235 problems,
2230 problems,
2236 b'problems',
2231 b'problems',
2237 _(b"%d problems detected, please check your install!\n"),
2232 _(b"%d problems detected, please check your install!\n"),
2238 problems,
2233 problems,
2239 )
2234 )
2240 fm.end()
2235 fm.end()
2241
2236
2242 return problems
2237 return problems
2243
2238
2244
2239
2245 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2240 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2246 def debugknown(ui, repopath, *ids, **opts):
2241 def debugknown(ui, repopath, *ids, **opts):
2247 """test whether node ids are known to a repo
2242 """test whether node ids are known to a repo
2248
2243
2249 Every ID must be a full-length hex node id string. Returns a list of 0s
2244 Every ID must be a full-length hex node id string. Returns a list of 0s
2250 and 1s indicating unknown/known.
2245 and 1s indicating unknown/known.
2251 """
2246 """
2252 opts = pycompat.byteskwargs(opts)
2247 opts = pycompat.byteskwargs(opts)
2253 repo = hg.peer(ui, opts, repopath)
2248 repo = hg.peer(ui, opts, repopath)
2254 if not repo.capable(b'known'):
2249 if not repo.capable(b'known'):
2255 raise error.Abort(b"known() not supported by target repository")
2250 raise error.Abort(b"known() not supported by target repository")
2256 flags = repo.known([bin(s) for s in ids])
2251 flags = repo.known([bin(s) for s in ids])
2257 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2252 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2258
2253
2259
2254
2260 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2255 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2261 def debuglabelcomplete(ui, repo, *args):
2256 def debuglabelcomplete(ui, repo, *args):
2262 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2257 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2263 debugnamecomplete(ui, repo, *args)
2258 debugnamecomplete(ui, repo, *args)
2264
2259
2265
2260
2266 @command(
2261 @command(
2267 b'debuglocks',
2262 b'debuglocks',
2268 [
2263 [
2269 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2264 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2270 (
2265 (
2271 b'W',
2266 b'W',
2272 b'force-free-wlock',
2267 b'force-free-wlock',
2273 None,
2268 None,
2274 _(b'free the working state lock (DANGEROUS)'),
2269 _(b'free the working state lock (DANGEROUS)'),
2275 ),
2270 ),
2276 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2271 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2277 (
2272 (
2278 b'S',
2273 b'S',
2279 b'set-wlock',
2274 b'set-wlock',
2280 None,
2275 None,
2281 _(b'set the working state lock until stopped'),
2276 _(b'set the working state lock until stopped'),
2282 ),
2277 ),
2283 ],
2278 ],
2284 _(b'[OPTION]...'),
2279 _(b'[OPTION]...'),
2285 )
2280 )
2286 def debuglocks(ui, repo, **opts):
2281 def debuglocks(ui, repo, **opts):
2287 """show or modify state of locks
2282 """show or modify state of locks
2288
2283
2289 By default, this command will show which locks are held. This
2284 By default, this command will show which locks are held. This
2290 includes the user and process holding the lock, the amount of time
2285 includes the user and process holding the lock, the amount of time
2291 the lock has been held, and the machine name where the process is
2286 the lock has been held, and the machine name where the process is
2292 running if it's not local.
2287 running if it's not local.
2293
2288
2294 Locks protect the integrity of Mercurial's data, so should be
2289 Locks protect the integrity of Mercurial's data, so should be
2295 treated with care. System crashes or other interruptions may cause
2290 treated with care. System crashes or other interruptions may cause
2296 locks to not be properly released, though Mercurial will usually
2291 locks to not be properly released, though Mercurial will usually
2297 detect and remove such stale locks automatically.
2292 detect and remove such stale locks automatically.
2298
2293
2299 However, detecting stale locks may not always be possible (for
2294 However, detecting stale locks may not always be possible (for
2300 instance, on a shared filesystem). Removing locks may also be
2295 instance, on a shared filesystem). Removing locks may also be
2301 blocked by filesystem permissions.
2296 blocked by filesystem permissions.
2302
2297
2303 Setting a lock will prevent other commands from changing the data.
2298 Setting a lock will prevent other commands from changing the data.
2304 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2299 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2305 The set locks are removed when the command exits.
2300 The set locks are removed when the command exits.
2306
2301
2307 Returns 0 if no locks are held.
2302 Returns 0 if no locks are held.
2308
2303
2309 """
2304 """
2310
2305
2311 if opts.get('force_free_lock'):
2306 if opts.get('force_free_lock'):
2312 repo.svfs.tryunlink(b'lock')
2307 repo.svfs.tryunlink(b'lock')
2313 if opts.get('force_free_wlock'):
2308 if opts.get('force_free_wlock'):
2314 repo.vfs.tryunlink(b'wlock')
2309 repo.vfs.tryunlink(b'wlock')
2315 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2310 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2316 return 0
2311 return 0
2317
2312
2318 locks = []
2313 locks = []
2319 try:
2314 try:
2320 if opts.get('set_wlock'):
2315 if opts.get('set_wlock'):
2321 try:
2316 try:
2322 locks.append(repo.wlock(False))
2317 locks.append(repo.wlock(False))
2323 except error.LockHeld:
2318 except error.LockHeld:
2324 raise error.Abort(_(b'wlock is already held'))
2319 raise error.Abort(_(b'wlock is already held'))
2325 if opts.get('set_lock'):
2320 if opts.get('set_lock'):
2326 try:
2321 try:
2327 locks.append(repo.lock(False))
2322 locks.append(repo.lock(False))
2328 except error.LockHeld:
2323 except error.LockHeld:
2329 raise error.Abort(_(b'lock is already held'))
2324 raise error.Abort(_(b'lock is already held'))
2330 if len(locks):
2325 if len(locks):
2331 try:
2326 try:
2332 if ui.interactive():
2327 if ui.interactive():
2333 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2328 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2334 ui.promptchoice(prompt)
2329 ui.promptchoice(prompt)
2335 else:
2330 else:
2336 msg = b"%d locks held, waiting for signal\n"
2331 msg = b"%d locks held, waiting for signal\n"
2337 msg %= len(locks)
2332 msg %= len(locks)
2338 ui.status(msg)
2333 ui.status(msg)
2339 while True: # XXX wait for a signal
2334 while True: # XXX wait for a signal
2340 time.sleep(0.1)
2335 time.sleep(0.1)
2341 except KeyboardInterrupt:
2336 except KeyboardInterrupt:
2342 msg = b"signal-received releasing locks\n"
2337 msg = b"signal-received releasing locks\n"
2343 ui.status(msg)
2338 ui.status(msg)
2344 return 0
2339 return 0
2345 finally:
2340 finally:
2346 release(*locks)
2341 release(*locks)
2347
2342
2348 now = time.time()
2343 now = time.time()
2349 held = 0
2344 held = 0
2350
2345
2351 def report(vfs, name, method):
2346 def report(vfs, name, method):
2352 # this causes stale locks to get reaped for more accurate reporting
2347 # this causes stale locks to get reaped for more accurate reporting
2353 try:
2348 try:
2354 l = method(False)
2349 l = method(False)
2355 except error.LockHeld:
2350 except error.LockHeld:
2356 l = None
2351 l = None
2357
2352
2358 if l:
2353 if l:
2359 l.release()
2354 l.release()
2360 else:
2355 else:
2361 try:
2356 try:
2362 st = vfs.lstat(name)
2357 st = vfs.lstat(name)
2363 age = now - st[stat.ST_MTIME]
2358 age = now - st[stat.ST_MTIME]
2364 user = util.username(st.st_uid)
2359 user = util.username(st.st_uid)
2365 locker = vfs.readlock(name)
2360 locker = vfs.readlock(name)
2366 if b":" in locker:
2361 if b":" in locker:
2367 host, pid = locker.split(b':')
2362 host, pid = locker.split(b':')
2368 if host == socket.gethostname():
2363 if host == socket.gethostname():
2369 locker = b'user %s, process %s' % (user or b'None', pid)
2364 locker = b'user %s, process %s' % (user or b'None', pid)
2370 else:
2365 else:
2371 locker = b'user %s, process %s, host %s' % (
2366 locker = b'user %s, process %s, host %s' % (
2372 user or b'None',
2367 user or b'None',
2373 pid,
2368 pid,
2374 host,
2369 host,
2375 )
2370 )
2376 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2371 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2377 return 1
2372 return 1
2378 except FileNotFoundError:
2373 except FileNotFoundError:
2379 pass
2374 pass
2380
2375
2381 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2376 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2382 return 0
2377 return 0
2383
2378
2384 held += report(repo.svfs, b"lock", repo.lock)
2379 held += report(repo.svfs, b"lock", repo.lock)
2385 held += report(repo.vfs, b"wlock", repo.wlock)
2380 held += report(repo.vfs, b"wlock", repo.wlock)
2386
2381
2387 return held
2382 return held
2388
2383
2389
2384
2390 @command(
2385 @command(
2391 b'debugmanifestfulltextcache',
2386 b'debugmanifestfulltextcache',
2392 [
2387 [
2393 (b'', b'clear', False, _(b'clear the cache')),
2388 (b'', b'clear', False, _(b'clear the cache')),
2394 (
2389 (
2395 b'a',
2390 b'a',
2396 b'add',
2391 b'add',
2397 [],
2392 [],
2398 _(b'add the given manifest nodes to the cache'),
2393 _(b'add the given manifest nodes to the cache'),
2399 _(b'NODE'),
2394 _(b'NODE'),
2400 ),
2395 ),
2401 ],
2396 ],
2402 b'',
2397 b'',
2403 )
2398 )
2404 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2399 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2405 """show, clear or amend the contents of the manifest fulltext cache"""
2400 """show, clear or amend the contents of the manifest fulltext cache"""
2406
2401
2407 def getcache():
2402 def getcache():
2408 r = repo.manifestlog.getstorage(b'')
2403 r = repo.manifestlog.getstorage(b'')
2409 try:
2404 try:
2410 return r._fulltextcache
2405 return r._fulltextcache
2411 except AttributeError:
2406 except AttributeError:
2412 msg = _(
2407 msg = _(
2413 b"Current revlog implementation doesn't appear to have a "
2408 b"Current revlog implementation doesn't appear to have a "
2414 b"manifest fulltext cache\n"
2409 b"manifest fulltext cache\n"
2415 )
2410 )
2416 raise error.Abort(msg)
2411 raise error.Abort(msg)
2417
2412
2418 if opts.get('clear'):
2413 if opts.get('clear'):
2419 with repo.wlock():
2414 with repo.wlock():
2420 cache = getcache()
2415 cache = getcache()
2421 cache.clear(clear_persisted_data=True)
2416 cache.clear(clear_persisted_data=True)
2422 return
2417 return
2423
2418
2424 if add:
2419 if add:
2425 with repo.wlock():
2420 with repo.wlock():
2426 m = repo.manifestlog
2421 m = repo.manifestlog
2427 store = m.getstorage(b'')
2422 store = m.getstorage(b'')
2428 for n in add:
2423 for n in add:
2429 try:
2424 try:
2430 manifest = m[store.lookup(n)]
2425 manifest = m[store.lookup(n)]
2431 except error.LookupError as e:
2426 except error.LookupError as e:
2432 raise error.Abort(
2427 raise error.Abort(
2433 bytes(e), hint=b"Check your manifest node id"
2428 bytes(e), hint=b"Check your manifest node id"
2434 )
2429 )
2435 manifest.read() # stores revisision in cache too
2430 manifest.read() # stores revisision in cache too
2436 return
2431 return
2437
2432
2438 cache = getcache()
2433 cache = getcache()
2439 if not len(cache):
2434 if not len(cache):
2440 ui.write(_(b'cache empty\n'))
2435 ui.write(_(b'cache empty\n'))
2441 else:
2436 else:
2442 ui.write(
2437 ui.write(
2443 _(
2438 _(
2444 b'cache contains %d manifest entries, in order of most to '
2439 b'cache contains %d manifest entries, in order of most to '
2445 b'least recent:\n'
2440 b'least recent:\n'
2446 )
2441 )
2447 % (len(cache),)
2442 % (len(cache),)
2448 )
2443 )
2449 totalsize = 0
2444 totalsize = 0
2450 for nodeid in cache:
2445 for nodeid in cache:
2451 # Use cache.get to not update the LRU order
2446 # Use cache.get to not update the LRU order
2452 data = cache.peek(nodeid)
2447 data = cache.peek(nodeid)
2453 size = len(data)
2448 size = len(data)
2454 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2449 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2455 ui.write(
2450 ui.write(
2456 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2451 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2457 )
2452 )
2458 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2453 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2459 ui.write(
2454 ui.write(
2460 _(b'total cache data size %s, on-disk %s\n')
2455 _(b'total cache data size %s, on-disk %s\n')
2461 % (util.bytecount(totalsize), util.bytecount(ondisk))
2456 % (util.bytecount(totalsize), util.bytecount(ondisk))
2462 )
2457 )
2463
2458
2464
2459
2465 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2460 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2466 def debugmergestate(ui, repo, *args, **opts):
2461 def debugmergestate(ui, repo, *args, **opts):
2467 """print merge state
2462 """print merge state
2468
2463
2469 Use --verbose to print out information about whether v1 or v2 merge state
2464 Use --verbose to print out information about whether v1 or v2 merge state
2470 was chosen."""
2465 was chosen."""
2471
2466
2472 if ui.verbose:
2467 if ui.verbose:
2473 ms = mergestatemod.mergestate(repo)
2468 ms = mergestatemod.mergestate(repo)
2474
2469
2475 # sort so that reasonable information is on top
2470 # sort so that reasonable information is on top
2476 v1records = ms._readrecordsv1()
2471 v1records = ms._readrecordsv1()
2477 v2records = ms._readrecordsv2()
2472 v2records = ms._readrecordsv2()
2478
2473
2479 if not v1records and not v2records:
2474 if not v1records and not v2records:
2480 pass
2475 pass
2481 elif not v2records:
2476 elif not v2records:
2482 ui.writenoi18n(b'no version 2 merge state\n')
2477 ui.writenoi18n(b'no version 2 merge state\n')
2483 elif ms._v1v2match(v1records, v2records):
2478 elif ms._v1v2match(v1records, v2records):
2484 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2479 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2485 else:
2480 else:
2486 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2481 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2487
2482
2488 opts = pycompat.byteskwargs(opts)
2483 opts = pycompat.byteskwargs(opts)
2489 if not opts[b'template']:
2484 if not opts[b'template']:
2490 opts[b'template'] = (
2485 opts[b'template'] = (
2491 b'{if(commits, "", "no merge state found\n")}'
2486 b'{if(commits, "", "no merge state found\n")}'
2492 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2487 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2493 b'{files % "file: {path} (state \\"{state}\\")\n'
2488 b'{files % "file: {path} (state \\"{state}\\")\n'
2494 b'{if(local_path, "'
2489 b'{if(local_path, "'
2495 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2490 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2496 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2491 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2497 b' other path: {other_path} (node {other_node})\n'
2492 b' other path: {other_path} (node {other_node})\n'
2498 b'")}'
2493 b'")}'
2499 b'{if(rename_side, "'
2494 b'{if(rename_side, "'
2500 b' rename side: {rename_side}\n'
2495 b' rename side: {rename_side}\n'
2501 b' renamed path: {renamed_path}\n'
2496 b' renamed path: {renamed_path}\n'
2502 b'")}'
2497 b'")}'
2503 b'{extras % " extra: {key} = {value}\n"}'
2498 b'{extras % " extra: {key} = {value}\n"}'
2504 b'"}'
2499 b'"}'
2505 b'{extras % "extra: {file} ({key} = {value})\n"}'
2500 b'{extras % "extra: {file} ({key} = {value})\n"}'
2506 )
2501 )
2507
2502
2508 ms = mergestatemod.mergestate.read(repo)
2503 ms = mergestatemod.mergestate.read(repo)
2509
2504
2510 fm = ui.formatter(b'debugmergestate', opts)
2505 fm = ui.formatter(b'debugmergestate', opts)
2511 fm.startitem()
2506 fm.startitem()
2512
2507
2513 fm_commits = fm.nested(b'commits')
2508 fm_commits = fm.nested(b'commits')
2514 if ms.active():
2509 if ms.active():
2515 for name, node, label_index in (
2510 for name, node, label_index in (
2516 (b'local', ms.local, 0),
2511 (b'local', ms.local, 0),
2517 (b'other', ms.other, 1),
2512 (b'other', ms.other, 1),
2518 ):
2513 ):
2519 fm_commits.startitem()
2514 fm_commits.startitem()
2520 fm_commits.data(name=name)
2515 fm_commits.data(name=name)
2521 fm_commits.data(node=hex(node))
2516 fm_commits.data(node=hex(node))
2522 if ms._labels and len(ms._labels) > label_index:
2517 if ms._labels and len(ms._labels) > label_index:
2523 fm_commits.data(label=ms._labels[label_index])
2518 fm_commits.data(label=ms._labels[label_index])
2524 fm_commits.end()
2519 fm_commits.end()
2525
2520
2526 fm_files = fm.nested(b'files')
2521 fm_files = fm.nested(b'files')
2527 if ms.active():
2522 if ms.active():
2528 for f in ms:
2523 for f in ms:
2529 fm_files.startitem()
2524 fm_files.startitem()
2530 fm_files.data(path=f)
2525 fm_files.data(path=f)
2531 state = ms._state[f]
2526 state = ms._state[f]
2532 fm_files.data(state=state[0])
2527 fm_files.data(state=state[0])
2533 if state[0] in (
2528 if state[0] in (
2534 mergestatemod.MERGE_RECORD_UNRESOLVED,
2529 mergestatemod.MERGE_RECORD_UNRESOLVED,
2535 mergestatemod.MERGE_RECORD_RESOLVED,
2530 mergestatemod.MERGE_RECORD_RESOLVED,
2536 ):
2531 ):
2537 fm_files.data(local_key=state[1])
2532 fm_files.data(local_key=state[1])
2538 fm_files.data(local_path=state[2])
2533 fm_files.data(local_path=state[2])
2539 fm_files.data(ancestor_path=state[3])
2534 fm_files.data(ancestor_path=state[3])
2540 fm_files.data(ancestor_node=state[4])
2535 fm_files.data(ancestor_node=state[4])
2541 fm_files.data(other_path=state[5])
2536 fm_files.data(other_path=state[5])
2542 fm_files.data(other_node=state[6])
2537 fm_files.data(other_node=state[6])
2543 fm_files.data(local_flags=state[7])
2538 fm_files.data(local_flags=state[7])
2544 elif state[0] in (
2539 elif state[0] in (
2545 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2540 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2546 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2541 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2547 ):
2542 ):
2548 fm_files.data(renamed_path=state[1])
2543 fm_files.data(renamed_path=state[1])
2549 fm_files.data(rename_side=state[2])
2544 fm_files.data(rename_side=state[2])
2550 fm_extras = fm_files.nested(b'extras')
2545 fm_extras = fm_files.nested(b'extras')
2551 for k, v in sorted(ms.extras(f).items()):
2546 for k, v in sorted(ms.extras(f).items()):
2552 fm_extras.startitem()
2547 fm_extras.startitem()
2553 fm_extras.data(key=k)
2548 fm_extras.data(key=k)
2554 fm_extras.data(value=v)
2549 fm_extras.data(value=v)
2555 fm_extras.end()
2550 fm_extras.end()
2556
2551
2557 fm_files.end()
2552 fm_files.end()
2558
2553
2559 fm_extras = fm.nested(b'extras')
2554 fm_extras = fm.nested(b'extras')
2560 for f, d in sorted(ms.allextras().items()):
2555 for f, d in sorted(ms.allextras().items()):
2561 if f in ms:
2556 if f in ms:
2562 # If file is in mergestate, we have already processed it's extras
2557 # If file is in mergestate, we have already processed it's extras
2563 continue
2558 continue
2564 for k, v in d.items():
2559 for k, v in d.items():
2565 fm_extras.startitem()
2560 fm_extras.startitem()
2566 fm_extras.data(file=f)
2561 fm_extras.data(file=f)
2567 fm_extras.data(key=k)
2562 fm_extras.data(key=k)
2568 fm_extras.data(value=v)
2563 fm_extras.data(value=v)
2569 fm_extras.end()
2564 fm_extras.end()
2570
2565
2571 fm.end()
2566 fm.end()
2572
2567
2573
2568
2574 @command(b'debugnamecomplete', [], _(b'NAME...'))
2569 @command(b'debugnamecomplete', [], _(b'NAME...'))
2575 def debugnamecomplete(ui, repo, *args):
2570 def debugnamecomplete(ui, repo, *args):
2576 '''complete "names" - tags, open branch names, bookmark names'''
2571 '''complete "names" - tags, open branch names, bookmark names'''
2577
2572
2578 names = set()
2573 names = set()
2579 # since we previously only listed open branches, we will handle that
2574 # since we previously only listed open branches, we will handle that
2580 # specially (after this for loop)
2575 # specially (after this for loop)
2581 for name, ns in repo.names.items():
2576 for name, ns in repo.names.items():
2582 if name != b'branches':
2577 if name != b'branches':
2583 names.update(ns.listnames(repo))
2578 names.update(ns.listnames(repo))
2584 names.update(
2579 names.update(
2585 tag
2580 tag
2586 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2581 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2587 if not closed
2582 if not closed
2588 )
2583 )
2589 completions = set()
2584 completions = set()
2590 if not args:
2585 if not args:
2591 args = [b'']
2586 args = [b'']
2592 for a in args:
2587 for a in args:
2593 completions.update(n for n in names if n.startswith(a))
2588 completions.update(n for n in names if n.startswith(a))
2594 ui.write(b'\n'.join(sorted(completions)))
2589 ui.write(b'\n'.join(sorted(completions)))
2595 ui.write(b'\n')
2590 ui.write(b'\n')
2596
2591
2597
2592
2598 @command(
2593 @command(
2599 b'debugnodemap',
2594 b'debugnodemap',
2600 [
2595 [
2601 (
2596 (
2602 b'',
2597 b'',
2603 b'dump-new',
2598 b'dump-new',
2604 False,
2599 False,
2605 _(b'write a (new) persistent binary nodemap on stdout'),
2600 _(b'write a (new) persistent binary nodemap on stdout'),
2606 ),
2601 ),
2607 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2602 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2608 (
2603 (
2609 b'',
2604 b'',
2610 b'check',
2605 b'check',
2611 False,
2606 False,
2612 _(b'check that the data on disk data are correct.'),
2607 _(b'check that the data on disk data are correct.'),
2613 ),
2608 ),
2614 (
2609 (
2615 b'',
2610 b'',
2616 b'metadata',
2611 b'metadata',
2617 False,
2612 False,
2618 _(b'display the on disk meta data for the nodemap'),
2613 _(b'display the on disk meta data for the nodemap'),
2619 ),
2614 ),
2620 ],
2615 ],
2621 )
2616 )
2622 def debugnodemap(ui, repo, **opts):
2617 def debugnodemap(ui, repo, **opts):
2623 """write and inspect on disk nodemap"""
2618 """write and inspect on disk nodemap"""
2624 if opts['dump_new']:
2619 if opts['dump_new']:
2625 unfi = repo.unfiltered()
2620 unfi = repo.unfiltered()
2626 cl = unfi.changelog
2621 cl = unfi.changelog
2627 if util.safehasattr(cl.index, "nodemap_data_all"):
2622 if util.safehasattr(cl.index, "nodemap_data_all"):
2628 data = cl.index.nodemap_data_all()
2623 data = cl.index.nodemap_data_all()
2629 else:
2624 else:
2630 data = nodemap.persistent_data(cl.index)
2625 data = nodemap.persistent_data(cl.index)
2631 ui.write(data)
2626 ui.write(data)
2632 elif opts['dump_disk']:
2627 elif opts['dump_disk']:
2633 unfi = repo.unfiltered()
2628 unfi = repo.unfiltered()
2634 cl = unfi.changelog
2629 cl = unfi.changelog
2635 nm_data = nodemap.persisted_data(cl)
2630 nm_data = nodemap.persisted_data(cl)
2636 if nm_data is not None:
2631 if nm_data is not None:
2637 docket, data = nm_data
2632 docket, data = nm_data
2638 ui.write(data[:])
2633 ui.write(data[:])
2639 elif opts['check']:
2634 elif opts['check']:
2640 unfi = repo.unfiltered()
2635 unfi = repo.unfiltered()
2641 cl = unfi.changelog
2636 cl = unfi.changelog
2642 nm_data = nodemap.persisted_data(cl)
2637 nm_data = nodemap.persisted_data(cl)
2643 if nm_data is not None:
2638 if nm_data is not None:
2644 docket, data = nm_data
2639 docket, data = nm_data
2645 return nodemap.check_data(ui, cl.index, data)
2640 return nodemap.check_data(ui, cl.index, data)
2646 elif opts['metadata']:
2641 elif opts['metadata']:
2647 unfi = repo.unfiltered()
2642 unfi = repo.unfiltered()
2648 cl = unfi.changelog
2643 cl = unfi.changelog
2649 nm_data = nodemap.persisted_data(cl)
2644 nm_data = nodemap.persisted_data(cl)
2650 if nm_data is not None:
2645 if nm_data is not None:
2651 docket, data = nm_data
2646 docket, data = nm_data
2652 ui.write((b"uid: %s\n") % docket.uid)
2647 ui.write((b"uid: %s\n") % docket.uid)
2653 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2648 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2654 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2649 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2655 ui.write((b"data-length: %d\n") % docket.data_length)
2650 ui.write((b"data-length: %d\n") % docket.data_length)
2656 ui.write((b"data-unused: %d\n") % docket.data_unused)
2651 ui.write((b"data-unused: %d\n") % docket.data_unused)
2657 unused_perc = docket.data_unused * 100.0 / docket.data_length
2652 unused_perc = docket.data_unused * 100.0 / docket.data_length
2658 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2653 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2659
2654
2660
2655
2661 @command(
2656 @command(
2662 b'debugobsolete',
2657 b'debugobsolete',
2663 [
2658 [
2664 (b'', b'flags', 0, _(b'markers flag')),
2659 (b'', b'flags', 0, _(b'markers flag')),
2665 (
2660 (
2666 b'',
2661 b'',
2667 b'record-parents',
2662 b'record-parents',
2668 False,
2663 False,
2669 _(b'record parent information for the precursor'),
2664 _(b'record parent information for the precursor'),
2670 ),
2665 ),
2671 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2666 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2672 (
2667 (
2673 b'',
2668 b'',
2674 b'exclusive',
2669 b'exclusive',
2675 False,
2670 False,
2676 _(b'restrict display to markers only relevant to REV'),
2671 _(b'restrict display to markers only relevant to REV'),
2677 ),
2672 ),
2678 (b'', b'index', False, _(b'display index of the marker')),
2673 (b'', b'index', False, _(b'display index of the marker')),
2679 (b'', b'delete', [], _(b'delete markers specified by indices')),
2674 (b'', b'delete', [], _(b'delete markers specified by indices')),
2680 ]
2675 ]
2681 + cmdutil.commitopts2
2676 + cmdutil.commitopts2
2682 + cmdutil.formatteropts,
2677 + cmdutil.formatteropts,
2683 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2678 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2684 )
2679 )
2685 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2680 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2686 """create arbitrary obsolete marker
2681 """create arbitrary obsolete marker
2687
2682
2688 With no arguments, displays the list of obsolescence markers."""
2683 With no arguments, displays the list of obsolescence markers."""
2689
2684
2690 opts = pycompat.byteskwargs(opts)
2685 opts = pycompat.byteskwargs(opts)
2691
2686
2692 def parsenodeid(s):
2687 def parsenodeid(s):
2693 try:
2688 try:
2694 # We do not use revsingle/revrange functions here to accept
2689 # We do not use revsingle/revrange functions here to accept
2695 # arbitrary node identifiers, possibly not present in the
2690 # arbitrary node identifiers, possibly not present in the
2696 # local repository.
2691 # local repository.
2697 n = bin(s)
2692 n = bin(s)
2698 if len(n) != repo.nodeconstants.nodelen:
2693 if len(n) != repo.nodeconstants.nodelen:
2699 raise ValueError
2694 raise ValueError
2700 return n
2695 return n
2701 except ValueError:
2696 except ValueError:
2702 raise error.InputError(
2697 raise error.InputError(
2703 b'changeset references must be full hexadecimal '
2698 b'changeset references must be full hexadecimal '
2704 b'node identifiers'
2699 b'node identifiers'
2705 )
2700 )
2706
2701
2707 if opts.get(b'delete'):
2702 if opts.get(b'delete'):
2708 indices = []
2703 indices = []
2709 for v in opts.get(b'delete'):
2704 for v in opts.get(b'delete'):
2710 try:
2705 try:
2711 indices.append(int(v))
2706 indices.append(int(v))
2712 except ValueError:
2707 except ValueError:
2713 raise error.InputError(
2708 raise error.InputError(
2714 _(b'invalid index value: %r') % v,
2709 _(b'invalid index value: %r') % v,
2715 hint=_(b'use integers for indices'),
2710 hint=_(b'use integers for indices'),
2716 )
2711 )
2717
2712
2718 if repo.currenttransaction():
2713 if repo.currenttransaction():
2719 raise error.Abort(
2714 raise error.Abort(
2720 _(b'cannot delete obsmarkers in the middle of transaction.')
2715 _(b'cannot delete obsmarkers in the middle of transaction.')
2721 )
2716 )
2722
2717
2723 with repo.lock():
2718 with repo.lock():
2724 n = repair.deleteobsmarkers(repo.obsstore, indices)
2719 n = repair.deleteobsmarkers(repo.obsstore, indices)
2725 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2720 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2726
2721
2727 return
2722 return
2728
2723
2729 if precursor is not None:
2724 if precursor is not None:
2730 if opts[b'rev']:
2725 if opts[b'rev']:
2731 raise error.InputError(
2726 raise error.InputError(
2732 b'cannot select revision when creating marker'
2727 b'cannot select revision when creating marker'
2733 )
2728 )
2734 metadata = {}
2729 metadata = {}
2735 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2730 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2736 succs = tuple(parsenodeid(succ) for succ in successors)
2731 succs = tuple(parsenodeid(succ) for succ in successors)
2737 l = repo.lock()
2732 l = repo.lock()
2738 try:
2733 try:
2739 tr = repo.transaction(b'debugobsolete')
2734 tr = repo.transaction(b'debugobsolete')
2740 try:
2735 try:
2741 date = opts.get(b'date')
2736 date = opts.get(b'date')
2742 if date:
2737 if date:
2743 date = dateutil.parsedate(date)
2738 date = dateutil.parsedate(date)
2744 else:
2739 else:
2745 date = None
2740 date = None
2746 prec = parsenodeid(precursor)
2741 prec = parsenodeid(precursor)
2747 parents = None
2742 parents = None
2748 if opts[b'record_parents']:
2743 if opts[b'record_parents']:
2749 if prec not in repo.unfiltered():
2744 if prec not in repo.unfiltered():
2750 raise error.Abort(
2745 raise error.Abort(
2751 b'cannot used --record-parents on '
2746 b'cannot used --record-parents on '
2752 b'unknown changesets'
2747 b'unknown changesets'
2753 )
2748 )
2754 parents = repo.unfiltered()[prec].parents()
2749 parents = repo.unfiltered()[prec].parents()
2755 parents = tuple(p.node() for p in parents)
2750 parents = tuple(p.node() for p in parents)
2756 repo.obsstore.create(
2751 repo.obsstore.create(
2757 tr,
2752 tr,
2758 prec,
2753 prec,
2759 succs,
2754 succs,
2760 opts[b'flags'],
2755 opts[b'flags'],
2761 parents=parents,
2756 parents=parents,
2762 date=date,
2757 date=date,
2763 metadata=metadata,
2758 metadata=metadata,
2764 ui=ui,
2759 ui=ui,
2765 )
2760 )
2766 tr.close()
2761 tr.close()
2767 except ValueError as exc:
2762 except ValueError as exc:
2768 raise error.Abort(
2763 raise error.Abort(
2769 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2764 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2770 )
2765 )
2771 finally:
2766 finally:
2772 tr.release()
2767 tr.release()
2773 finally:
2768 finally:
2774 l.release()
2769 l.release()
2775 else:
2770 else:
2776 if opts[b'rev']:
2771 if opts[b'rev']:
2777 revs = logcmdutil.revrange(repo, opts[b'rev'])
2772 revs = logcmdutil.revrange(repo, opts[b'rev'])
2778 nodes = [repo[r].node() for r in revs]
2773 nodes = [repo[r].node() for r in revs]
2779 markers = list(
2774 markers = list(
2780 obsutil.getmarkers(
2775 obsutil.getmarkers(
2781 repo, nodes=nodes, exclusive=opts[b'exclusive']
2776 repo, nodes=nodes, exclusive=opts[b'exclusive']
2782 )
2777 )
2783 )
2778 )
2784 markers.sort(key=lambda x: x._data)
2779 markers.sort(key=lambda x: x._data)
2785 else:
2780 else:
2786 markers = obsutil.getmarkers(repo)
2781 markers = obsutil.getmarkers(repo)
2787
2782
2788 markerstoiter = markers
2783 markerstoiter = markers
2789 isrelevant = lambda m: True
2784 isrelevant = lambda m: True
2790 if opts.get(b'rev') and opts.get(b'index'):
2785 if opts.get(b'rev') and opts.get(b'index'):
2791 markerstoiter = obsutil.getmarkers(repo)
2786 markerstoiter = obsutil.getmarkers(repo)
2792 markerset = set(markers)
2787 markerset = set(markers)
2793 isrelevant = lambda m: m in markerset
2788 isrelevant = lambda m: m in markerset
2794
2789
2795 fm = ui.formatter(b'debugobsolete', opts)
2790 fm = ui.formatter(b'debugobsolete', opts)
2796 for i, m in enumerate(markerstoiter):
2791 for i, m in enumerate(markerstoiter):
2797 if not isrelevant(m):
2792 if not isrelevant(m):
2798 # marker can be irrelevant when we're iterating over a set
2793 # marker can be irrelevant when we're iterating over a set
2799 # of markers (markerstoiter) which is bigger than the set
2794 # of markers (markerstoiter) which is bigger than the set
2800 # of markers we want to display (markers)
2795 # of markers we want to display (markers)
2801 # this can happen if both --index and --rev options are
2796 # this can happen if both --index and --rev options are
2802 # provided and thus we need to iterate over all of the markers
2797 # provided and thus we need to iterate over all of the markers
2803 # to get the correct indices, but only display the ones that
2798 # to get the correct indices, but only display the ones that
2804 # are relevant to --rev value
2799 # are relevant to --rev value
2805 continue
2800 continue
2806 fm.startitem()
2801 fm.startitem()
2807 ind = i if opts.get(b'index') else None
2802 ind = i if opts.get(b'index') else None
2808 cmdutil.showmarker(fm, m, index=ind)
2803 cmdutil.showmarker(fm, m, index=ind)
2809 fm.end()
2804 fm.end()
2810
2805
2811
2806
2812 @command(
2807 @command(
2813 b'debugp1copies',
2808 b'debugp1copies',
2814 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2809 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2815 _(b'[-r REV]'),
2810 _(b'[-r REV]'),
2816 )
2811 )
2817 def debugp1copies(ui, repo, **opts):
2812 def debugp1copies(ui, repo, **opts):
2818 """dump copy information compared to p1"""
2813 """dump copy information compared to p1"""
2819
2814
2820 opts = pycompat.byteskwargs(opts)
2815 opts = pycompat.byteskwargs(opts)
2821 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2816 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2822 for dst, src in ctx.p1copies().items():
2817 for dst, src in ctx.p1copies().items():
2823 ui.write(b'%s -> %s\n' % (src, dst))
2818 ui.write(b'%s -> %s\n' % (src, dst))
2824
2819
2825
2820
2826 @command(
2821 @command(
2827 b'debugp2copies',
2822 b'debugp2copies',
2828 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2823 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2829 _(b'[-r REV]'),
2824 _(b'[-r REV]'),
2830 )
2825 )
2831 def debugp2copies(ui, repo, **opts):
2826 def debugp2copies(ui, repo, **opts):
2832 """dump copy information compared to p2"""
2827 """dump copy information compared to p2"""
2833
2828
2834 opts = pycompat.byteskwargs(opts)
2829 opts = pycompat.byteskwargs(opts)
2835 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2830 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2836 for dst, src in ctx.p2copies().items():
2831 for dst, src in ctx.p2copies().items():
2837 ui.write(b'%s -> %s\n' % (src, dst))
2832 ui.write(b'%s -> %s\n' % (src, dst))
2838
2833
2839
2834
2840 @command(
2835 @command(
2841 b'debugpathcomplete',
2836 b'debugpathcomplete',
2842 [
2837 [
2843 (b'f', b'full', None, _(b'complete an entire path')),
2838 (b'f', b'full', None, _(b'complete an entire path')),
2844 (b'n', b'normal', None, _(b'show only normal files')),
2839 (b'n', b'normal', None, _(b'show only normal files')),
2845 (b'a', b'added', None, _(b'show only added files')),
2840 (b'a', b'added', None, _(b'show only added files')),
2846 (b'r', b'removed', None, _(b'show only removed files')),
2841 (b'r', b'removed', None, _(b'show only removed files')),
2847 ],
2842 ],
2848 _(b'FILESPEC...'),
2843 _(b'FILESPEC...'),
2849 )
2844 )
2850 def debugpathcomplete(ui, repo, *specs, **opts):
2845 def debugpathcomplete(ui, repo, *specs, **opts):
2851 """complete part or all of a tracked path
2846 """complete part or all of a tracked path
2852
2847
2853 This command supports shells that offer path name completion. It
2848 This command supports shells that offer path name completion. It
2854 currently completes only files already known to the dirstate.
2849 currently completes only files already known to the dirstate.
2855
2850
2856 Completion extends only to the next path segment unless
2851 Completion extends only to the next path segment unless
2857 --full is specified, in which case entire paths are used."""
2852 --full is specified, in which case entire paths are used."""
2858
2853
2859 def complete(path, acceptable):
2854 def complete(path, acceptable):
2860 dirstate = repo.dirstate
2855 dirstate = repo.dirstate
2861 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2856 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2862 rootdir = repo.root + pycompat.ossep
2857 rootdir = repo.root + pycompat.ossep
2863 if spec != repo.root and not spec.startswith(rootdir):
2858 if spec != repo.root and not spec.startswith(rootdir):
2864 return [], []
2859 return [], []
2865 if os.path.isdir(spec):
2860 if os.path.isdir(spec):
2866 spec += b'/'
2861 spec += b'/'
2867 spec = spec[len(rootdir) :]
2862 spec = spec[len(rootdir) :]
2868 fixpaths = pycompat.ossep != b'/'
2863 fixpaths = pycompat.ossep != b'/'
2869 if fixpaths:
2864 if fixpaths:
2870 spec = spec.replace(pycompat.ossep, b'/')
2865 spec = spec.replace(pycompat.ossep, b'/')
2871 speclen = len(spec)
2866 speclen = len(spec)
2872 fullpaths = opts['full']
2867 fullpaths = opts['full']
2873 files, dirs = set(), set()
2868 files, dirs = set(), set()
2874 adddir, addfile = dirs.add, files.add
2869 adddir, addfile = dirs.add, files.add
2875 for f, st in dirstate.items():
2870 for f, st in dirstate.items():
2876 if f.startswith(spec) and st.state in acceptable:
2871 if f.startswith(spec) and st.state in acceptable:
2877 if fixpaths:
2872 if fixpaths:
2878 f = f.replace(b'/', pycompat.ossep)
2873 f = f.replace(b'/', pycompat.ossep)
2879 if fullpaths:
2874 if fullpaths:
2880 addfile(f)
2875 addfile(f)
2881 continue
2876 continue
2882 s = f.find(pycompat.ossep, speclen)
2877 s = f.find(pycompat.ossep, speclen)
2883 if s >= 0:
2878 if s >= 0:
2884 adddir(f[:s])
2879 adddir(f[:s])
2885 else:
2880 else:
2886 addfile(f)
2881 addfile(f)
2887 return files, dirs
2882 return files, dirs
2888
2883
2889 acceptable = b''
2884 acceptable = b''
2890 if opts['normal']:
2885 if opts['normal']:
2891 acceptable += b'nm'
2886 acceptable += b'nm'
2892 if opts['added']:
2887 if opts['added']:
2893 acceptable += b'a'
2888 acceptable += b'a'
2894 if opts['removed']:
2889 if opts['removed']:
2895 acceptable += b'r'
2890 acceptable += b'r'
2896 cwd = repo.getcwd()
2891 cwd = repo.getcwd()
2897 if not specs:
2892 if not specs:
2898 specs = [b'.']
2893 specs = [b'.']
2899
2894
2900 files, dirs = set(), set()
2895 files, dirs = set(), set()
2901 for spec in specs:
2896 for spec in specs:
2902 f, d = complete(spec, acceptable or b'nmar')
2897 f, d = complete(spec, acceptable or b'nmar')
2903 files.update(f)
2898 files.update(f)
2904 dirs.update(d)
2899 dirs.update(d)
2905 files.update(dirs)
2900 files.update(dirs)
2906 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2901 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2907 ui.write(b'\n')
2902 ui.write(b'\n')
2908
2903
2909
2904
2910 @command(
2905 @command(
2911 b'debugpathcopies',
2906 b'debugpathcopies',
2912 cmdutil.walkopts,
2907 cmdutil.walkopts,
2913 b'hg debugpathcopies REV1 REV2 [FILE]',
2908 b'hg debugpathcopies REV1 REV2 [FILE]',
2914 inferrepo=True,
2909 inferrepo=True,
2915 )
2910 )
2916 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2911 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2917 """show copies between two revisions"""
2912 """show copies between two revisions"""
2918 ctx1 = scmutil.revsingle(repo, rev1)
2913 ctx1 = scmutil.revsingle(repo, rev1)
2919 ctx2 = scmutil.revsingle(repo, rev2)
2914 ctx2 = scmutil.revsingle(repo, rev2)
2920 m = scmutil.match(ctx1, pats, opts)
2915 m = scmutil.match(ctx1, pats, opts)
2921 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2916 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2922 ui.write(b'%s -> %s\n' % (src, dst))
2917 ui.write(b'%s -> %s\n' % (src, dst))
2923
2918
2924
2919
2925 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2920 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2926 def debugpeer(ui, path):
2921 def debugpeer(ui, path):
2927 """establish a connection to a peer repository"""
2922 """establish a connection to a peer repository"""
2928 # Always enable peer request logging. Requires --debug to display
2923 # Always enable peer request logging. Requires --debug to display
2929 # though.
2924 # though.
2930 overrides = {
2925 overrides = {
2931 (b'devel', b'debug.peer-request'): True,
2926 (b'devel', b'debug.peer-request'): True,
2932 }
2927 }
2933
2928
2934 with ui.configoverride(overrides):
2929 with ui.configoverride(overrides):
2935 peer = hg.peer(ui, {}, path)
2930 peer = hg.peer(ui, {}, path)
2936
2931
2937 try:
2932 try:
2938 local = peer.local() is not None
2933 local = peer.local() is not None
2939 canpush = peer.canpush()
2934 canpush = peer.canpush()
2940
2935
2941 ui.write(_(b'url: %s\n') % peer.url())
2936 ui.write(_(b'url: %s\n') % peer.url())
2942 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2937 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2943 ui.write(
2938 ui.write(
2944 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2939 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2945 )
2940 )
2946 finally:
2941 finally:
2947 peer.close()
2942 peer.close()
2948
2943
2949
2944
2950 @command(
2945 @command(
2951 b'debugpickmergetool',
2946 b'debugpickmergetool',
2952 [
2947 [
2953 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2948 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2954 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2949 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2955 ]
2950 ]
2956 + cmdutil.walkopts
2951 + cmdutil.walkopts
2957 + cmdutil.mergetoolopts,
2952 + cmdutil.mergetoolopts,
2958 _(b'[PATTERN]...'),
2953 _(b'[PATTERN]...'),
2959 inferrepo=True,
2954 inferrepo=True,
2960 )
2955 )
2961 def debugpickmergetool(ui, repo, *pats, **opts):
2956 def debugpickmergetool(ui, repo, *pats, **opts):
2962 """examine which merge tool is chosen for specified file
2957 """examine which merge tool is chosen for specified file
2963
2958
2964 As described in :hg:`help merge-tools`, Mercurial examines
2959 As described in :hg:`help merge-tools`, Mercurial examines
2965 configurations below in this order to decide which merge tool is
2960 configurations below in this order to decide which merge tool is
2966 chosen for specified file.
2961 chosen for specified file.
2967
2962
2968 1. ``--tool`` option
2963 1. ``--tool`` option
2969 2. ``HGMERGE`` environment variable
2964 2. ``HGMERGE`` environment variable
2970 3. configurations in ``merge-patterns`` section
2965 3. configurations in ``merge-patterns`` section
2971 4. configuration of ``ui.merge``
2966 4. configuration of ``ui.merge``
2972 5. configurations in ``merge-tools`` section
2967 5. configurations in ``merge-tools`` section
2973 6. ``hgmerge`` tool (for historical reason only)
2968 6. ``hgmerge`` tool (for historical reason only)
2974 7. default tool for fallback (``:merge`` or ``:prompt``)
2969 7. default tool for fallback (``:merge`` or ``:prompt``)
2975
2970
2976 This command writes out examination result in the style below::
2971 This command writes out examination result in the style below::
2977
2972
2978 FILE = MERGETOOL
2973 FILE = MERGETOOL
2979
2974
2980 By default, all files known in the first parent context of the
2975 By default, all files known in the first parent context of the
2981 working directory are examined. Use file patterns and/or -I/-X
2976 working directory are examined. Use file patterns and/or -I/-X
2982 options to limit target files. -r/--rev is also useful to examine
2977 options to limit target files. -r/--rev is also useful to examine
2983 files in another context without actual updating to it.
2978 files in another context without actual updating to it.
2984
2979
2985 With --debug, this command shows warning messages while matching
2980 With --debug, this command shows warning messages while matching
2986 against ``merge-patterns`` and so on, too. It is recommended to
2981 against ``merge-patterns`` and so on, too. It is recommended to
2987 use this option with explicit file patterns and/or -I/-X options,
2982 use this option with explicit file patterns and/or -I/-X options,
2988 because this option increases amount of output per file according
2983 because this option increases amount of output per file according
2989 to configurations in hgrc.
2984 to configurations in hgrc.
2990
2985
2991 With -v/--verbose, this command shows configurations below at
2986 With -v/--verbose, this command shows configurations below at
2992 first (only if specified).
2987 first (only if specified).
2993
2988
2994 - ``--tool`` option
2989 - ``--tool`` option
2995 - ``HGMERGE`` environment variable
2990 - ``HGMERGE`` environment variable
2996 - configuration of ``ui.merge``
2991 - configuration of ``ui.merge``
2997
2992
2998 If merge tool is chosen before matching against
2993 If merge tool is chosen before matching against
2999 ``merge-patterns``, this command can't show any helpful
2994 ``merge-patterns``, this command can't show any helpful
3000 information, even with --debug. In such case, information above is
2995 information, even with --debug. In such case, information above is
3001 useful to know why a merge tool is chosen.
2996 useful to know why a merge tool is chosen.
3002 """
2997 """
3003 opts = pycompat.byteskwargs(opts)
2998 opts = pycompat.byteskwargs(opts)
3004 overrides = {}
2999 overrides = {}
3005 if opts[b'tool']:
3000 if opts[b'tool']:
3006 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
3001 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
3007 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
3002 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
3008
3003
3009 with ui.configoverride(overrides, b'debugmergepatterns'):
3004 with ui.configoverride(overrides, b'debugmergepatterns'):
3010 hgmerge = encoding.environ.get(b"HGMERGE")
3005 hgmerge = encoding.environ.get(b"HGMERGE")
3011 if hgmerge is not None:
3006 if hgmerge is not None:
3012 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
3007 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
3013 uimerge = ui.config(b"ui", b"merge")
3008 uimerge = ui.config(b"ui", b"merge")
3014 if uimerge:
3009 if uimerge:
3015 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
3010 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
3016
3011
3017 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3012 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3018 m = scmutil.match(ctx, pats, opts)
3013 m = scmutil.match(ctx, pats, opts)
3019 changedelete = opts[b'changedelete']
3014 changedelete = opts[b'changedelete']
3020 for path in ctx.walk(m):
3015 for path in ctx.walk(m):
3021 fctx = ctx[path]
3016 fctx = ctx[path]
3022 with ui.silent(
3017 with ui.silent(
3023 error=True
3018 error=True
3024 ) if not ui.debugflag else util.nullcontextmanager():
3019 ) if not ui.debugflag else util.nullcontextmanager():
3025 tool, toolpath = filemerge._picktool(
3020 tool, toolpath = filemerge._picktool(
3026 repo,
3021 repo,
3027 ui,
3022 ui,
3028 path,
3023 path,
3029 fctx.isbinary(),
3024 fctx.isbinary(),
3030 b'l' in fctx.flags(),
3025 b'l' in fctx.flags(),
3031 changedelete,
3026 changedelete,
3032 )
3027 )
3033 ui.write(b'%s = %s\n' % (path, tool))
3028 ui.write(b'%s = %s\n' % (path, tool))
3034
3029
3035
3030
3036 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3031 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3037 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3032 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3038 """access the pushkey key/value protocol
3033 """access the pushkey key/value protocol
3039
3034
3040 With two args, list the keys in the given namespace.
3035 With two args, list the keys in the given namespace.
3041
3036
3042 With five args, set a key to new if it currently is set to old.
3037 With five args, set a key to new if it currently is set to old.
3043 Reports success or failure.
3038 Reports success or failure.
3044 """
3039 """
3045
3040
3046 target = hg.peer(ui, {}, repopath)
3041 target = hg.peer(ui, {}, repopath)
3047 try:
3042 try:
3048 if keyinfo:
3043 if keyinfo:
3049 key, old, new = keyinfo
3044 key, old, new = keyinfo
3050 with target.commandexecutor() as e:
3045 with target.commandexecutor() as e:
3051 r = e.callcommand(
3046 r = e.callcommand(
3052 b'pushkey',
3047 b'pushkey',
3053 {
3048 {
3054 b'namespace': namespace,
3049 b'namespace': namespace,
3055 b'key': key,
3050 b'key': key,
3056 b'old': old,
3051 b'old': old,
3057 b'new': new,
3052 b'new': new,
3058 },
3053 },
3059 ).result()
3054 ).result()
3060
3055
3061 ui.status(pycompat.bytestr(r) + b'\n')
3056 ui.status(pycompat.bytestr(r) + b'\n')
3062 return not r
3057 return not r
3063 else:
3058 else:
3064 for k, v in sorted(target.listkeys(namespace).items()):
3059 for k, v in sorted(target.listkeys(namespace).items()):
3065 ui.write(
3060 ui.write(
3066 b"%s\t%s\n"
3061 b"%s\t%s\n"
3067 % (stringutil.escapestr(k), stringutil.escapestr(v))
3062 % (stringutil.escapestr(k), stringutil.escapestr(v))
3068 )
3063 )
3069 finally:
3064 finally:
3070 target.close()
3065 target.close()
3071
3066
3072
3067
3073 @command(b'debugpvec', [], _(b'A B'))
3068 @command(b'debugpvec', [], _(b'A B'))
3074 def debugpvec(ui, repo, a, b=None):
3069 def debugpvec(ui, repo, a, b=None):
3075 ca = scmutil.revsingle(repo, a)
3070 ca = scmutil.revsingle(repo, a)
3076 cb = scmutil.revsingle(repo, b)
3071 cb = scmutil.revsingle(repo, b)
3077 pa = pvec.ctxpvec(ca)
3072 pa = pvec.ctxpvec(ca)
3078 pb = pvec.ctxpvec(cb)
3073 pb = pvec.ctxpvec(cb)
3079 if pa == pb:
3074 if pa == pb:
3080 rel = b"="
3075 rel = b"="
3081 elif pa > pb:
3076 elif pa > pb:
3082 rel = b">"
3077 rel = b">"
3083 elif pa < pb:
3078 elif pa < pb:
3084 rel = b"<"
3079 rel = b"<"
3085 elif pa | pb:
3080 elif pa | pb:
3086 rel = b"|"
3081 rel = b"|"
3087 ui.write(_(b"a: %s\n") % pa)
3082 ui.write(_(b"a: %s\n") % pa)
3088 ui.write(_(b"b: %s\n") % pb)
3083 ui.write(_(b"b: %s\n") % pb)
3089 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3084 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3090 ui.write(
3085 ui.write(
3091 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3086 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3092 % (
3087 % (
3093 abs(pa._depth - pb._depth),
3088 abs(pa._depth - pb._depth),
3094 pvec._hamming(pa._vec, pb._vec),
3089 pvec._hamming(pa._vec, pb._vec),
3095 pa.distance(pb),
3090 pa.distance(pb),
3096 rel,
3091 rel,
3097 )
3092 )
3098 )
3093 )
3099
3094
3100
3095
3101 @command(
3096 @command(
3102 b'debugrebuilddirstate|debugrebuildstate',
3097 b'debugrebuilddirstate|debugrebuildstate',
3103 [
3098 [
3104 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3099 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3105 (
3100 (
3106 b'',
3101 b'',
3107 b'minimal',
3102 b'minimal',
3108 None,
3103 None,
3109 _(
3104 _(
3110 b'only rebuild files that are inconsistent with '
3105 b'only rebuild files that are inconsistent with '
3111 b'the working copy parent'
3106 b'the working copy parent'
3112 ),
3107 ),
3113 ),
3108 ),
3114 ],
3109 ],
3115 _(b'[-r REV]'),
3110 _(b'[-r REV]'),
3116 )
3111 )
3117 def debugrebuilddirstate(ui, repo, rev, **opts):
3112 def debugrebuilddirstate(ui, repo, rev, **opts):
3118 """rebuild the dirstate as it would look like for the given revision
3113 """rebuild the dirstate as it would look like for the given revision
3119
3114
3120 If no revision is specified the first current parent will be used.
3115 If no revision is specified the first current parent will be used.
3121
3116
3122 The dirstate will be set to the files of the given revision.
3117 The dirstate will be set to the files of the given revision.
3123 The actual working directory content or existing dirstate
3118 The actual working directory content or existing dirstate
3124 information such as adds or removes is not considered.
3119 information such as adds or removes is not considered.
3125
3120
3126 ``minimal`` will only rebuild the dirstate status for files that claim to be
3121 ``minimal`` will only rebuild the dirstate status for files that claim to be
3127 tracked but are not in the parent manifest, or that exist in the parent
3122 tracked but are not in the parent manifest, or that exist in the parent
3128 manifest but are not in the dirstate. It will not change adds, removes, or
3123 manifest but are not in the dirstate. It will not change adds, removes, or
3129 modified files that are in the working copy parent.
3124 modified files that are in the working copy parent.
3130
3125
3131 One use of this command is to make the next :hg:`status` invocation
3126 One use of this command is to make the next :hg:`status` invocation
3132 check the actual file content.
3127 check the actual file content.
3133 """
3128 """
3134 ctx = scmutil.revsingle(repo, rev)
3129 ctx = scmutil.revsingle(repo, rev)
3135 with repo.wlock():
3130 with repo.wlock():
3136 dirstate = repo.dirstate
3131 dirstate = repo.dirstate
3137 changedfiles = None
3132 changedfiles = None
3138 # See command doc for what minimal does.
3133 # See command doc for what minimal does.
3139 if opts.get('minimal'):
3134 if opts.get('minimal'):
3140 manifestfiles = set(ctx.manifest().keys())
3135 manifestfiles = set(ctx.manifest().keys())
3141 dirstatefiles = set(dirstate)
3136 dirstatefiles = set(dirstate)
3142 manifestonly = manifestfiles - dirstatefiles
3137 manifestonly = manifestfiles - dirstatefiles
3143 dsonly = dirstatefiles - manifestfiles
3138 dsonly = dirstatefiles - manifestfiles
3144 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3139 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3145 changedfiles = manifestonly | dsnotadded
3140 changedfiles = manifestonly | dsnotadded
3146
3141
3147 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3142 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3148
3143
3149
3144
3150 @command(
3145 @command(
3151 b'debugrebuildfncache',
3146 b'debugrebuildfncache',
3152 [
3147 [
3153 (
3148 (
3154 b'',
3149 b'',
3155 b'only-data',
3150 b'only-data',
3156 False,
3151 False,
3157 _(b'only look for wrong .d files (much faster)'),
3152 _(b'only look for wrong .d files (much faster)'),
3158 )
3153 )
3159 ],
3154 ],
3160 b'',
3155 b'',
3161 )
3156 )
3162 def debugrebuildfncache(ui, repo, **opts):
3157 def debugrebuildfncache(ui, repo, **opts):
3163 """rebuild the fncache file"""
3158 """rebuild the fncache file"""
3164 opts = pycompat.byteskwargs(opts)
3159 opts = pycompat.byteskwargs(opts)
3165 repair.rebuildfncache(ui, repo, opts.get(b"only_data"))
3160 repair.rebuildfncache(ui, repo, opts.get(b"only_data"))
3166
3161
3167
3162
3168 @command(
3163 @command(
3169 b'debugrename',
3164 b'debugrename',
3170 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3165 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3171 _(b'[-r REV] [FILE]...'),
3166 _(b'[-r REV] [FILE]...'),
3172 )
3167 )
3173 def debugrename(ui, repo, *pats, **opts):
3168 def debugrename(ui, repo, *pats, **opts):
3174 """dump rename information"""
3169 """dump rename information"""
3175
3170
3176 opts = pycompat.byteskwargs(opts)
3171 opts = pycompat.byteskwargs(opts)
3177 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3172 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3178 m = scmutil.match(ctx, pats, opts)
3173 m = scmutil.match(ctx, pats, opts)
3179 for abs in ctx.walk(m):
3174 for abs in ctx.walk(m):
3180 fctx = ctx[abs]
3175 fctx = ctx[abs]
3181 o = fctx.filelog().renamed(fctx.filenode())
3176 o = fctx.filelog().renamed(fctx.filenode())
3182 rel = repo.pathto(abs)
3177 rel = repo.pathto(abs)
3183 if o:
3178 if o:
3184 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3179 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3185 else:
3180 else:
3186 ui.write(_(b"%s not renamed\n") % rel)
3181 ui.write(_(b"%s not renamed\n") % rel)
3187
3182
3188
3183
3189 @command(b'debugrequires|debugrequirements', [], b'')
3184 @command(b'debugrequires|debugrequirements', [], b'')
3190 def debugrequirements(ui, repo):
3185 def debugrequirements(ui, repo):
3191 """print the current repo requirements"""
3186 """print the current repo requirements"""
3192 for r in sorted(repo.requirements):
3187 for r in sorted(repo.requirements):
3193 ui.write(b"%s\n" % r)
3188 ui.write(b"%s\n" % r)
3194
3189
3195
3190
3196 @command(
3191 @command(
3197 b'debugrevlog',
3192 b'debugrevlog',
3198 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3193 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3199 _(b'-c|-m|FILE'),
3194 _(b'-c|-m|FILE'),
3200 optionalrepo=True,
3195 optionalrepo=True,
3201 )
3196 )
3202 def debugrevlog(ui, repo, file_=None, **opts):
3197 def debugrevlog(ui, repo, file_=None, **opts):
3203 """show data and statistics about a revlog"""
3198 """show data and statistics about a revlog"""
3204 opts = pycompat.byteskwargs(opts)
3199 opts = pycompat.byteskwargs(opts)
3205 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
3200 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
3206
3201
3207 if opts.get(b"dump"):
3202 if opts.get(b"dump"):
3208 revlog_debug.dump(ui, r)
3203 revlog_debug.dump(ui, r)
3209 else:
3204 else:
3210 revlog_debug.debug_revlog(ui, r)
3205 revlog_debug.debug_revlog(ui, r)
3211 return 0
3206 return 0
3212
3207
3213
3208
3214 @command(
3209 @command(
3215 b'debugrevlogindex',
3210 b'debugrevlogindex',
3216 cmdutil.debugrevlogopts
3211 cmdutil.debugrevlogopts
3217 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3212 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3218 _(b'[-f FORMAT] -c|-m|FILE'),
3213 _(b'[-f FORMAT] -c|-m|FILE'),
3219 optionalrepo=True,
3214 optionalrepo=True,
3220 )
3215 )
3221 def debugrevlogindex(ui, repo, file_=None, **opts):
3216 def debugrevlogindex(ui, repo, file_=None, **opts):
3222 """dump the contents of a revlog index"""
3217 """dump the contents of a revlog index"""
3223 opts = pycompat.byteskwargs(opts)
3218 opts = pycompat.byteskwargs(opts)
3224 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3219 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3225 format = opts.get(b'format', 0)
3220 format = opts.get(b'format', 0)
3226 if format not in (0, 1):
3221 if format not in (0, 1):
3227 raise error.Abort(_(b"unknown format %d") % format)
3222 raise error.Abort(_(b"unknown format %d") % format)
3228
3223
3229 if ui.debugflag:
3224 if ui.debugflag:
3230 shortfn = hex
3225 shortfn = hex
3231 else:
3226 else:
3232 shortfn = short
3227 shortfn = short
3233
3228
3234 # There might not be anything in r, so have a sane default
3229 # There might not be anything in r, so have a sane default
3235 idlen = 12
3230 idlen = 12
3236 for i in r:
3231 for i in r:
3237 idlen = len(shortfn(r.node(i)))
3232 idlen = len(shortfn(r.node(i)))
3238 break
3233 break
3239
3234
3240 if format == 0:
3235 if format == 0:
3241 if ui.verbose:
3236 if ui.verbose:
3242 ui.writenoi18n(
3237 ui.writenoi18n(
3243 b" rev offset length linkrev %s %s p2\n"
3238 b" rev offset length linkrev %s %s p2\n"
3244 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3239 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3245 )
3240 )
3246 else:
3241 else:
3247 ui.writenoi18n(
3242 ui.writenoi18n(
3248 b" rev linkrev %s %s p2\n"
3243 b" rev linkrev %s %s p2\n"
3249 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3244 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3250 )
3245 )
3251 elif format == 1:
3246 elif format == 1:
3252 if ui.verbose:
3247 if ui.verbose:
3253 ui.writenoi18n(
3248 ui.writenoi18n(
3254 (
3249 (
3255 b" rev flag offset length size link p1"
3250 b" rev flag offset length size link p1"
3256 b" p2 %s\n"
3251 b" p2 %s\n"
3257 )
3252 )
3258 % b"nodeid".rjust(idlen)
3253 % b"nodeid".rjust(idlen)
3259 )
3254 )
3260 else:
3255 else:
3261 ui.writenoi18n(
3256 ui.writenoi18n(
3262 b" rev flag size link p1 p2 %s\n"
3257 b" rev flag size link p1 p2 %s\n"
3263 % b"nodeid".rjust(idlen)
3258 % b"nodeid".rjust(idlen)
3264 )
3259 )
3265
3260
3266 for i in r:
3261 for i in r:
3267 node = r.node(i)
3262 node = r.node(i)
3268 if format == 0:
3263 if format == 0:
3269 try:
3264 try:
3270 pp = r.parents(node)
3265 pp = r.parents(node)
3271 except Exception:
3266 except Exception:
3272 pp = [repo.nullid, repo.nullid]
3267 pp = [repo.nullid, repo.nullid]
3273 if ui.verbose:
3268 if ui.verbose:
3274 ui.write(
3269 ui.write(
3275 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3270 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3276 % (
3271 % (
3277 i,
3272 i,
3278 r.start(i),
3273 r.start(i),
3279 r.length(i),
3274 r.length(i),
3280 r.linkrev(i),
3275 r.linkrev(i),
3281 shortfn(node),
3276 shortfn(node),
3282 shortfn(pp[0]),
3277 shortfn(pp[0]),
3283 shortfn(pp[1]),
3278 shortfn(pp[1]),
3284 )
3279 )
3285 )
3280 )
3286 else:
3281 else:
3287 ui.write(
3282 ui.write(
3288 b"% 6d % 7d %s %s %s\n"
3283 b"% 6d % 7d %s %s %s\n"
3289 % (
3284 % (
3290 i,
3285 i,
3291 r.linkrev(i),
3286 r.linkrev(i),
3292 shortfn(node),
3287 shortfn(node),
3293 shortfn(pp[0]),
3288 shortfn(pp[0]),
3294 shortfn(pp[1]),
3289 shortfn(pp[1]),
3295 )
3290 )
3296 )
3291 )
3297 elif format == 1:
3292 elif format == 1:
3298 pr = r.parentrevs(i)
3293 pr = r.parentrevs(i)
3299 if ui.verbose:
3294 if ui.verbose:
3300 ui.write(
3295 ui.write(
3301 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3296 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3302 % (
3297 % (
3303 i,
3298 i,
3304 r.flags(i),
3299 r.flags(i),
3305 r.start(i),
3300 r.start(i),
3306 r.length(i),
3301 r.length(i),
3307 r.rawsize(i),
3302 r.rawsize(i),
3308 r.linkrev(i),
3303 r.linkrev(i),
3309 pr[0],
3304 pr[0],
3310 pr[1],
3305 pr[1],
3311 shortfn(node),
3306 shortfn(node),
3312 )
3307 )
3313 )
3308 )
3314 else:
3309 else:
3315 ui.write(
3310 ui.write(
3316 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3311 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3317 % (
3312 % (
3318 i,
3313 i,
3319 r.flags(i),
3314 r.flags(i),
3320 r.rawsize(i),
3315 r.rawsize(i),
3321 r.linkrev(i),
3316 r.linkrev(i),
3322 pr[0],
3317 pr[0],
3323 pr[1],
3318 pr[1],
3324 shortfn(node),
3319 shortfn(node),
3325 )
3320 )
3326 )
3321 )
3327
3322
3328
3323
3329 @command(
3324 @command(
3330 b'debugrevspec',
3325 b'debugrevspec',
3331 [
3326 [
3332 (
3327 (
3333 b'',
3328 b'',
3334 b'optimize',
3329 b'optimize',
3335 None,
3330 None,
3336 _(b'print parsed tree after optimizing (DEPRECATED)'),
3331 _(b'print parsed tree after optimizing (DEPRECATED)'),
3337 ),
3332 ),
3338 (
3333 (
3339 b'',
3334 b'',
3340 b'show-revs',
3335 b'show-revs',
3341 True,
3336 True,
3342 _(b'print list of result revisions (default)'),
3337 _(b'print list of result revisions (default)'),
3343 ),
3338 ),
3344 (
3339 (
3345 b's',
3340 b's',
3346 b'show-set',
3341 b'show-set',
3347 None,
3342 None,
3348 _(b'print internal representation of result set'),
3343 _(b'print internal representation of result set'),
3349 ),
3344 ),
3350 (
3345 (
3351 b'p',
3346 b'p',
3352 b'show-stage',
3347 b'show-stage',
3353 [],
3348 [],
3354 _(b'print parsed tree at the given stage'),
3349 _(b'print parsed tree at the given stage'),
3355 _(b'NAME'),
3350 _(b'NAME'),
3356 ),
3351 ),
3357 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3352 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3358 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3353 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3359 ],
3354 ],
3360 b'REVSPEC',
3355 b'REVSPEC',
3361 )
3356 )
3362 def debugrevspec(ui, repo, expr, **opts):
3357 def debugrevspec(ui, repo, expr, **opts):
3363 """parse and apply a revision specification
3358 """parse and apply a revision specification
3364
3359
3365 Use -p/--show-stage option to print the parsed tree at the given stages.
3360 Use -p/--show-stage option to print the parsed tree at the given stages.
3366 Use -p all to print tree at every stage.
3361 Use -p all to print tree at every stage.
3367
3362
3368 Use --no-show-revs option with -s or -p to print only the set
3363 Use --no-show-revs option with -s or -p to print only the set
3369 representation or the parsed tree respectively.
3364 representation or the parsed tree respectively.
3370
3365
3371 Use --verify-optimized to compare the optimized result with the unoptimized
3366 Use --verify-optimized to compare the optimized result with the unoptimized
3372 one. Returns 1 if the optimized result differs.
3367 one. Returns 1 if the optimized result differs.
3373 """
3368 """
3374 opts = pycompat.byteskwargs(opts)
3369 opts = pycompat.byteskwargs(opts)
3375 aliases = ui.configitems(b'revsetalias')
3370 aliases = ui.configitems(b'revsetalias')
3376 stages = [
3371 stages = [
3377 (b'parsed', lambda tree: tree),
3372 (b'parsed', lambda tree: tree),
3378 (
3373 (
3379 b'expanded',
3374 b'expanded',
3380 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3375 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3381 ),
3376 ),
3382 (b'concatenated', revsetlang.foldconcat),
3377 (b'concatenated', revsetlang.foldconcat),
3383 (b'analyzed', revsetlang.analyze),
3378 (b'analyzed', revsetlang.analyze),
3384 (b'optimized', revsetlang.optimize),
3379 (b'optimized', revsetlang.optimize),
3385 ]
3380 ]
3386 if opts[b'no_optimized']:
3381 if opts[b'no_optimized']:
3387 stages = stages[:-1]
3382 stages = stages[:-1]
3388 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3383 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3389 raise error.Abort(
3384 raise error.Abort(
3390 _(b'cannot use --verify-optimized with --no-optimized')
3385 _(b'cannot use --verify-optimized with --no-optimized')
3391 )
3386 )
3392 stagenames = {n for n, f in stages}
3387 stagenames = {n for n, f in stages}
3393
3388
3394 showalways = set()
3389 showalways = set()
3395 showchanged = set()
3390 showchanged = set()
3396 if ui.verbose and not opts[b'show_stage']:
3391 if ui.verbose and not opts[b'show_stage']:
3397 # show parsed tree by --verbose (deprecated)
3392 # show parsed tree by --verbose (deprecated)
3398 showalways.add(b'parsed')
3393 showalways.add(b'parsed')
3399 showchanged.update([b'expanded', b'concatenated'])
3394 showchanged.update([b'expanded', b'concatenated'])
3400 if opts[b'optimize']:
3395 if opts[b'optimize']:
3401 showalways.add(b'optimized')
3396 showalways.add(b'optimized')
3402 if opts[b'show_stage'] and opts[b'optimize']:
3397 if opts[b'show_stage'] and opts[b'optimize']:
3403 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3398 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3404 if opts[b'show_stage'] == [b'all']:
3399 if opts[b'show_stage'] == [b'all']:
3405 showalways.update(stagenames)
3400 showalways.update(stagenames)
3406 else:
3401 else:
3407 for n in opts[b'show_stage']:
3402 for n in opts[b'show_stage']:
3408 if n not in stagenames:
3403 if n not in stagenames:
3409 raise error.Abort(_(b'invalid stage name: %s') % n)
3404 raise error.Abort(_(b'invalid stage name: %s') % n)
3410 showalways.update(opts[b'show_stage'])
3405 showalways.update(opts[b'show_stage'])
3411
3406
3412 treebystage = {}
3407 treebystage = {}
3413 printedtree = None
3408 printedtree = None
3414 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3409 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3415 for n, f in stages:
3410 for n, f in stages:
3416 treebystage[n] = tree = f(tree)
3411 treebystage[n] = tree = f(tree)
3417 if n in showalways or (n in showchanged and tree != printedtree):
3412 if n in showalways or (n in showchanged and tree != printedtree):
3418 if opts[b'show_stage'] or n != b'parsed':
3413 if opts[b'show_stage'] or n != b'parsed':
3419 ui.write(b"* %s:\n" % n)
3414 ui.write(b"* %s:\n" % n)
3420 ui.write(revsetlang.prettyformat(tree), b"\n")
3415 ui.write(revsetlang.prettyformat(tree), b"\n")
3421 printedtree = tree
3416 printedtree = tree
3422
3417
3423 if opts[b'verify_optimized']:
3418 if opts[b'verify_optimized']:
3424 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3419 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3425 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3420 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3426 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3421 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3427 ui.writenoi18n(
3422 ui.writenoi18n(
3428 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3423 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3429 )
3424 )
3430 ui.writenoi18n(
3425 ui.writenoi18n(
3431 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3426 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3432 )
3427 )
3433 arevs = list(arevs)
3428 arevs = list(arevs)
3434 brevs = list(brevs)
3429 brevs = list(brevs)
3435 if arevs == brevs:
3430 if arevs == brevs:
3436 return 0
3431 return 0
3437 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3432 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3438 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3433 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3439 sm = difflib.SequenceMatcher(None, arevs, brevs)
3434 sm = difflib.SequenceMatcher(None, arevs, brevs)
3440 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3435 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3441 if tag in ('delete', 'replace'):
3436 if tag in ('delete', 'replace'):
3442 for c in arevs[alo:ahi]:
3437 for c in arevs[alo:ahi]:
3443 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3438 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3444 if tag in ('insert', 'replace'):
3439 if tag in ('insert', 'replace'):
3445 for c in brevs[blo:bhi]:
3440 for c in brevs[blo:bhi]:
3446 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3441 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3447 if tag == 'equal':
3442 if tag == 'equal':
3448 for c in arevs[alo:ahi]:
3443 for c in arevs[alo:ahi]:
3449 ui.write(b' %d\n' % c)
3444 ui.write(b' %d\n' % c)
3450 return 1
3445 return 1
3451
3446
3452 func = revset.makematcher(tree)
3447 func = revset.makematcher(tree)
3453 revs = func(repo)
3448 revs = func(repo)
3454 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3449 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3455 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3450 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3456 if not opts[b'show_revs']:
3451 if not opts[b'show_revs']:
3457 return
3452 return
3458 for c in revs:
3453 for c in revs:
3459 ui.write(b"%d\n" % c)
3454 ui.write(b"%d\n" % c)
3460
3455
3461
3456
3462 @command(
3457 @command(
3463 b'debugserve',
3458 b'debugserve',
3464 [
3459 [
3465 (
3460 (
3466 b'',
3461 b'',
3467 b'sshstdio',
3462 b'sshstdio',
3468 False,
3463 False,
3469 _(b'run an SSH server bound to process handles'),
3464 _(b'run an SSH server bound to process handles'),
3470 ),
3465 ),
3471 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3466 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3472 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3467 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3473 ],
3468 ],
3474 b'',
3469 b'',
3475 )
3470 )
3476 def debugserve(ui, repo, **opts):
3471 def debugserve(ui, repo, **opts):
3477 """run a server with advanced settings
3472 """run a server with advanced settings
3478
3473
3479 This command is similar to :hg:`serve`. It exists partially as a
3474 This command is similar to :hg:`serve`. It exists partially as a
3480 workaround to the fact that ``hg serve --stdio`` must have specific
3475 workaround to the fact that ``hg serve --stdio`` must have specific
3481 arguments for security reasons.
3476 arguments for security reasons.
3482 """
3477 """
3483 opts = pycompat.byteskwargs(opts)
3478 opts = pycompat.byteskwargs(opts)
3484
3479
3485 if not opts[b'sshstdio']:
3480 if not opts[b'sshstdio']:
3486 raise error.Abort(_(b'only --sshstdio is currently supported'))
3481 raise error.Abort(_(b'only --sshstdio is currently supported'))
3487
3482
3488 logfh = None
3483 logfh = None
3489
3484
3490 if opts[b'logiofd'] and opts[b'logiofile']:
3485 if opts[b'logiofd'] and opts[b'logiofile']:
3491 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3486 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3492
3487
3493 if opts[b'logiofd']:
3488 if opts[b'logiofd']:
3494 # Ideally we would be line buffered. But line buffering in binary
3489 # Ideally we would be line buffered. But line buffering in binary
3495 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3490 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3496 # buffering could have performance impacts. But since this isn't
3491 # buffering could have performance impacts. But since this isn't
3497 # performance critical code, it should be fine.
3492 # performance critical code, it should be fine.
3498 try:
3493 try:
3499 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3494 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3500 except OSError as e:
3495 except OSError as e:
3501 if e.errno != errno.ESPIPE:
3496 if e.errno != errno.ESPIPE:
3502 raise
3497 raise
3503 # can't seek a pipe, so `ab` mode fails on py3
3498 # can't seek a pipe, so `ab` mode fails on py3
3504 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3499 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3505 elif opts[b'logiofile']:
3500 elif opts[b'logiofile']:
3506 logfh = open(opts[b'logiofile'], b'ab', 0)
3501 logfh = open(opts[b'logiofile'], b'ab', 0)
3507
3502
3508 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3503 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3509 s.serve_forever()
3504 s.serve_forever()
3510
3505
3511
3506
3512 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3507 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3513 def debugsetparents(ui, repo, rev1, rev2=None):
3508 def debugsetparents(ui, repo, rev1, rev2=None):
3514 """manually set the parents of the current working directory (DANGEROUS)
3509 """manually set the parents of the current working directory (DANGEROUS)
3515
3510
3516 This command is not what you are looking for and should not be used. Using
3511 This command is not what you are looking for and should not be used. Using
3517 this command will most certainly results in slight corruption of the file
3512 this command will most certainly results in slight corruption of the file
3518 level histories withing your repository. DO NOT USE THIS COMMAND.
3513 level histories withing your repository. DO NOT USE THIS COMMAND.
3519
3514
3520 The command update the p1 and p2 field in the dirstate, and not touching
3515 The command update the p1 and p2 field in the dirstate, and not touching
3521 anything else. This useful for writing repository conversion tools, but
3516 anything else. This useful for writing repository conversion tools, but
3522 should be used with extreme care. For example, neither the working
3517 should be used with extreme care. For example, neither the working
3523 directory nor the dirstate is updated, so file status may be incorrect
3518 directory nor the dirstate is updated, so file status may be incorrect
3524 after running this command. Only used if you are one of the few people that
3519 after running this command. Only used if you are one of the few people that
3525 deeply unstand both conversion tools and file level histories. If you are
3520 deeply unstand both conversion tools and file level histories. If you are
3526 reading this help, you are not one of this people (most of them sailed west
3521 reading this help, you are not one of this people (most of them sailed west
3527 from Mithlond anyway.
3522 from Mithlond anyway.
3528
3523
3529 So one last time DO NOT USE THIS COMMAND.
3524 So one last time DO NOT USE THIS COMMAND.
3530
3525
3531 Returns 0 on success.
3526 Returns 0 on success.
3532 """
3527 """
3533
3528
3534 node1 = scmutil.revsingle(repo, rev1).node()
3529 node1 = scmutil.revsingle(repo, rev1).node()
3535 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3530 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3536
3531
3537 with repo.wlock():
3532 with repo.wlock():
3538 repo.setparents(node1, node2)
3533 repo.setparents(node1, node2)
3539
3534
3540
3535
3541 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3536 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3542 def debugsidedata(ui, repo, file_, rev=None, **opts):
3537 def debugsidedata(ui, repo, file_, rev=None, **opts):
3543 """dump the side data for a cl/manifest/file revision
3538 """dump the side data for a cl/manifest/file revision
3544
3539
3545 Use --verbose to dump the sidedata content."""
3540 Use --verbose to dump the sidedata content."""
3546 opts = pycompat.byteskwargs(opts)
3541 opts = pycompat.byteskwargs(opts)
3547 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3542 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3548 if rev is not None:
3543 if rev is not None:
3549 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3544 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3550 file_, rev = None, file_
3545 file_, rev = None, file_
3551 elif rev is None:
3546 elif rev is None:
3552 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3547 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3553 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3548 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3554 r = getattr(r, '_revlog', r)
3549 r = getattr(r, '_revlog', r)
3555 try:
3550 try:
3556 sidedata = r.sidedata(r.lookup(rev))
3551 sidedata = r.sidedata(r.lookup(rev))
3557 except KeyError:
3552 except KeyError:
3558 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3553 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3559 if sidedata:
3554 if sidedata:
3560 sidedata = list(sidedata.items())
3555 sidedata = list(sidedata.items())
3561 sidedata.sort()
3556 sidedata.sort()
3562 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3557 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3563 for key, value in sidedata:
3558 for key, value in sidedata:
3564 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3559 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3565 if ui.verbose:
3560 if ui.verbose:
3566 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3561 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3567
3562
3568
3563
3569 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3564 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3570 def debugssl(ui, repo, source=None, **opts):
3565 def debugssl(ui, repo, source=None, **opts):
3571 """test a secure connection to a server
3566 """test a secure connection to a server
3572
3567
3573 This builds the certificate chain for the server on Windows, installing the
3568 This builds the certificate chain for the server on Windows, installing the
3574 missing intermediates and trusted root via Windows Update if necessary. It
3569 missing intermediates and trusted root via Windows Update if necessary. It
3575 does nothing on other platforms.
3570 does nothing on other platforms.
3576
3571
3577 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3572 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3578 that server is used. See :hg:`help urls` for more information.
3573 that server is used. See :hg:`help urls` for more information.
3579
3574
3580 If the update succeeds, retry the original operation. Otherwise, the cause
3575 If the update succeeds, retry the original operation. Otherwise, the cause
3581 of the SSL error is likely another issue.
3576 of the SSL error is likely another issue.
3582 """
3577 """
3583 if not pycompat.iswindows:
3578 if not pycompat.iswindows:
3584 raise error.Abort(
3579 raise error.Abort(
3585 _(b'certificate chain building is only possible on Windows')
3580 _(b'certificate chain building is only possible on Windows')
3586 )
3581 )
3587
3582
3588 if not source:
3583 if not source:
3589 if not repo:
3584 if not repo:
3590 raise error.Abort(
3585 raise error.Abort(
3591 _(
3586 _(
3592 b"there is no Mercurial repository here, and no "
3587 b"there is no Mercurial repository here, and no "
3593 b"server specified"
3588 b"server specified"
3594 )
3589 )
3595 )
3590 )
3596 source = b"default"
3591 source = b"default"
3597
3592
3598 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3593 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3599 url = path.url
3594 url = path.url
3600
3595
3601 defaultport = {b'https': 443, b'ssh': 22}
3596 defaultport = {b'https': 443, b'ssh': 22}
3602 if url.scheme in defaultport:
3597 if url.scheme in defaultport:
3603 try:
3598 try:
3604 addr = (url.host, int(url.port or defaultport[url.scheme]))
3599 addr = (url.host, int(url.port or defaultport[url.scheme]))
3605 except ValueError:
3600 except ValueError:
3606 raise error.Abort(_(b"malformed port number in URL"))
3601 raise error.Abort(_(b"malformed port number in URL"))
3607 else:
3602 else:
3608 raise error.Abort(_(b"only https and ssh connections are supported"))
3603 raise error.Abort(_(b"only https and ssh connections are supported"))
3609
3604
3610 from . import win32
3605 from . import win32
3611
3606
3612 s = ssl.wrap_socket(
3607 s = ssl.wrap_socket(
3613 socket.socket(),
3608 socket.socket(),
3614 ssl_version=ssl.PROTOCOL_TLS,
3609 ssl_version=ssl.PROTOCOL_TLS,
3615 cert_reqs=ssl.CERT_NONE,
3610 cert_reqs=ssl.CERT_NONE,
3616 ca_certs=None,
3611 ca_certs=None,
3617 )
3612 )
3618
3613
3619 try:
3614 try:
3620 s.connect(addr)
3615 s.connect(addr)
3621 cert = s.getpeercert(True)
3616 cert = s.getpeercert(True)
3622
3617
3623 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3618 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3624
3619
3625 complete = win32.checkcertificatechain(cert, build=False)
3620 complete = win32.checkcertificatechain(cert, build=False)
3626
3621
3627 if not complete:
3622 if not complete:
3628 ui.status(_(b'certificate chain is incomplete, updating... '))
3623 ui.status(_(b'certificate chain is incomplete, updating... '))
3629
3624
3630 if not win32.checkcertificatechain(cert):
3625 if not win32.checkcertificatechain(cert):
3631 ui.status(_(b'failed.\n'))
3626 ui.status(_(b'failed.\n'))
3632 else:
3627 else:
3633 ui.status(_(b'done.\n'))
3628 ui.status(_(b'done.\n'))
3634 else:
3629 else:
3635 ui.status(_(b'full certificate chain is available\n'))
3630 ui.status(_(b'full certificate chain is available\n'))
3636 finally:
3631 finally:
3637 s.close()
3632 s.close()
3638
3633
3639
3634
3640 @command(
3635 @command(
3641 b"debugbackupbundle",
3636 b"debugbackupbundle",
3642 [
3637 [
3643 (
3638 (
3644 b"",
3639 b"",
3645 b"recover",
3640 b"recover",
3646 b"",
3641 b"",
3647 b"brings the specified changeset back into the repository",
3642 b"brings the specified changeset back into the repository",
3648 )
3643 )
3649 ]
3644 ]
3650 + cmdutil.logopts,
3645 + cmdutil.logopts,
3651 _(b"hg debugbackupbundle [--recover HASH]"),
3646 _(b"hg debugbackupbundle [--recover HASH]"),
3652 )
3647 )
3653 def debugbackupbundle(ui, repo, *pats, **opts):
3648 def debugbackupbundle(ui, repo, *pats, **opts):
3654 """lists the changesets available in backup bundles
3649 """lists the changesets available in backup bundles
3655
3650
3656 Without any arguments, this command prints a list of the changesets in each
3651 Without any arguments, this command prints a list of the changesets in each
3657 backup bundle.
3652 backup bundle.
3658
3653
3659 --recover takes a changeset hash and unbundles the first bundle that
3654 --recover takes a changeset hash and unbundles the first bundle that
3660 contains that hash, which puts that changeset back in your repository.
3655 contains that hash, which puts that changeset back in your repository.
3661
3656
3662 --verbose will print the entire commit message and the bundle path for that
3657 --verbose will print the entire commit message and the bundle path for that
3663 backup.
3658 backup.
3664 """
3659 """
3665 backups = list(
3660 backups = list(
3666 filter(
3661 filter(
3667 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3662 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3668 )
3663 )
3669 )
3664 )
3670 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3665 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3671
3666
3672 opts = pycompat.byteskwargs(opts)
3667 opts = pycompat.byteskwargs(opts)
3673 opts[b"bundle"] = b""
3668 opts[b"bundle"] = b""
3674 opts[b"force"] = None
3669 opts[b"force"] = None
3675 limit = logcmdutil.getlimit(opts)
3670 limit = logcmdutil.getlimit(opts)
3676
3671
3677 def display(other, chlist, displayer):
3672 def display(other, chlist, displayer):
3678 if opts.get(b"newest_first"):
3673 if opts.get(b"newest_first"):
3679 chlist.reverse()
3674 chlist.reverse()
3680 count = 0
3675 count = 0
3681 for n in chlist:
3676 for n in chlist:
3682 if limit is not None and count >= limit:
3677 if limit is not None and count >= limit:
3683 break
3678 break
3684 parents = [
3679 parents = [
3685 True for p in other.changelog.parents(n) if p != repo.nullid
3680 True for p in other.changelog.parents(n) if p != repo.nullid
3686 ]
3681 ]
3687 if opts.get(b"no_merges") and len(parents) == 2:
3682 if opts.get(b"no_merges") and len(parents) == 2:
3688 continue
3683 continue
3689 count += 1
3684 count += 1
3690 displayer.show(other[n])
3685 displayer.show(other[n])
3691
3686
3692 recovernode = opts.get(b"recover")
3687 recovernode = opts.get(b"recover")
3693 if recovernode:
3688 if recovernode:
3694 if scmutil.isrevsymbol(repo, recovernode):
3689 if scmutil.isrevsymbol(repo, recovernode):
3695 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3690 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3696 return
3691 return
3697 elif backups:
3692 elif backups:
3698 msg = _(
3693 msg = _(
3699 b"Recover changesets using: hg debugbackupbundle --recover "
3694 b"Recover changesets using: hg debugbackupbundle --recover "
3700 b"<changeset hash>\n\nAvailable backup changesets:"
3695 b"<changeset hash>\n\nAvailable backup changesets:"
3701 )
3696 )
3702 ui.status(msg, label=b"status.removed")
3697 ui.status(msg, label=b"status.removed")
3703 else:
3698 else:
3704 ui.status(_(b"no backup changesets found\n"))
3699 ui.status(_(b"no backup changesets found\n"))
3705 return
3700 return
3706
3701
3707 for backup in backups:
3702 for backup in backups:
3708 # Much of this is copied from the hg incoming logic
3703 # Much of this is copied from the hg incoming logic
3709 source = os.path.relpath(backup, encoding.getcwd())
3704 source = os.path.relpath(backup, encoding.getcwd())
3710 path = urlutil.get_unique_pull_path_obj(
3705 path = urlutil.get_unique_pull_path_obj(
3711 b'debugbackupbundle',
3706 b'debugbackupbundle',
3712 ui,
3707 ui,
3713 source,
3708 source,
3714 )
3709 )
3715 try:
3710 try:
3716 other = hg.peer(repo, opts, path)
3711 other = hg.peer(repo, opts, path)
3717 except error.LookupError as ex:
3712 except error.LookupError as ex:
3718 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3713 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3719 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3714 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3720 ui.warn(msg, hint=hint)
3715 ui.warn(msg, hint=hint)
3721 continue
3716 continue
3722 branches = (path.branch, opts.get(b'branch', []))
3717 branches = (path.branch, opts.get(b'branch', []))
3723 revs, checkout = hg.addbranchrevs(
3718 revs, checkout = hg.addbranchrevs(
3724 repo, other, branches, opts.get(b"rev")
3719 repo, other, branches, opts.get(b"rev")
3725 )
3720 )
3726
3721
3727 if revs:
3722 if revs:
3728 revs = [other.lookup(rev) for rev in revs]
3723 revs = [other.lookup(rev) for rev in revs]
3729
3724
3730 with ui.silent():
3725 with ui.silent():
3731 try:
3726 try:
3732 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3727 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3733 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3728 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3734 )
3729 )
3735 except error.LookupError:
3730 except error.LookupError:
3736 continue
3731 continue
3737
3732
3738 try:
3733 try:
3739 if not chlist:
3734 if not chlist:
3740 continue
3735 continue
3741 if recovernode:
3736 if recovernode:
3742 with repo.lock(), repo.transaction(b"unbundle") as tr:
3737 with repo.lock(), repo.transaction(b"unbundle") as tr:
3743 if scmutil.isrevsymbol(other, recovernode):
3738 if scmutil.isrevsymbol(other, recovernode):
3744 ui.status(_(b"Unbundling %s\n") % (recovernode))
3739 ui.status(_(b"Unbundling %s\n") % (recovernode))
3745 f = hg.openpath(ui, path.loc)
3740 f = hg.openpath(ui, path.loc)
3746 gen = exchange.readbundle(ui, f, path.loc)
3741 gen = exchange.readbundle(ui, f, path.loc)
3747 if isinstance(gen, bundle2.unbundle20):
3742 if isinstance(gen, bundle2.unbundle20):
3748 bundle2.applybundle(
3743 bundle2.applybundle(
3749 repo,
3744 repo,
3750 gen,
3745 gen,
3751 tr,
3746 tr,
3752 source=b"unbundle",
3747 source=b"unbundle",
3753 url=b"bundle:" + path.loc,
3748 url=b"bundle:" + path.loc,
3754 )
3749 )
3755 else:
3750 else:
3756 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3751 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3757 break
3752 break
3758 else:
3753 else:
3759 backupdate = encoding.strtolocal(
3754 backupdate = encoding.strtolocal(
3760 time.strftime(
3755 time.strftime(
3761 "%a %H:%M, %Y-%m-%d",
3756 "%a %H:%M, %Y-%m-%d",
3762 time.localtime(os.path.getmtime(path.loc)),
3757 time.localtime(os.path.getmtime(path.loc)),
3763 )
3758 )
3764 )
3759 )
3765 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3760 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3766 if ui.verbose:
3761 if ui.verbose:
3767 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3762 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3768 else:
3763 else:
3769 opts[
3764 opts[
3770 b"template"
3765 b"template"
3771 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3766 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3772 displayer = logcmdutil.changesetdisplayer(
3767 displayer = logcmdutil.changesetdisplayer(
3773 ui, other, opts, False
3768 ui, other, opts, False
3774 )
3769 )
3775 display(other, chlist, displayer)
3770 display(other, chlist, displayer)
3776 displayer.close()
3771 displayer.close()
3777 finally:
3772 finally:
3778 cleanupfn()
3773 cleanupfn()
3779
3774
3780
3775
3781 @command(
3776 @command(
3782 b'debugsub',
3777 b'debugsub',
3783 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3778 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3784 _(b'[-r REV] [REV]'),
3779 _(b'[-r REV] [REV]'),
3785 )
3780 )
3786 def debugsub(ui, repo, rev=None):
3781 def debugsub(ui, repo, rev=None):
3787 ctx = scmutil.revsingle(repo, rev, None)
3782 ctx = scmutil.revsingle(repo, rev, None)
3788 for k, v in sorted(ctx.substate.items()):
3783 for k, v in sorted(ctx.substate.items()):
3789 ui.writenoi18n(b'path %s\n' % k)
3784 ui.writenoi18n(b'path %s\n' % k)
3790 ui.writenoi18n(b' source %s\n' % v[0])
3785 ui.writenoi18n(b' source %s\n' % v[0])
3791 ui.writenoi18n(b' revision %s\n' % v[1])
3786 ui.writenoi18n(b' revision %s\n' % v[1])
3792
3787
3793
3788
3794 @command(b'debugshell', optionalrepo=True)
3789 @command(b'debugshell', optionalrepo=True)
3795 def debugshell(ui, repo):
3790 def debugshell(ui, repo):
3796 """run an interactive Python interpreter
3791 """run an interactive Python interpreter
3797
3792
3798 The local namespace is provided with a reference to the ui and
3793 The local namespace is provided with a reference to the ui and
3799 the repo instance (if available).
3794 the repo instance (if available).
3800 """
3795 """
3801 import code
3796 import code
3802
3797
3803 imported_objects = {
3798 imported_objects = {
3804 'ui': ui,
3799 'ui': ui,
3805 'repo': repo,
3800 'repo': repo,
3806 }
3801 }
3807
3802
3808 code.interact(local=imported_objects)
3803 code.interact(local=imported_objects)
3809
3804
3810
3805
3811 @command(
3806 @command(
3812 b'debug-revlog-stats',
3807 b'debug-revlog-stats',
3813 [
3808 [
3814 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3809 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3815 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3810 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3816 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3811 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3817 ]
3812 ]
3818 + cmdutil.formatteropts,
3813 + cmdutil.formatteropts,
3819 )
3814 )
3820 def debug_revlog_stats(ui, repo, **opts):
3815 def debug_revlog_stats(ui, repo, **opts):
3821 """display statistics about revlogs in the store"""
3816 """display statistics about revlogs in the store"""
3822 opts = pycompat.byteskwargs(opts)
3817 opts = pycompat.byteskwargs(opts)
3823 changelog = opts[b"changelog"]
3818 changelog = opts[b"changelog"]
3824 manifest = opts[b"manifest"]
3819 manifest = opts[b"manifest"]
3825 filelogs = opts[b"filelogs"]
3820 filelogs = opts[b"filelogs"]
3826
3821
3827 if changelog is None and manifest is None and filelogs is None:
3822 if changelog is None and manifest is None and filelogs is None:
3828 changelog = True
3823 changelog = True
3829 manifest = True
3824 manifest = True
3830 filelogs = True
3825 filelogs = True
3831
3826
3832 repo = repo.unfiltered()
3827 repo = repo.unfiltered()
3833 fm = ui.formatter(b'debug-revlog-stats', opts)
3828 fm = ui.formatter(b'debug-revlog-stats', opts)
3834 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3829 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3835 fm.end()
3830 fm.end()
3836
3831
3837
3832
3838 @command(
3833 @command(
3839 b'debugsuccessorssets',
3834 b'debugsuccessorssets',
3840 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3835 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3841 _(b'[REV]'),
3836 _(b'[REV]'),
3842 )
3837 )
3843 def debugsuccessorssets(ui, repo, *revs, **opts):
3838 def debugsuccessorssets(ui, repo, *revs, **opts):
3844 """show set of successors for revision
3839 """show set of successors for revision
3845
3840
3846 A successors set of changeset A is a consistent group of revisions that
3841 A successors set of changeset A is a consistent group of revisions that
3847 succeed A. It contains non-obsolete changesets only unless closests
3842 succeed A. It contains non-obsolete changesets only unless closests
3848 successors set is set.
3843 successors set is set.
3849
3844
3850 In most cases a changeset A has a single successors set containing a single
3845 In most cases a changeset A has a single successors set containing a single
3851 successor (changeset A replaced by A').
3846 successor (changeset A replaced by A').
3852
3847
3853 A changeset that is made obsolete with no successors are called "pruned".
3848 A changeset that is made obsolete with no successors are called "pruned".
3854 Such changesets have no successors sets at all.
3849 Such changesets have no successors sets at all.
3855
3850
3856 A changeset that has been "split" will have a successors set containing
3851 A changeset that has been "split" will have a successors set containing
3857 more than one successor.
3852 more than one successor.
3858
3853
3859 A changeset that has been rewritten in multiple different ways is called
3854 A changeset that has been rewritten in multiple different ways is called
3860 "divergent". Such changesets have multiple successor sets (each of which
3855 "divergent". Such changesets have multiple successor sets (each of which
3861 may also be split, i.e. have multiple successors).
3856 may also be split, i.e. have multiple successors).
3862
3857
3863 Results are displayed as follows::
3858 Results are displayed as follows::
3864
3859
3865 <rev1>
3860 <rev1>
3866 <successors-1A>
3861 <successors-1A>
3867 <rev2>
3862 <rev2>
3868 <successors-2A>
3863 <successors-2A>
3869 <successors-2B1> <successors-2B2> <successors-2B3>
3864 <successors-2B1> <successors-2B2> <successors-2B3>
3870
3865
3871 Here rev2 has two possible (i.e. divergent) successors sets. The first
3866 Here rev2 has two possible (i.e. divergent) successors sets. The first
3872 holds one element, whereas the second holds three (i.e. the changeset has
3867 holds one element, whereas the second holds three (i.e. the changeset has
3873 been split).
3868 been split).
3874 """
3869 """
3875 # passed to successorssets caching computation from one call to another
3870 # passed to successorssets caching computation from one call to another
3876 cache = {}
3871 cache = {}
3877 ctx2str = bytes
3872 ctx2str = bytes
3878 node2str = short
3873 node2str = short
3879 for rev in logcmdutil.revrange(repo, revs):
3874 for rev in logcmdutil.revrange(repo, revs):
3880 ctx = repo[rev]
3875 ctx = repo[rev]
3881 ui.write(b'%s\n' % ctx2str(ctx))
3876 ui.write(b'%s\n' % ctx2str(ctx))
3882 for succsset in obsutil.successorssets(
3877 for succsset in obsutil.successorssets(
3883 repo, ctx.node(), closest=opts['closest'], cache=cache
3878 repo, ctx.node(), closest=opts['closest'], cache=cache
3884 ):
3879 ):
3885 if succsset:
3880 if succsset:
3886 ui.write(b' ')
3881 ui.write(b' ')
3887 ui.write(node2str(succsset[0]))
3882 ui.write(node2str(succsset[0]))
3888 for node in succsset[1:]:
3883 for node in succsset[1:]:
3889 ui.write(b' ')
3884 ui.write(b' ')
3890 ui.write(node2str(node))
3885 ui.write(node2str(node))
3891 ui.write(b'\n')
3886 ui.write(b'\n')
3892
3887
3893
3888
3894 @command(b'debugtagscache', [])
3889 @command(b'debugtagscache', [])
3895 def debugtagscache(ui, repo):
3890 def debugtagscache(ui, repo):
3896 """display the contents of .hg/cache/hgtagsfnodes1"""
3891 """display the contents of .hg/cache/hgtagsfnodes1"""
3897 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3892 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3898 flog = repo.file(b'.hgtags')
3893 flog = repo.file(b'.hgtags')
3899 for r in repo:
3894 for r in repo:
3900 node = repo[r].node()
3895 node = repo[r].node()
3901 tagsnode = cache.getfnode(node, computemissing=False)
3896 tagsnode = cache.getfnode(node, computemissing=False)
3902 if tagsnode:
3897 if tagsnode:
3903 tagsnodedisplay = hex(tagsnode)
3898 tagsnodedisplay = hex(tagsnode)
3904 if not flog.hasnode(tagsnode):
3899 if not flog.hasnode(tagsnode):
3905 tagsnodedisplay += b' (unknown node)'
3900 tagsnodedisplay += b' (unknown node)'
3906 elif tagsnode is None:
3901 elif tagsnode is None:
3907 tagsnodedisplay = b'missing'
3902 tagsnodedisplay = b'missing'
3908 else:
3903 else:
3909 tagsnodedisplay = b'invalid'
3904 tagsnodedisplay = b'invalid'
3910
3905
3911 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3906 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3912
3907
3913
3908
3914 @command(
3909 @command(
3915 b'debugtemplate',
3910 b'debugtemplate',
3916 [
3911 [
3917 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3912 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3918 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3913 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3919 ],
3914 ],
3920 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3915 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3921 optionalrepo=True,
3916 optionalrepo=True,
3922 )
3917 )
3923 def debugtemplate(ui, repo, tmpl, **opts):
3918 def debugtemplate(ui, repo, tmpl, **opts):
3924 """parse and apply a template
3919 """parse and apply a template
3925
3920
3926 If -r/--rev is given, the template is processed as a log template and
3921 If -r/--rev is given, the template is processed as a log template and
3927 applied to the given changesets. Otherwise, it is processed as a generic
3922 applied to the given changesets. Otherwise, it is processed as a generic
3928 template.
3923 template.
3929
3924
3930 Use --verbose to print the parsed tree.
3925 Use --verbose to print the parsed tree.
3931 """
3926 """
3932 revs = None
3927 revs = None
3933 if opts['rev']:
3928 if opts['rev']:
3934 if repo is None:
3929 if repo is None:
3935 raise error.RepoError(
3930 raise error.RepoError(
3936 _(b'there is no Mercurial repository here (.hg not found)')
3931 _(b'there is no Mercurial repository here (.hg not found)')
3937 )
3932 )
3938 revs = logcmdutil.revrange(repo, opts['rev'])
3933 revs = logcmdutil.revrange(repo, opts['rev'])
3939
3934
3940 props = {}
3935 props = {}
3941 for d in opts['define']:
3936 for d in opts['define']:
3942 try:
3937 try:
3943 k, v = (e.strip() for e in d.split(b'=', 1))
3938 k, v = (e.strip() for e in d.split(b'=', 1))
3944 if not k or k == b'ui':
3939 if not k or k == b'ui':
3945 raise ValueError
3940 raise ValueError
3946 props[k] = v
3941 props[k] = v
3947 except ValueError:
3942 except ValueError:
3948 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3943 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3949
3944
3950 if ui.verbose:
3945 if ui.verbose:
3951 aliases = ui.configitems(b'templatealias')
3946 aliases = ui.configitems(b'templatealias')
3952 tree = templater.parse(tmpl)
3947 tree = templater.parse(tmpl)
3953 ui.note(templater.prettyformat(tree), b'\n')
3948 ui.note(templater.prettyformat(tree), b'\n')
3954 newtree = templater.expandaliases(tree, aliases)
3949 newtree = templater.expandaliases(tree, aliases)
3955 if newtree != tree:
3950 if newtree != tree:
3956 ui.notenoi18n(
3951 ui.notenoi18n(
3957 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3952 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3958 )
3953 )
3959
3954
3960 if revs is None:
3955 if revs is None:
3961 tres = formatter.templateresources(ui, repo)
3956 tres = formatter.templateresources(ui, repo)
3962 t = formatter.maketemplater(ui, tmpl, resources=tres)
3957 t = formatter.maketemplater(ui, tmpl, resources=tres)
3963 if ui.verbose:
3958 if ui.verbose:
3964 kwds, funcs = t.symbolsuseddefault()
3959 kwds, funcs = t.symbolsuseddefault()
3965 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3960 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3966 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3961 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3967 ui.write(t.renderdefault(props))
3962 ui.write(t.renderdefault(props))
3968 else:
3963 else:
3969 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3964 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3970 if ui.verbose:
3965 if ui.verbose:
3971 kwds, funcs = displayer.t.symbolsuseddefault()
3966 kwds, funcs = displayer.t.symbolsuseddefault()
3972 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3967 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3973 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3968 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3974 for r in revs:
3969 for r in revs:
3975 displayer.show(repo[r], **pycompat.strkwargs(props))
3970 displayer.show(repo[r], **pycompat.strkwargs(props))
3976 displayer.close()
3971 displayer.close()
3977
3972
3978
3973
3979 @command(
3974 @command(
3980 b'debuguigetpass',
3975 b'debuguigetpass',
3981 [
3976 [
3982 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3977 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3983 ],
3978 ],
3984 _(b'[-p TEXT]'),
3979 _(b'[-p TEXT]'),
3985 norepo=True,
3980 norepo=True,
3986 )
3981 )
3987 def debuguigetpass(ui, prompt=b''):
3982 def debuguigetpass(ui, prompt=b''):
3988 """show prompt to type password"""
3983 """show prompt to type password"""
3989 r = ui.getpass(prompt)
3984 r = ui.getpass(prompt)
3990 if r is None:
3985 if r is None:
3991 r = b"<default response>"
3986 r = b"<default response>"
3992 ui.writenoi18n(b'response: %s\n' % r)
3987 ui.writenoi18n(b'response: %s\n' % r)
3993
3988
3994
3989
3995 @command(
3990 @command(
3996 b'debuguiprompt',
3991 b'debuguiprompt',
3997 [
3992 [
3998 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3993 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3999 ],
3994 ],
4000 _(b'[-p TEXT]'),
3995 _(b'[-p TEXT]'),
4001 norepo=True,
3996 norepo=True,
4002 )
3997 )
4003 def debuguiprompt(ui, prompt=b''):
3998 def debuguiprompt(ui, prompt=b''):
4004 """show plain prompt"""
3999 """show plain prompt"""
4005 r = ui.prompt(prompt)
4000 r = ui.prompt(prompt)
4006 ui.writenoi18n(b'response: %s\n' % r)
4001 ui.writenoi18n(b'response: %s\n' % r)
4007
4002
4008
4003
4009 @command(b'debugupdatecaches', [])
4004 @command(b'debugupdatecaches', [])
4010 def debugupdatecaches(ui, repo, *pats, **opts):
4005 def debugupdatecaches(ui, repo, *pats, **opts):
4011 """warm all known caches in the repository"""
4006 """warm all known caches in the repository"""
4012 with repo.wlock(), repo.lock():
4007 with repo.wlock(), repo.lock():
4013 repo.updatecaches(caches=repository.CACHES_ALL)
4008 repo.updatecaches(caches=repository.CACHES_ALL)
4014
4009
4015
4010
4016 @command(
4011 @command(
4017 b'debugupgraderepo',
4012 b'debugupgraderepo',
4018 [
4013 [
4019 (
4014 (
4020 b'o',
4015 b'o',
4021 b'optimize',
4016 b'optimize',
4022 [],
4017 [],
4023 _(b'extra optimization to perform'),
4018 _(b'extra optimization to perform'),
4024 _(b'NAME'),
4019 _(b'NAME'),
4025 ),
4020 ),
4026 (b'', b'run', False, _(b'performs an upgrade')),
4021 (b'', b'run', False, _(b'performs an upgrade')),
4027 (b'', b'backup', True, _(b'keep the old repository content around')),
4022 (b'', b'backup', True, _(b'keep the old repository content around')),
4028 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4023 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4029 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4024 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4030 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4025 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4031 ],
4026 ],
4032 )
4027 )
4033 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4028 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4034 """upgrade a repository to use different features
4029 """upgrade a repository to use different features
4035
4030
4036 If no arguments are specified, the repository is evaluated for upgrade
4031 If no arguments are specified, the repository is evaluated for upgrade
4037 and a list of problems and potential optimizations is printed.
4032 and a list of problems and potential optimizations is printed.
4038
4033
4039 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4034 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4040 can be influenced via additional arguments. More details will be provided
4035 can be influenced via additional arguments. More details will be provided
4041 by the command output when run without ``--run``.
4036 by the command output when run without ``--run``.
4042
4037
4043 During the upgrade, the repository will be locked and no writes will be
4038 During the upgrade, the repository will be locked and no writes will be
4044 allowed.
4039 allowed.
4045
4040
4046 At the end of the upgrade, the repository may not be readable while new
4041 At the end of the upgrade, the repository may not be readable while new
4047 repository data is swapped in. This window will be as long as it takes to
4042 repository data is swapped in. This window will be as long as it takes to
4048 rename some directories inside the ``.hg`` directory. On most machines, this
4043 rename some directories inside the ``.hg`` directory. On most machines, this
4049 should complete almost instantaneously and the chances of a consumer being
4044 should complete almost instantaneously and the chances of a consumer being
4050 unable to access the repository should be low.
4045 unable to access the repository should be low.
4051
4046
4052 By default, all revlogs will be upgraded. You can restrict this using flags
4047 By default, all revlogs will be upgraded. You can restrict this using flags
4053 such as `--manifest`:
4048 such as `--manifest`:
4054
4049
4055 * `--manifest`: only optimize the manifest
4050 * `--manifest`: only optimize the manifest
4056 * `--no-manifest`: optimize all revlog but the manifest
4051 * `--no-manifest`: optimize all revlog but the manifest
4057 * `--changelog`: optimize the changelog only
4052 * `--changelog`: optimize the changelog only
4058 * `--no-changelog --no-manifest`: optimize filelogs only
4053 * `--no-changelog --no-manifest`: optimize filelogs only
4059 * `--filelogs`: optimize the filelogs only
4054 * `--filelogs`: optimize the filelogs only
4060 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4055 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4061 """
4056 """
4062 return upgrade.upgraderepo(
4057 return upgrade.upgraderepo(
4063 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4058 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4064 )
4059 )
4065
4060
4066
4061
4067 @command(
4062 @command(
4068 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4063 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4069 )
4064 )
4070 def debugwalk(ui, repo, *pats, **opts):
4065 def debugwalk(ui, repo, *pats, **opts):
4071 """show how files match on given patterns"""
4066 """show how files match on given patterns"""
4072 opts = pycompat.byteskwargs(opts)
4067 opts = pycompat.byteskwargs(opts)
4073 m = scmutil.match(repo[None], pats, opts)
4068 m = scmutil.match(repo[None], pats, opts)
4074 if ui.verbose:
4069 if ui.verbose:
4075 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4070 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4076 items = list(repo[None].walk(m))
4071 items = list(repo[None].walk(m))
4077 if not items:
4072 if not items:
4078 return
4073 return
4079 f = lambda fn: fn
4074 f = lambda fn: fn
4080 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4075 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4081 f = lambda fn: util.normpath(fn)
4076 f = lambda fn: util.normpath(fn)
4082 fmt = b'f %%-%ds %%-%ds %%s' % (
4077 fmt = b'f %%-%ds %%-%ds %%s' % (
4083 max([len(abs) for abs in items]),
4078 max([len(abs) for abs in items]),
4084 max([len(repo.pathto(abs)) for abs in items]),
4079 max([len(repo.pathto(abs)) for abs in items]),
4085 )
4080 )
4086 for abs in items:
4081 for abs in items:
4087 line = fmt % (
4082 line = fmt % (
4088 abs,
4083 abs,
4089 f(repo.pathto(abs)),
4084 f(repo.pathto(abs)),
4090 m.exact(abs) and b'exact' or b'',
4085 m.exact(abs) and b'exact' or b'',
4091 )
4086 )
4092 ui.write(b"%s\n" % line.rstrip())
4087 ui.write(b"%s\n" % line.rstrip())
4093
4088
4094
4089
4095 @command(b'debugwhyunstable', [], _(b'REV'))
4090 @command(b'debugwhyunstable', [], _(b'REV'))
4096 def debugwhyunstable(ui, repo, rev):
4091 def debugwhyunstable(ui, repo, rev):
4097 """explain instabilities of a changeset"""
4092 """explain instabilities of a changeset"""
4098 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4093 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4099 dnodes = b''
4094 dnodes = b''
4100 if entry.get(b'divergentnodes'):
4095 if entry.get(b'divergentnodes'):
4101 dnodes = (
4096 dnodes = (
4102 b' '.join(
4097 b' '.join(
4103 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4098 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4104 for ctx in entry[b'divergentnodes']
4099 for ctx in entry[b'divergentnodes']
4105 )
4100 )
4106 + b' '
4101 + b' '
4107 )
4102 )
4108 ui.write(
4103 ui.write(
4109 b'%s: %s%s %s\n'
4104 b'%s: %s%s %s\n'
4110 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4105 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4111 )
4106 )
4112
4107
4113
4108
4114 @command(
4109 @command(
4115 b'debugwireargs',
4110 b'debugwireargs',
4116 [
4111 [
4117 (b'', b'three', b'', b'three'),
4112 (b'', b'three', b'', b'three'),
4118 (b'', b'four', b'', b'four'),
4113 (b'', b'four', b'', b'four'),
4119 (b'', b'five', b'', b'five'),
4114 (b'', b'five', b'', b'five'),
4120 ]
4115 ]
4121 + cmdutil.remoteopts,
4116 + cmdutil.remoteopts,
4122 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4117 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4123 norepo=True,
4118 norepo=True,
4124 )
4119 )
4125 def debugwireargs(ui, repopath, *vals, **opts):
4120 def debugwireargs(ui, repopath, *vals, **opts):
4126 opts = pycompat.byteskwargs(opts)
4121 opts = pycompat.byteskwargs(opts)
4127 repo = hg.peer(ui, opts, repopath)
4122 repo = hg.peer(ui, opts, repopath)
4128 try:
4123 try:
4129 for opt in cmdutil.remoteopts:
4124 for opt in cmdutil.remoteopts:
4130 del opts[opt[1]]
4125 del opts[opt[1]]
4131 args = {}
4126 args = {}
4132 for k, v in opts.items():
4127 for k, v in opts.items():
4133 if v:
4128 if v:
4134 args[k] = v
4129 args[k] = v
4135 args = pycompat.strkwargs(args)
4130 args = pycompat.strkwargs(args)
4136 # run twice to check that we don't mess up the stream for the next command
4131 # run twice to check that we don't mess up the stream for the next command
4137 res1 = repo.debugwireargs(*vals, **args)
4132 res1 = repo.debugwireargs(*vals, **args)
4138 res2 = repo.debugwireargs(*vals, **args)
4133 res2 = repo.debugwireargs(*vals, **args)
4139 ui.write(b"%s\n" % res1)
4134 ui.write(b"%s\n" % res1)
4140 if res1 != res2:
4135 if res1 != res2:
4141 ui.warn(b"%s\n" % res2)
4136 ui.warn(b"%s\n" % res2)
4142 finally:
4137 finally:
4143 repo.close()
4138 repo.close()
4144
4139
4145
4140
4146 def _parsewirelangblocks(fh):
4141 def _parsewirelangblocks(fh):
4147 activeaction = None
4142 activeaction = None
4148 blocklines = []
4143 blocklines = []
4149 lastindent = 0
4144 lastindent = 0
4150
4145
4151 for line in fh:
4146 for line in fh:
4152 line = line.rstrip()
4147 line = line.rstrip()
4153 if not line:
4148 if not line:
4154 continue
4149 continue
4155
4150
4156 if line.startswith(b'#'):
4151 if line.startswith(b'#'):
4157 continue
4152 continue
4158
4153
4159 if not line.startswith(b' '):
4154 if not line.startswith(b' '):
4160 # New block. Flush previous one.
4155 # New block. Flush previous one.
4161 if activeaction:
4156 if activeaction:
4162 yield activeaction, blocklines
4157 yield activeaction, blocklines
4163
4158
4164 activeaction = line
4159 activeaction = line
4165 blocklines = []
4160 blocklines = []
4166 lastindent = 0
4161 lastindent = 0
4167 continue
4162 continue
4168
4163
4169 # Else we start with an indent.
4164 # Else we start with an indent.
4170
4165
4171 if not activeaction:
4166 if not activeaction:
4172 raise error.Abort(_(b'indented line outside of block'))
4167 raise error.Abort(_(b'indented line outside of block'))
4173
4168
4174 indent = len(line) - len(line.lstrip())
4169 indent = len(line) - len(line.lstrip())
4175
4170
4176 # If this line is indented more than the last line, concatenate it.
4171 # If this line is indented more than the last line, concatenate it.
4177 if indent > lastindent and blocklines:
4172 if indent > lastindent and blocklines:
4178 blocklines[-1] += line.lstrip()
4173 blocklines[-1] += line.lstrip()
4179 else:
4174 else:
4180 blocklines.append(line)
4175 blocklines.append(line)
4181 lastindent = indent
4176 lastindent = indent
4182
4177
4183 # Flush last block.
4178 # Flush last block.
4184 if activeaction:
4179 if activeaction:
4185 yield activeaction, blocklines
4180 yield activeaction, blocklines
4186
4181
4187
4182
4188 @command(
4183 @command(
4189 b'debugwireproto',
4184 b'debugwireproto',
4190 [
4185 [
4191 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4186 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4192 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4187 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4193 (
4188 (
4194 b'',
4189 b'',
4195 b'noreadstderr',
4190 b'noreadstderr',
4196 False,
4191 False,
4197 _(b'do not read from stderr of the remote'),
4192 _(b'do not read from stderr of the remote'),
4198 ),
4193 ),
4199 (
4194 (
4200 b'',
4195 b'',
4201 b'nologhandshake',
4196 b'nologhandshake',
4202 False,
4197 False,
4203 _(b'do not log I/O related to the peer handshake'),
4198 _(b'do not log I/O related to the peer handshake'),
4204 ),
4199 ),
4205 ]
4200 ]
4206 + cmdutil.remoteopts,
4201 + cmdutil.remoteopts,
4207 _(b'[PATH]'),
4202 _(b'[PATH]'),
4208 optionalrepo=True,
4203 optionalrepo=True,
4209 )
4204 )
4210 def debugwireproto(ui, repo, path=None, **opts):
4205 def debugwireproto(ui, repo, path=None, **opts):
4211 """send wire protocol commands to a server
4206 """send wire protocol commands to a server
4212
4207
4213 This command can be used to issue wire protocol commands to remote
4208 This command can be used to issue wire protocol commands to remote
4214 peers and to debug the raw data being exchanged.
4209 peers and to debug the raw data being exchanged.
4215
4210
4216 ``--localssh`` will start an SSH server against the current repository
4211 ``--localssh`` will start an SSH server against the current repository
4217 and connect to that. By default, the connection will perform a handshake
4212 and connect to that. By default, the connection will perform a handshake
4218 and establish an appropriate peer instance.
4213 and establish an appropriate peer instance.
4219
4214
4220 ``--peer`` can be used to bypass the handshake protocol and construct a
4215 ``--peer`` can be used to bypass the handshake protocol and construct a
4221 peer instance using the specified class type. Valid values are ``raw``,
4216 peer instance using the specified class type. Valid values are ``raw``,
4222 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4217 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4223 don't support higher-level command actions.
4218 don't support higher-level command actions.
4224
4219
4225 ``--noreadstderr`` can be used to disable automatic reading from stderr
4220 ``--noreadstderr`` can be used to disable automatic reading from stderr
4226 of the peer (for SSH connections only). Disabling automatic reading of
4221 of the peer (for SSH connections only). Disabling automatic reading of
4227 stderr is useful for making output more deterministic.
4222 stderr is useful for making output more deterministic.
4228
4223
4229 Commands are issued via a mini language which is specified via stdin.
4224 Commands are issued via a mini language which is specified via stdin.
4230 The language consists of individual actions to perform. An action is
4225 The language consists of individual actions to perform. An action is
4231 defined by a block. A block is defined as a line with no leading
4226 defined by a block. A block is defined as a line with no leading
4232 space followed by 0 or more lines with leading space. Blocks are
4227 space followed by 0 or more lines with leading space. Blocks are
4233 effectively a high-level command with additional metadata.
4228 effectively a high-level command with additional metadata.
4234
4229
4235 Lines beginning with ``#`` are ignored.
4230 Lines beginning with ``#`` are ignored.
4236
4231
4237 The following sections denote available actions.
4232 The following sections denote available actions.
4238
4233
4239 raw
4234 raw
4240 ---
4235 ---
4241
4236
4242 Send raw data to the server.
4237 Send raw data to the server.
4243
4238
4244 The block payload contains the raw data to send as one atomic send
4239 The block payload contains the raw data to send as one atomic send
4245 operation. The data may not actually be delivered in a single system
4240 operation. The data may not actually be delivered in a single system
4246 call: it depends on the abilities of the transport being used.
4241 call: it depends on the abilities of the transport being used.
4247
4242
4248 Each line in the block is de-indented and concatenated. Then, that
4243 Each line in the block is de-indented and concatenated. Then, that
4249 value is evaluated as a Python b'' literal. This allows the use of
4244 value is evaluated as a Python b'' literal. This allows the use of
4250 backslash escaping, etc.
4245 backslash escaping, etc.
4251
4246
4252 raw+
4247 raw+
4253 ----
4248 ----
4254
4249
4255 Behaves like ``raw`` except flushes output afterwards.
4250 Behaves like ``raw`` except flushes output afterwards.
4256
4251
4257 command <X>
4252 command <X>
4258 -----------
4253 -----------
4259
4254
4260 Send a request to run a named command, whose name follows the ``command``
4255 Send a request to run a named command, whose name follows the ``command``
4261 string.
4256 string.
4262
4257
4263 Arguments to the command are defined as lines in this block. The format of
4258 Arguments to the command are defined as lines in this block. The format of
4264 each line is ``<key> <value>``. e.g.::
4259 each line is ``<key> <value>``. e.g.::
4265
4260
4266 command listkeys
4261 command listkeys
4267 namespace bookmarks
4262 namespace bookmarks
4268
4263
4269 If the value begins with ``eval:``, it will be interpreted as a Python
4264 If the value begins with ``eval:``, it will be interpreted as a Python
4270 literal expression. Otherwise values are interpreted as Python b'' literals.
4265 literal expression. Otherwise values are interpreted as Python b'' literals.
4271 This allows sending complex types and encoding special byte sequences via
4266 This allows sending complex types and encoding special byte sequences via
4272 backslash escaping.
4267 backslash escaping.
4273
4268
4274 The following arguments have special meaning:
4269 The following arguments have special meaning:
4275
4270
4276 ``PUSHFILE``
4271 ``PUSHFILE``
4277 When defined, the *push* mechanism of the peer will be used instead
4272 When defined, the *push* mechanism of the peer will be used instead
4278 of the static request-response mechanism and the content of the
4273 of the static request-response mechanism and the content of the
4279 file specified in the value of this argument will be sent as the
4274 file specified in the value of this argument will be sent as the
4280 command payload.
4275 command payload.
4281
4276
4282 This can be used to submit a local bundle file to the remote.
4277 This can be used to submit a local bundle file to the remote.
4283
4278
4284 batchbegin
4279 batchbegin
4285 ----------
4280 ----------
4286
4281
4287 Instruct the peer to begin a batched send.
4282 Instruct the peer to begin a batched send.
4288
4283
4289 All ``command`` blocks are queued for execution until the next
4284 All ``command`` blocks are queued for execution until the next
4290 ``batchsubmit`` block.
4285 ``batchsubmit`` block.
4291
4286
4292 batchsubmit
4287 batchsubmit
4293 -----------
4288 -----------
4294
4289
4295 Submit previously queued ``command`` blocks as a batch request.
4290 Submit previously queued ``command`` blocks as a batch request.
4296
4291
4297 This action MUST be paired with a ``batchbegin`` action.
4292 This action MUST be paired with a ``batchbegin`` action.
4298
4293
4299 httprequest <method> <path>
4294 httprequest <method> <path>
4300 ---------------------------
4295 ---------------------------
4301
4296
4302 (HTTP peer only)
4297 (HTTP peer only)
4303
4298
4304 Send an HTTP request to the peer.
4299 Send an HTTP request to the peer.
4305
4300
4306 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4301 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4307
4302
4308 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4303 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4309 headers to add to the request. e.g. ``Accept: foo``.
4304 headers to add to the request. e.g. ``Accept: foo``.
4310
4305
4311 The following arguments are special:
4306 The following arguments are special:
4312
4307
4313 ``BODYFILE``
4308 ``BODYFILE``
4314 The content of the file defined as the value to this argument will be
4309 The content of the file defined as the value to this argument will be
4315 transferred verbatim as the HTTP request body.
4310 transferred verbatim as the HTTP request body.
4316
4311
4317 ``frame <type> <flags> <payload>``
4312 ``frame <type> <flags> <payload>``
4318 Send a unified protocol frame as part of the request body.
4313 Send a unified protocol frame as part of the request body.
4319
4314
4320 All frames will be collected and sent as the body to the HTTP
4315 All frames will be collected and sent as the body to the HTTP
4321 request.
4316 request.
4322
4317
4323 close
4318 close
4324 -----
4319 -----
4325
4320
4326 Close the connection to the server.
4321 Close the connection to the server.
4327
4322
4328 flush
4323 flush
4329 -----
4324 -----
4330
4325
4331 Flush data written to the server.
4326 Flush data written to the server.
4332
4327
4333 readavailable
4328 readavailable
4334 -------------
4329 -------------
4335
4330
4336 Close the write end of the connection and read all available data from
4331 Close the write end of the connection and read all available data from
4337 the server.
4332 the server.
4338
4333
4339 If the connection to the server encompasses multiple pipes, we poll both
4334 If the connection to the server encompasses multiple pipes, we poll both
4340 pipes and read available data.
4335 pipes and read available data.
4341
4336
4342 readline
4337 readline
4343 --------
4338 --------
4344
4339
4345 Read a line of output from the server. If there are multiple output
4340 Read a line of output from the server. If there are multiple output
4346 pipes, reads only the main pipe.
4341 pipes, reads only the main pipe.
4347
4342
4348 ereadline
4343 ereadline
4349 ---------
4344 ---------
4350
4345
4351 Like ``readline``, but read from the stderr pipe, if available.
4346 Like ``readline``, but read from the stderr pipe, if available.
4352
4347
4353 read <X>
4348 read <X>
4354 --------
4349 --------
4355
4350
4356 ``read()`` N bytes from the server's main output pipe.
4351 ``read()`` N bytes from the server's main output pipe.
4357
4352
4358 eread <X>
4353 eread <X>
4359 ---------
4354 ---------
4360
4355
4361 ``read()`` N bytes from the server's stderr pipe, if available.
4356 ``read()`` N bytes from the server's stderr pipe, if available.
4362
4357
4363 Specifying Unified Frame-Based Protocol Frames
4358 Specifying Unified Frame-Based Protocol Frames
4364 ----------------------------------------------
4359 ----------------------------------------------
4365
4360
4366 It is possible to emit a *Unified Frame-Based Protocol* by using special
4361 It is possible to emit a *Unified Frame-Based Protocol* by using special
4367 syntax.
4362 syntax.
4368
4363
4369 A frame is composed as a type, flags, and payload. These can be parsed
4364 A frame is composed as a type, flags, and payload. These can be parsed
4370 from a string of the form:
4365 from a string of the form:
4371
4366
4372 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4367 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4373
4368
4374 ``request-id`` and ``stream-id`` are integers defining the request and
4369 ``request-id`` and ``stream-id`` are integers defining the request and
4375 stream identifiers.
4370 stream identifiers.
4376
4371
4377 ``type`` can be an integer value for the frame type or the string name
4372 ``type`` can be an integer value for the frame type or the string name
4378 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4373 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4379 ``command-name``.
4374 ``command-name``.
4380
4375
4381 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4376 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4382 components. Each component (and there can be just one) can be an integer
4377 components. Each component (and there can be just one) can be an integer
4383 or a flag name for stream flags or frame flags, respectively. Values are
4378 or a flag name for stream flags or frame flags, respectively. Values are
4384 resolved to integers and then bitwise OR'd together.
4379 resolved to integers and then bitwise OR'd together.
4385
4380
4386 ``payload`` represents the raw frame payload. If it begins with
4381 ``payload`` represents the raw frame payload. If it begins with
4387 ``cbor:``, the following string is evaluated as Python code and the
4382 ``cbor:``, the following string is evaluated as Python code and the
4388 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4383 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4389 as a Python byte string literal.
4384 as a Python byte string literal.
4390 """
4385 """
4391 opts = pycompat.byteskwargs(opts)
4386 opts = pycompat.byteskwargs(opts)
4392
4387
4393 if opts[b'localssh'] and not repo:
4388 if opts[b'localssh'] and not repo:
4394 raise error.Abort(_(b'--localssh requires a repository'))
4389 raise error.Abort(_(b'--localssh requires a repository'))
4395
4390
4396 if opts[b'peer'] and opts[b'peer'] not in (
4391 if opts[b'peer'] and opts[b'peer'] not in (
4397 b'raw',
4392 b'raw',
4398 b'ssh1',
4393 b'ssh1',
4399 ):
4394 ):
4400 raise error.Abort(
4395 raise error.Abort(
4401 _(b'invalid value for --peer'),
4396 _(b'invalid value for --peer'),
4402 hint=_(b'valid values are "raw" and "ssh1"'),
4397 hint=_(b'valid values are "raw" and "ssh1"'),
4403 )
4398 )
4404
4399
4405 if path and opts[b'localssh']:
4400 if path and opts[b'localssh']:
4406 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4401 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4407
4402
4408 if ui.interactive():
4403 if ui.interactive():
4409 ui.write(_(b'(waiting for commands on stdin)\n'))
4404 ui.write(_(b'(waiting for commands on stdin)\n'))
4410
4405
4411 blocks = list(_parsewirelangblocks(ui.fin))
4406 blocks = list(_parsewirelangblocks(ui.fin))
4412
4407
4413 proc = None
4408 proc = None
4414 stdin = None
4409 stdin = None
4415 stdout = None
4410 stdout = None
4416 stderr = None
4411 stderr = None
4417 opener = None
4412 opener = None
4418
4413
4419 if opts[b'localssh']:
4414 if opts[b'localssh']:
4420 # We start the SSH server in its own process so there is process
4415 # We start the SSH server in its own process so there is process
4421 # separation. This prevents a whole class of potential bugs around
4416 # separation. This prevents a whole class of potential bugs around
4422 # shared state from interfering with server operation.
4417 # shared state from interfering with server operation.
4423 args = procutil.hgcmd() + [
4418 args = procutil.hgcmd() + [
4424 b'-R',
4419 b'-R',
4425 repo.root,
4420 repo.root,
4426 b'debugserve',
4421 b'debugserve',
4427 b'--sshstdio',
4422 b'--sshstdio',
4428 ]
4423 ]
4429 proc = subprocess.Popen(
4424 proc = subprocess.Popen(
4430 pycompat.rapply(procutil.tonativestr, args),
4425 pycompat.rapply(procutil.tonativestr, args),
4431 stdin=subprocess.PIPE,
4426 stdin=subprocess.PIPE,
4432 stdout=subprocess.PIPE,
4427 stdout=subprocess.PIPE,
4433 stderr=subprocess.PIPE,
4428 stderr=subprocess.PIPE,
4434 bufsize=0,
4429 bufsize=0,
4435 )
4430 )
4436
4431
4437 stdin = proc.stdin
4432 stdin = proc.stdin
4438 stdout = proc.stdout
4433 stdout = proc.stdout
4439 stderr = proc.stderr
4434 stderr = proc.stderr
4440
4435
4441 # We turn the pipes into observers so we can log I/O.
4436 # We turn the pipes into observers so we can log I/O.
4442 if ui.verbose or opts[b'peer'] == b'raw':
4437 if ui.verbose or opts[b'peer'] == b'raw':
4443 stdin = util.makeloggingfileobject(
4438 stdin = util.makeloggingfileobject(
4444 ui, proc.stdin, b'i', logdata=True
4439 ui, proc.stdin, b'i', logdata=True
4445 )
4440 )
4446 stdout = util.makeloggingfileobject(
4441 stdout = util.makeloggingfileobject(
4447 ui, proc.stdout, b'o', logdata=True
4442 ui, proc.stdout, b'o', logdata=True
4448 )
4443 )
4449 stderr = util.makeloggingfileobject(
4444 stderr = util.makeloggingfileobject(
4450 ui, proc.stderr, b'e', logdata=True
4445 ui, proc.stderr, b'e', logdata=True
4451 )
4446 )
4452
4447
4453 # --localssh also implies the peer connection settings.
4448 # --localssh also implies the peer connection settings.
4454
4449
4455 url = b'ssh://localserver'
4450 url = b'ssh://localserver'
4456 autoreadstderr = not opts[b'noreadstderr']
4451 autoreadstderr = not opts[b'noreadstderr']
4457
4452
4458 if opts[b'peer'] == b'ssh1':
4453 if opts[b'peer'] == b'ssh1':
4459 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4454 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4460 peer = sshpeer.sshv1peer(
4455 peer = sshpeer.sshv1peer(
4461 ui,
4456 ui,
4462 url,
4457 url,
4463 proc,
4458 proc,
4464 stdin,
4459 stdin,
4465 stdout,
4460 stdout,
4466 stderr,
4461 stderr,
4467 None,
4462 None,
4468 autoreadstderr=autoreadstderr,
4463 autoreadstderr=autoreadstderr,
4469 )
4464 )
4470 elif opts[b'peer'] == b'raw':
4465 elif opts[b'peer'] == b'raw':
4471 ui.write(_(b'using raw connection to peer\n'))
4466 ui.write(_(b'using raw connection to peer\n'))
4472 peer = None
4467 peer = None
4473 else:
4468 else:
4474 ui.write(_(b'creating ssh peer from handshake results\n'))
4469 ui.write(_(b'creating ssh peer from handshake results\n'))
4475 peer = sshpeer.makepeer(
4470 peer = sshpeer.makepeer(
4476 ui,
4471 ui,
4477 url,
4472 url,
4478 proc,
4473 proc,
4479 stdin,
4474 stdin,
4480 stdout,
4475 stdout,
4481 stderr,
4476 stderr,
4482 autoreadstderr=autoreadstderr,
4477 autoreadstderr=autoreadstderr,
4483 )
4478 )
4484
4479
4485 elif path:
4480 elif path:
4486 # We bypass hg.peer() so we can proxy the sockets.
4481 # We bypass hg.peer() so we can proxy the sockets.
4487 # TODO consider not doing this because we skip
4482 # TODO consider not doing this because we skip
4488 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4483 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4489 u = urlutil.url(path)
4484 u = urlutil.url(path)
4490 if u.scheme != b'http':
4485 if u.scheme != b'http':
4491 raise error.Abort(_(b'only http:// paths are currently supported'))
4486 raise error.Abort(_(b'only http:// paths are currently supported'))
4492
4487
4493 url, authinfo = u.authinfo()
4488 url, authinfo = u.authinfo()
4494 openerargs = {
4489 openerargs = {
4495 'useragent': b'Mercurial debugwireproto',
4490 'useragent': b'Mercurial debugwireproto',
4496 }
4491 }
4497
4492
4498 # Turn pipes/sockets into observers so we can log I/O.
4493 # Turn pipes/sockets into observers so we can log I/O.
4499 if ui.verbose:
4494 if ui.verbose:
4500 openerargs.update(
4495 openerargs.update(
4501 {
4496 {
4502 'loggingfh': ui,
4497 'loggingfh': ui,
4503 'loggingname': b's',
4498 'loggingname': b's',
4504 'loggingopts': {
4499 'loggingopts': {
4505 'logdata': True,
4500 'logdata': True,
4506 'logdataapis': False,
4501 'logdataapis': False,
4507 },
4502 },
4508 }
4503 }
4509 )
4504 )
4510
4505
4511 if ui.debugflag:
4506 if ui.debugflag:
4512 openerargs['loggingopts']['logdataapis'] = True
4507 openerargs['loggingopts']['logdataapis'] = True
4513
4508
4514 # Don't send default headers when in raw mode. This allows us to
4509 # Don't send default headers when in raw mode. This allows us to
4515 # bypass most of the behavior of our URL handling code so we can
4510 # bypass most of the behavior of our URL handling code so we can
4516 # have near complete control over what's sent on the wire.
4511 # have near complete control over what's sent on the wire.
4517 if opts[b'peer'] == b'raw':
4512 if opts[b'peer'] == b'raw':
4518 openerargs['sendaccept'] = False
4513 openerargs['sendaccept'] = False
4519
4514
4520 opener = urlmod.opener(ui, authinfo, **openerargs)
4515 opener = urlmod.opener(ui, authinfo, **openerargs)
4521
4516
4522 if opts[b'peer'] == b'raw':
4517 if opts[b'peer'] == b'raw':
4523 ui.write(_(b'using raw connection to peer\n'))
4518 ui.write(_(b'using raw connection to peer\n'))
4524 peer = None
4519 peer = None
4525 elif opts[b'peer']:
4520 elif opts[b'peer']:
4526 raise error.Abort(
4521 raise error.Abort(
4527 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4522 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4528 )
4523 )
4529 else:
4524 else:
4530 peer_path = urlutil.try_path(ui, path)
4525 peer_path = urlutil.try_path(ui, path)
4531 peer = httppeer.makepeer(ui, peer_path, opener=opener)
4526 peer = httppeer.makepeer(ui, peer_path, opener=opener)
4532
4527
4533 # We /could/ populate stdin/stdout with sock.makefile()...
4528 # We /could/ populate stdin/stdout with sock.makefile()...
4534 else:
4529 else:
4535 raise error.Abort(_(b'unsupported connection configuration'))
4530 raise error.Abort(_(b'unsupported connection configuration'))
4536
4531
4537 batchedcommands = None
4532 batchedcommands = None
4538
4533
4539 # Now perform actions based on the parsed wire language instructions.
4534 # Now perform actions based on the parsed wire language instructions.
4540 for action, lines in blocks:
4535 for action, lines in blocks:
4541 if action in (b'raw', b'raw+'):
4536 if action in (b'raw', b'raw+'):
4542 if not stdin:
4537 if not stdin:
4543 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4538 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4544
4539
4545 # Concatenate the data together.
4540 # Concatenate the data together.
4546 data = b''.join(l.lstrip() for l in lines)
4541 data = b''.join(l.lstrip() for l in lines)
4547 data = stringutil.unescapestr(data)
4542 data = stringutil.unescapestr(data)
4548 stdin.write(data)
4543 stdin.write(data)
4549
4544
4550 if action == b'raw+':
4545 if action == b'raw+':
4551 stdin.flush()
4546 stdin.flush()
4552 elif action == b'flush':
4547 elif action == b'flush':
4553 if not stdin:
4548 if not stdin:
4554 raise error.Abort(_(b'cannot call flush on this peer'))
4549 raise error.Abort(_(b'cannot call flush on this peer'))
4555 stdin.flush()
4550 stdin.flush()
4556 elif action.startswith(b'command'):
4551 elif action.startswith(b'command'):
4557 if not peer:
4552 if not peer:
4558 raise error.Abort(
4553 raise error.Abort(
4559 _(
4554 _(
4560 b'cannot send commands unless peer instance '
4555 b'cannot send commands unless peer instance '
4561 b'is available'
4556 b'is available'
4562 )
4557 )
4563 )
4558 )
4564
4559
4565 command = action.split(b' ', 1)[1]
4560 command = action.split(b' ', 1)[1]
4566
4561
4567 args = {}
4562 args = {}
4568 for line in lines:
4563 for line in lines:
4569 # We need to allow empty values.
4564 # We need to allow empty values.
4570 fields = line.lstrip().split(b' ', 1)
4565 fields = line.lstrip().split(b' ', 1)
4571 if len(fields) == 1:
4566 if len(fields) == 1:
4572 key = fields[0]
4567 key = fields[0]
4573 value = b''
4568 value = b''
4574 else:
4569 else:
4575 key, value = fields
4570 key, value = fields
4576
4571
4577 if value.startswith(b'eval:'):
4572 if value.startswith(b'eval:'):
4578 value = stringutil.evalpythonliteral(value[5:])
4573 value = stringutil.evalpythonliteral(value[5:])
4579 else:
4574 else:
4580 value = stringutil.unescapestr(value)
4575 value = stringutil.unescapestr(value)
4581
4576
4582 args[key] = value
4577 args[key] = value
4583
4578
4584 if batchedcommands is not None:
4579 if batchedcommands is not None:
4585 batchedcommands.append((command, args))
4580 batchedcommands.append((command, args))
4586 continue
4581 continue
4587
4582
4588 ui.status(_(b'sending %s command\n') % command)
4583 ui.status(_(b'sending %s command\n') % command)
4589
4584
4590 if b'PUSHFILE' in args:
4585 if b'PUSHFILE' in args:
4591 with open(args[b'PUSHFILE'], 'rb') as fh:
4586 with open(args[b'PUSHFILE'], 'rb') as fh:
4592 del args[b'PUSHFILE']
4587 del args[b'PUSHFILE']
4593 res, output = peer._callpush(
4588 res, output = peer._callpush(
4594 command, fh, **pycompat.strkwargs(args)
4589 command, fh, **pycompat.strkwargs(args)
4595 )
4590 )
4596 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4591 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4597 ui.status(
4592 ui.status(
4598 _(b'remote output: %s\n') % stringutil.escapestr(output)
4593 _(b'remote output: %s\n') % stringutil.escapestr(output)
4599 )
4594 )
4600 else:
4595 else:
4601 with peer.commandexecutor() as e:
4596 with peer.commandexecutor() as e:
4602 res = e.callcommand(command, args).result()
4597 res = e.callcommand(command, args).result()
4603
4598
4604 ui.status(
4599 ui.status(
4605 _(b'response: %s\n')
4600 _(b'response: %s\n')
4606 % stringutil.pprint(res, bprefix=True, indent=2)
4601 % stringutil.pprint(res, bprefix=True, indent=2)
4607 )
4602 )
4608
4603
4609 elif action == b'batchbegin':
4604 elif action == b'batchbegin':
4610 if batchedcommands is not None:
4605 if batchedcommands is not None:
4611 raise error.Abort(_(b'nested batchbegin not allowed'))
4606 raise error.Abort(_(b'nested batchbegin not allowed'))
4612
4607
4613 batchedcommands = []
4608 batchedcommands = []
4614 elif action == b'batchsubmit':
4609 elif action == b'batchsubmit':
4615 # There is a batching API we could go through. But it would be
4610 # There is a batching API we could go through. But it would be
4616 # difficult to normalize requests into function calls. It is easier
4611 # difficult to normalize requests into function calls. It is easier
4617 # to bypass this layer and normalize to commands + args.
4612 # to bypass this layer and normalize to commands + args.
4618 ui.status(
4613 ui.status(
4619 _(b'sending batch with %d sub-commands\n')
4614 _(b'sending batch with %d sub-commands\n')
4620 % len(batchedcommands)
4615 % len(batchedcommands)
4621 )
4616 )
4622 assert peer is not None
4617 assert peer is not None
4623 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4618 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4624 ui.status(
4619 ui.status(
4625 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4620 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4626 )
4621 )
4627
4622
4628 batchedcommands = None
4623 batchedcommands = None
4629
4624
4630 elif action.startswith(b'httprequest '):
4625 elif action.startswith(b'httprequest '):
4631 if not opener:
4626 if not opener:
4632 raise error.Abort(
4627 raise error.Abort(
4633 _(b'cannot use httprequest without an HTTP peer')
4628 _(b'cannot use httprequest without an HTTP peer')
4634 )
4629 )
4635
4630
4636 request = action.split(b' ', 2)
4631 request = action.split(b' ', 2)
4637 if len(request) != 3:
4632 if len(request) != 3:
4638 raise error.Abort(
4633 raise error.Abort(
4639 _(
4634 _(
4640 b'invalid httprequest: expected format is '
4635 b'invalid httprequest: expected format is '
4641 b'"httprequest <method> <path>'
4636 b'"httprequest <method> <path>'
4642 )
4637 )
4643 )
4638 )
4644
4639
4645 method, httppath = request[1:]
4640 method, httppath = request[1:]
4646 headers = {}
4641 headers = {}
4647 body = None
4642 body = None
4648 frames = []
4643 frames = []
4649 for line in lines:
4644 for line in lines:
4650 line = line.lstrip()
4645 line = line.lstrip()
4651 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4646 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4652 if m:
4647 if m:
4653 # Headers need to use native strings.
4648 # Headers need to use native strings.
4654 key = pycompat.strurl(m.group(1))
4649 key = pycompat.strurl(m.group(1))
4655 value = pycompat.strurl(m.group(2))
4650 value = pycompat.strurl(m.group(2))
4656 headers[key] = value
4651 headers[key] = value
4657 continue
4652 continue
4658
4653
4659 if line.startswith(b'BODYFILE '):
4654 if line.startswith(b'BODYFILE '):
4660 with open(line.split(b' ', 1), b'rb') as fh:
4655 with open(line.split(b' ', 1), b'rb') as fh:
4661 body = fh.read()
4656 body = fh.read()
4662 elif line.startswith(b'frame '):
4657 elif line.startswith(b'frame '):
4663 frame = wireprotoframing.makeframefromhumanstring(
4658 frame = wireprotoframing.makeframefromhumanstring(
4664 line[len(b'frame ') :]
4659 line[len(b'frame ') :]
4665 )
4660 )
4666
4661
4667 frames.append(frame)
4662 frames.append(frame)
4668 else:
4663 else:
4669 raise error.Abort(
4664 raise error.Abort(
4670 _(b'unknown argument to httprequest: %s') % line
4665 _(b'unknown argument to httprequest: %s') % line
4671 )
4666 )
4672
4667
4673 url = path + httppath
4668 url = path + httppath
4674
4669
4675 if frames:
4670 if frames:
4676 body = b''.join(bytes(f) for f in frames)
4671 body = b''.join(bytes(f) for f in frames)
4677
4672
4678 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4673 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4679
4674
4680 # urllib.Request insists on using has_data() as a proxy for
4675 # urllib.Request insists on using has_data() as a proxy for
4681 # determining the request method. Override that to use our
4676 # determining the request method. Override that to use our
4682 # explicitly requested method.
4677 # explicitly requested method.
4683 req.get_method = lambda: pycompat.sysstr(method)
4678 req.get_method = lambda: pycompat.sysstr(method)
4684
4679
4685 try:
4680 try:
4686 res = opener.open(req)
4681 res = opener.open(req)
4687 body = res.read()
4682 body = res.read()
4688 except util.urlerr.urlerror as e:
4683 except util.urlerr.urlerror as e:
4689 # read() method must be called, but only exists in Python 2
4684 # read() method must be called, but only exists in Python 2
4690 getattr(e, 'read', lambda: None)()
4685 getattr(e, 'read', lambda: None)()
4691 continue
4686 continue
4692
4687
4693 ct = res.headers.get('Content-Type')
4688 ct = res.headers.get('Content-Type')
4694 if ct == 'application/mercurial-cbor':
4689 if ct == 'application/mercurial-cbor':
4695 ui.write(
4690 ui.write(
4696 _(b'cbor> %s\n')
4691 _(b'cbor> %s\n')
4697 % stringutil.pprint(
4692 % stringutil.pprint(
4698 cborutil.decodeall(body), bprefix=True, indent=2
4693 cborutil.decodeall(body), bprefix=True, indent=2
4699 )
4694 )
4700 )
4695 )
4701
4696
4702 elif action == b'close':
4697 elif action == b'close':
4703 assert peer is not None
4698 assert peer is not None
4704 peer.close()
4699 peer.close()
4705 elif action == b'readavailable':
4700 elif action == b'readavailable':
4706 if not stdout or not stderr:
4701 if not stdout or not stderr:
4707 raise error.Abort(
4702 raise error.Abort(
4708 _(b'readavailable not available on this peer')
4703 _(b'readavailable not available on this peer')
4709 )
4704 )
4710
4705
4711 stdin.close()
4706 stdin.close()
4712 stdout.read()
4707 stdout.read()
4713 stderr.read()
4708 stderr.read()
4714
4709
4715 elif action == b'readline':
4710 elif action == b'readline':
4716 if not stdout:
4711 if not stdout:
4717 raise error.Abort(_(b'readline not available on this peer'))
4712 raise error.Abort(_(b'readline not available on this peer'))
4718 stdout.readline()
4713 stdout.readline()
4719 elif action == b'ereadline':
4714 elif action == b'ereadline':
4720 if not stderr:
4715 if not stderr:
4721 raise error.Abort(_(b'ereadline not available on this peer'))
4716 raise error.Abort(_(b'ereadline not available on this peer'))
4722 stderr.readline()
4717 stderr.readline()
4723 elif action.startswith(b'read '):
4718 elif action.startswith(b'read '):
4724 count = int(action.split(b' ', 1)[1])
4719 count = int(action.split(b' ', 1)[1])
4725 if not stdout:
4720 if not stdout:
4726 raise error.Abort(_(b'read not available on this peer'))
4721 raise error.Abort(_(b'read not available on this peer'))
4727 stdout.read(count)
4722 stdout.read(count)
4728 elif action.startswith(b'eread '):
4723 elif action.startswith(b'eread '):
4729 count = int(action.split(b' ', 1)[1])
4724 count = int(action.split(b' ', 1)[1])
4730 if not stderr:
4725 if not stderr:
4731 raise error.Abort(_(b'eread not available on this peer'))
4726 raise error.Abort(_(b'eread not available on this peer'))
4732 stderr.read(count)
4727 stderr.read(count)
4733 else:
4728 else:
4734 raise error.Abort(_(b'unknown action: %s') % action)
4729 raise error.Abort(_(b'unknown action: %s') % action)
4735
4730
4736 if batchedcommands is not None:
4731 if batchedcommands is not None:
4737 raise error.Abort(_(b'unclosed "batchbegin" request'))
4732 raise error.Abort(_(b'unclosed "batchbegin" request'))
4738
4733
4739 if peer:
4734 if peer:
4740 peer.close()
4735 peer.close()
4741
4736
4742 if proc:
4737 if proc:
4743 proc.kill()
4738 proc.kill()
@@ -1,587 +1,621 b''
1 # verify.py - repository integrity checking for Mercurial
1 # verify.py - repository integrity checking for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2006, 2007 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
8
9 import os
9 import os
10
10
11 from .i18n import _
11 from .i18n import _
12 from .node import short
12 from .node import short
13 from .utils import stringutil
13 from .utils import stringutil
14
14
15 from . import (
15 from . import (
16 error,
16 error,
17 pycompat,
17 pycompat,
18 requirements,
18 revlog,
19 revlog,
19 util,
20 util,
20 )
21 )
21
22
22 VERIFY_DEFAULT = 0
23 VERIFY_DEFAULT = 0
23 VERIFY_FULL = 1
24 VERIFY_FULL = 1
24
25
25
26
26 def verify(repo, level=None):
27 def verify(repo, level=None):
27 with repo.lock():
28 with repo.lock():
28 v = verifier(repo, level)
29 v = verifier(repo, level)
29 return v.verify()
30 return v.verify()
30
31
31
32
32 def _normpath(f):
33 def _normpath(f):
33 # under hg < 2.4, convert didn't sanitize paths properly, so a
34 # under hg < 2.4, convert didn't sanitize paths properly, so a
34 # converted repo may contain repeated slashes
35 # converted repo may contain repeated slashes
35 while b'//' in f:
36 while b'//' in f:
36 f = f.replace(b'//', b'/')
37 f = f.replace(b'//', b'/')
37 return f
38 return f
38
39
39
40
40 HINT_FNCACHE = _(
41 HINT_FNCACHE = _(
41 b'hint: run "hg debugrebuildfncache" to recover from corrupt fncache\n'
42 b'hint: run "hg debugrebuildfncache" to recover from corrupt fncache\n'
42 )
43 )
43
44
44 WARN_PARENT_DIR_UNKNOWN_REV = _(
45 WARN_PARENT_DIR_UNKNOWN_REV = _(
45 b"parent-directory manifest refers to unknown revision %s"
46 b"parent-directory manifest refers to unknown revision %s"
46 )
47 )
47
48
48 WARN_UNKNOWN_COPY_SOURCE = _(
49 WARN_UNKNOWN_COPY_SOURCE = _(
49 b"warning: copy source of '%s' not in parents of %s"
50 b"warning: copy source of '%s' not in parents of %s"
50 )
51 )
51
52
52 WARN_NULLID_COPY_SOURCE = _(
53 WARN_NULLID_COPY_SOURCE = _(
53 b"warning: %s@%s: copy source revision is nullid %s:%s\n"
54 b"warning: %s@%s: copy source revision is nullid %s:%s\n"
54 )
55 )
55
56
56
57
57 class verifier:
58 class verifier:
58 def __init__(self, repo, level=None):
59 def __init__(self, repo, level=None):
59 self.repo = repo.unfiltered()
60 self.repo = repo.unfiltered()
60 self.ui = repo.ui
61 self.ui = repo.ui
61 self.match = repo.narrowmatch()
62 self.match = repo.narrowmatch()
62 if level is None:
63 if level is None:
63 level = VERIFY_DEFAULT
64 level = VERIFY_DEFAULT
64 self._level = level
65 self._level = level
65 self.badrevs = set()
66 self.badrevs = set()
66 self.errors = 0
67 self.errors = 0
67 self.warnings = 0
68 self.warnings = 0
68 self.havecl = len(repo.changelog) > 0
69 self.havecl = len(repo.changelog) > 0
69 self.havemf = len(repo.manifestlog.getstorage(b'')) > 0
70 self.havemf = len(repo.manifestlog.getstorage(b'')) > 0
70 self.revlogv1 = repo.changelog._format_version != revlog.REVLOGV0
71 self.revlogv1 = repo.changelog._format_version != revlog.REVLOGV0
71 self.lrugetctx = util.lrucachefunc(repo.unfiltered().__getitem__)
72 self.lrugetctx = util.lrucachefunc(repo.unfiltered().__getitem__)
72 self.refersmf = False
73 self.refersmf = False
73 self.fncachewarned = False
74 self.fncachewarned = False
74 # developer config: verify.skipflags
75 # developer config: verify.skipflags
75 self.skipflags = repo.ui.configint(b'verify', b'skipflags')
76 self.skipflags = repo.ui.configint(b'verify', b'skipflags')
76 self.warnorphanstorefiles = True
77 self.warnorphanstorefiles = True
77
78
78 def _warn(self, msg):
79 def _warn(self, msg):
79 """record a "warning" level issue"""
80 """record a "warning" level issue"""
80 self.ui.warn(msg + b"\n")
81 self.ui.warn(msg + b"\n")
81 self.warnings += 1
82 self.warnings += 1
82
83
83 def _err(self, linkrev, msg, filename=None):
84 def _err(self, linkrev, msg, filename=None):
84 """record a "error" level issue"""
85 """record a "error" level issue"""
85 if linkrev is not None:
86 if linkrev is not None:
86 self.badrevs.add(linkrev)
87 self.badrevs.add(linkrev)
87 linkrev = b"%d" % linkrev
88 linkrev = b"%d" % linkrev
88 else:
89 else:
89 linkrev = b'?'
90 linkrev = b'?'
90 msg = b"%s: %s" % (linkrev, msg)
91 msg = b"%s: %s" % (linkrev, msg)
91 if filename:
92 if filename:
92 msg = b"%s@%s" % (filename, msg)
93 msg = b"%s@%s" % (filename, msg)
93 self.ui.warn(b" " + msg + b"\n")
94 self.ui.warn(b" " + msg + b"\n")
94 self.errors += 1
95 self.errors += 1
95
96
96 def _exc(self, linkrev, msg, inst, filename=None):
97 def _exc(self, linkrev, msg, inst, filename=None):
97 """record exception raised during the verify process"""
98 """record exception raised during the verify process"""
98 fmsg = stringutil.forcebytestr(inst)
99 fmsg = stringutil.forcebytestr(inst)
99 if not fmsg:
100 if not fmsg:
100 fmsg = pycompat.byterepr(inst)
101 fmsg = pycompat.byterepr(inst)
101 self._err(linkrev, b"%s: %s" % (msg, fmsg), filename)
102 self._err(linkrev, b"%s: %s" % (msg, fmsg), filename)
102
103
103 def _checkrevlog(self, obj, name, linkrev):
104 def _checkrevlog(self, obj, name, linkrev):
104 """verify high level property of a revlog
105 """verify high level property of a revlog
105
106
106 - revlog is present,
107 - revlog is present,
107 - revlog is non-empty,
108 - revlog is non-empty,
108 - sizes (index and data) are correct,
109 - sizes (index and data) are correct,
109 - revlog's format version is correct.
110 - revlog's format version is correct.
110 """
111 """
111 if not len(obj) and (self.havecl or self.havemf):
112 if not len(obj) and (self.havecl or self.havemf):
112 self._err(linkrev, _(b"empty or missing %s") % name)
113 self._err(linkrev, _(b"empty or missing %s") % name)
113 return
114 return
114
115
115 d = obj.checksize()
116 d = obj.checksize()
116 if d[0]:
117 if d[0]:
117 self._err(None, _(b"data length off by %d bytes") % d[0], name)
118 self._err(None, _(b"data length off by %d bytes") % d[0], name)
118 if d[1]:
119 if d[1]:
119 self._err(None, _(b"index contains %d extra bytes") % d[1], name)
120 self._err(None, _(b"index contains %d extra bytes") % d[1], name)
120
121
121 if obj._format_version != revlog.REVLOGV0:
122 if obj._format_version != revlog.REVLOGV0:
122 if not self.revlogv1:
123 if not self.revlogv1:
123 self._warn(_(b"warning: `%s' uses revlog format 1") % name)
124 self._warn(_(b"warning: `%s' uses revlog format 1") % name)
124 elif self.revlogv1:
125 elif self.revlogv1:
125 self._warn(_(b"warning: `%s' uses revlog format 0") % name)
126 self._warn(_(b"warning: `%s' uses revlog format 0") % name)
126
127
127 def _checkentry(self, obj, i, node, seen, linkrevs, f):
128 def _checkentry(self, obj, i, node, seen, linkrevs, f):
128 """verify a single revlog entry
129 """verify a single revlog entry
129
130
130 arguments are:
131 arguments are:
131 - obj: the source revlog
132 - obj: the source revlog
132 - i: the revision number
133 - i: the revision number
133 - node: the revision node id
134 - node: the revision node id
134 - seen: nodes previously seen for this revlog
135 - seen: nodes previously seen for this revlog
135 - linkrevs: [changelog-revisions] introducing "node"
136 - linkrevs: [changelog-revisions] introducing "node"
136 - f: string label ("changelog", "manifest", or filename)
137 - f: string label ("changelog", "manifest", or filename)
137
138
138 Performs the following checks:
139 Performs the following checks:
139 - linkrev points to an existing changelog revision,
140 - linkrev points to an existing changelog revision,
140 - linkrev points to a changelog revision that introduces this revision,
141 - linkrev points to a changelog revision that introduces this revision,
141 - linkrev points to the lowest of these changesets,
142 - linkrev points to the lowest of these changesets,
142 - both parents exist in the revlog,
143 - both parents exist in the revlog,
143 - the revision is not duplicated.
144 - the revision is not duplicated.
144
145
145 Return the linkrev of the revision (or None for changelog's revisions).
146 Return the linkrev of the revision (or None for changelog's revisions).
146 """
147 """
147 lr = obj.linkrev(obj.rev(node))
148 lr = obj.linkrev(obj.rev(node))
148 if lr < 0 or (self.havecl and lr not in linkrevs):
149 if lr < 0 or (self.havecl and lr not in linkrevs):
149 if lr < 0 or lr >= len(self.repo.changelog):
150 if lr < 0 or lr >= len(self.repo.changelog):
150 msg = _(b"rev %d points to nonexistent changeset %d")
151 msg = _(b"rev %d points to nonexistent changeset %d")
151 else:
152 else:
152 msg = _(b"rev %d points to unexpected changeset %d")
153 msg = _(b"rev %d points to unexpected changeset %d")
153 self._err(None, msg % (i, lr), f)
154 self._err(None, msg % (i, lr), f)
154 if linkrevs:
155 if linkrevs:
155 if f and len(linkrevs) > 1:
156 if f and len(linkrevs) > 1:
156 try:
157 try:
157 # attempt to filter down to real linkrevs
158 # attempt to filter down to real linkrevs
158 linkrevs = []
159 linkrevs = []
159 for lr in linkrevs:
160 for lr in linkrevs:
160 if self.lrugetctx(lr)[f].filenode() == node:
161 if self.lrugetctx(lr)[f].filenode() == node:
161 linkrevs.append(lr)
162 linkrevs.append(lr)
162 except Exception:
163 except Exception:
163 pass
164 pass
164 msg = _(b" (expected %s)")
165 msg = _(b" (expected %s)")
165 msg %= b" ".join(map(pycompat.bytestr, linkrevs))
166 msg %= b" ".join(map(pycompat.bytestr, linkrevs))
166 self._warn(msg)
167 self._warn(msg)
167 lr = None # can't be trusted
168 lr = None # can't be trusted
168
169
169 try:
170 try:
170 p1, p2 = obj.parents(node)
171 p1, p2 = obj.parents(node)
171 if p1 not in seen and p1 != self.repo.nullid:
172 if p1 not in seen and p1 != self.repo.nullid:
172 msg = _(b"unknown parent 1 %s of %s") % (short(p1), short(node))
173 msg = _(b"unknown parent 1 %s of %s") % (short(p1), short(node))
173 self._err(lr, msg, f)
174 self._err(lr, msg, f)
174 if p2 not in seen and p2 != self.repo.nullid:
175 if p2 not in seen and p2 != self.repo.nullid:
175 msg = _(b"unknown parent 2 %s of %s") % (short(p2), short(node))
176 msg = _(b"unknown parent 2 %s of %s") % (short(p2), short(node))
176 self._err(lr, msg, f)
177 self._err(lr, msg, f)
177 except Exception as inst:
178 except Exception as inst:
178 self._exc(lr, _(b"checking parents of %s") % short(node), inst, f)
179 self._exc(lr, _(b"checking parents of %s") % short(node), inst, f)
179
180
180 if node in seen:
181 if node in seen:
181 self._err(lr, _(b"duplicate revision %d (%d)") % (i, seen[node]), f)
182 self._err(lr, _(b"duplicate revision %d (%d)") % (i, seen[node]), f)
182 seen[node] = i
183 seen[node] = i
183 return lr
184 return lr
184
185
185 def verify(self):
186 def verify(self):
186 """verify the content of the Mercurial repository
187 """verify the content of the Mercurial repository
187
188
188 This method run all verifications, displaying issues as they are found.
189 This method run all verifications, displaying issues as they are found.
189
190
190 return 1 if any error have been encountered, 0 otherwise."""
191 return 1 if any error have been encountered, 0 otherwise."""
191 # initial validation and generic report
192 # initial validation and generic report
192 repo = self.repo
193 repo = self.repo
193 ui = repo.ui
194 ui = repo.ui
194 if not repo.url().startswith(b'file:'):
195 if not repo.url().startswith(b'file:'):
195 raise error.Abort(_(b"cannot verify bundle or remote repos"))
196 raise error.Abort(_(b"cannot verify bundle or remote repos"))
196
197
197 if os.path.exists(repo.sjoin(b"journal")):
198 if os.path.exists(repo.sjoin(b"journal")):
198 ui.warn(_(b"abandoned transaction found - run hg recover\n"))
199 ui.warn(_(b"abandoned transaction found - run hg recover\n"))
199
200
200 if ui.verbose or not self.revlogv1:
201 if ui.verbose or not self.revlogv1:
201 ui.status(
202 ui.status(
202 _(b"repository uses revlog format %d\n")
203 _(b"repository uses revlog format %d\n")
203 % (self.revlogv1 and 1 or 0)
204 % (self.revlogv1 and 1 or 0)
204 )
205 )
205
206
206 # data verification
207 # data verification
207 mflinkrevs, filelinkrevs = self._verifychangelog()
208 mflinkrevs, filelinkrevs = self._verifychangelog()
208 filenodes = self._verifymanifest(mflinkrevs)
209 filenodes = self._verifymanifest(mflinkrevs)
209 del mflinkrevs
210 del mflinkrevs
210 self._crosscheckfiles(filelinkrevs, filenodes)
211 self._crosscheckfiles(filelinkrevs, filenodes)
211 totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
212 totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
212
213
214 if self.errors:
215 ui.warn(_(b"not checking dirstate because of previous errors\n"))
216 dirstate_errors = 0
217 else:
218 dirstate_errors = self._verify_dirstate()
219
213 # final report
220 # final report
214 ui.status(
221 ui.status(
215 _(b"checked %d changesets with %d changes to %d files\n")
222 _(b"checked %d changesets with %d changes to %d files\n")
216 % (len(repo.changelog), filerevisions, totalfiles)
223 % (len(repo.changelog), filerevisions, totalfiles)
217 )
224 )
218 if self.warnings:
225 if self.warnings:
219 ui.warn(_(b"%d warnings encountered!\n") % self.warnings)
226 ui.warn(_(b"%d warnings encountered!\n") % self.warnings)
220 if self.fncachewarned:
227 if self.fncachewarned:
221 ui.warn(HINT_FNCACHE)
228 ui.warn(HINT_FNCACHE)
222 if self.errors:
229 if self.errors:
223 ui.warn(_(b"%d integrity errors encountered!\n") % self.errors)
230 ui.warn(_(b"%d integrity errors encountered!\n") % self.errors)
224 if self.badrevs:
231 if self.badrevs:
225 msg = _(b"(first damaged changeset appears to be %d)\n")
232 msg = _(b"(first damaged changeset appears to be %d)\n")
226 msg %= min(self.badrevs)
233 msg %= min(self.badrevs)
227 ui.warn(msg)
234 ui.warn(msg)
235 if dirstate_errors:
236 ui.warn(
237 _(b"dirstate inconsistent with current parent's manifest\n")
238 )
239 ui.warn(_(b"%d dirstate errors\n") % dirstate_errors)
228 return 1
240 return 1
229 return 0
241 return 0
230
242
231 def _verifychangelog(self):
243 def _verifychangelog(self):
232 """verify the changelog of a repository
244 """verify the changelog of a repository
233
245
234 The following checks are performed:
246 The following checks are performed:
235 - all of `_checkrevlog` checks,
247 - all of `_checkrevlog` checks,
236 - all of `_checkentry` checks (for each revisions),
248 - all of `_checkentry` checks (for each revisions),
237 - each revision can be read.
249 - each revision can be read.
238
250
239 The function returns some of the data observed in the changesets as a
251 The function returns some of the data observed in the changesets as a
240 (mflinkrevs, filelinkrevs) tuples:
252 (mflinkrevs, filelinkrevs) tuples:
241 - mflinkrevs: is a { manifest-node -> [changelog-rev] } mapping
253 - mflinkrevs: is a { manifest-node -> [changelog-rev] } mapping
242 - filelinkrevs: is a { file-path -> [changelog-rev] } mapping
254 - filelinkrevs: is a { file-path -> [changelog-rev] } mapping
243
255
244 If a matcher was specified, filelinkrevs will only contains matched
256 If a matcher was specified, filelinkrevs will only contains matched
245 files.
257 files.
246 """
258 """
247 ui = self.ui
259 ui = self.ui
248 repo = self.repo
260 repo = self.repo
249 match = self.match
261 match = self.match
250 cl = repo.changelog
262 cl = repo.changelog
251
263
252 ui.status(_(b"checking changesets\n"))
264 ui.status(_(b"checking changesets\n"))
253 mflinkrevs = {}
265 mflinkrevs = {}
254 filelinkrevs = {}
266 filelinkrevs = {}
255 seen = {}
267 seen = {}
256 self._checkrevlog(cl, b"changelog", 0)
268 self._checkrevlog(cl, b"changelog", 0)
257 progress = ui.makeprogress(
269 progress = ui.makeprogress(
258 _(b'checking'), unit=_(b'changesets'), total=len(repo)
270 _(b'checking'), unit=_(b'changesets'), total=len(repo)
259 )
271 )
260 for i in repo:
272 for i in repo:
261 progress.update(i)
273 progress.update(i)
262 n = cl.node(i)
274 n = cl.node(i)
263 self._checkentry(cl, i, n, seen, [i], b"changelog")
275 self._checkentry(cl, i, n, seen, [i], b"changelog")
264
276
265 try:
277 try:
266 changes = cl.read(n)
278 changes = cl.read(n)
267 if changes[0] != self.repo.nullid:
279 if changes[0] != self.repo.nullid:
268 mflinkrevs.setdefault(changes[0], []).append(i)
280 mflinkrevs.setdefault(changes[0], []).append(i)
269 self.refersmf = True
281 self.refersmf = True
270 for f in changes[3]:
282 for f in changes[3]:
271 if match(f):
283 if match(f):
272 filelinkrevs.setdefault(_normpath(f), []).append(i)
284 filelinkrevs.setdefault(_normpath(f), []).append(i)
273 except Exception as inst:
285 except Exception as inst:
274 self.refersmf = True
286 self.refersmf = True
275 self._exc(i, _(b"unpacking changeset %s") % short(n), inst)
287 self._exc(i, _(b"unpacking changeset %s") % short(n), inst)
276 progress.complete()
288 progress.complete()
277 return mflinkrevs, filelinkrevs
289 return mflinkrevs, filelinkrevs
278
290
279 def _verifymanifest(
291 def _verifymanifest(
280 self, mflinkrevs, dir=b"", storefiles=None, subdirprogress=None
292 self, mflinkrevs, dir=b"", storefiles=None, subdirprogress=None
281 ):
293 ):
282 """verify the manifestlog content
294 """verify the manifestlog content
283
295
284 Inputs:
296 Inputs:
285 - mflinkrevs: a {manifest-node -> [changelog-revisions]} mapping
297 - mflinkrevs: a {manifest-node -> [changelog-revisions]} mapping
286 - dir: a subdirectory to check (for tree manifest repo)
298 - dir: a subdirectory to check (for tree manifest repo)
287 - storefiles: set of currently "orphan" files.
299 - storefiles: set of currently "orphan" files.
288 - subdirprogress: a progress object
300 - subdirprogress: a progress object
289
301
290 This function checks:
302 This function checks:
291 * all of `_checkrevlog` checks (for all manifest related revlogs)
303 * all of `_checkrevlog` checks (for all manifest related revlogs)
292 * all of `_checkentry` checks (for all manifest related revisions)
304 * all of `_checkentry` checks (for all manifest related revisions)
293 * nodes for subdirectory exists in the sub-directory manifest
305 * nodes for subdirectory exists in the sub-directory manifest
294 * each manifest entries have a file path
306 * each manifest entries have a file path
295 * each manifest node refered in mflinkrevs exist in the manifest log
307 * each manifest node refered in mflinkrevs exist in the manifest log
296
308
297 If tree manifest is in use and a matchers is specified, only the
309 If tree manifest is in use and a matchers is specified, only the
298 sub-directories matching it will be verified.
310 sub-directories matching it will be verified.
299
311
300 return a two level mapping:
312 return a two level mapping:
301 {"path" -> { filenode -> changelog-revision}}
313 {"path" -> { filenode -> changelog-revision}}
302
314
303 This mapping primarily contains entries for every files in the
315 This mapping primarily contains entries for every files in the
304 repository. In addition, when tree-manifest is used, it also contains
316 repository. In addition, when tree-manifest is used, it also contains
305 sub-directory entries.
317 sub-directory entries.
306
318
307 If a matcher is provided, only matching paths will be included.
319 If a matcher is provided, only matching paths will be included.
308 """
320 """
309 repo = self.repo
321 repo = self.repo
310 ui = self.ui
322 ui = self.ui
311 match = self.match
323 match = self.match
312 mfl = self.repo.manifestlog
324 mfl = self.repo.manifestlog
313 mf = mfl.getstorage(dir)
325 mf = mfl.getstorage(dir)
314
326
315 if not dir:
327 if not dir:
316 self.ui.status(_(b"checking manifests\n"))
328 self.ui.status(_(b"checking manifests\n"))
317
329
318 filenodes = {}
330 filenodes = {}
319 subdirnodes = {}
331 subdirnodes = {}
320 seen = {}
332 seen = {}
321 label = b"manifest"
333 label = b"manifest"
322 if dir:
334 if dir:
323 label = dir
335 label = dir
324 revlogfiles = mf.files()
336 revlogfiles = mf.files()
325 storefiles.difference_update(revlogfiles)
337 storefiles.difference_update(revlogfiles)
326 if subdirprogress: # should be true since we're in a subdirectory
338 if subdirprogress: # should be true since we're in a subdirectory
327 subdirprogress.increment()
339 subdirprogress.increment()
328 if self.refersmf:
340 if self.refersmf:
329 # Do not check manifest if there are only changelog entries with
341 # Do not check manifest if there are only changelog entries with
330 # null manifests.
342 # null manifests.
331 self._checkrevlog(mf._revlog, label, 0)
343 self._checkrevlog(mf._revlog, label, 0)
332 progress = ui.makeprogress(
344 progress = ui.makeprogress(
333 _(b'checking'), unit=_(b'manifests'), total=len(mf)
345 _(b'checking'), unit=_(b'manifests'), total=len(mf)
334 )
346 )
335 for i in mf:
347 for i in mf:
336 if not dir:
348 if not dir:
337 progress.update(i)
349 progress.update(i)
338 n = mf.node(i)
350 n = mf.node(i)
339 lr = self._checkentry(mf, i, n, seen, mflinkrevs.get(n, []), label)
351 lr = self._checkentry(mf, i, n, seen, mflinkrevs.get(n, []), label)
340 if n in mflinkrevs:
352 if n in mflinkrevs:
341 del mflinkrevs[n]
353 del mflinkrevs[n]
342 elif dir:
354 elif dir:
343 msg = _(b"%s not in parent-directory manifest") % short(n)
355 msg = _(b"%s not in parent-directory manifest") % short(n)
344 self._err(lr, msg, label)
356 self._err(lr, msg, label)
345 else:
357 else:
346 self._err(lr, _(b"%s not in changesets") % short(n), label)
358 self._err(lr, _(b"%s not in changesets") % short(n), label)
347
359
348 try:
360 try:
349 mfdelta = mfl.get(dir, n).readdelta(shallow=True)
361 mfdelta = mfl.get(dir, n).readdelta(shallow=True)
350 for f, fn, fl in mfdelta.iterentries():
362 for f, fn, fl in mfdelta.iterentries():
351 if not f:
363 if not f:
352 self._err(lr, _(b"entry without name in manifest"))
364 self._err(lr, _(b"entry without name in manifest"))
353 elif f == b"/dev/null": # ignore this in very old repos
365 elif f == b"/dev/null": # ignore this in very old repos
354 continue
366 continue
355 fullpath = dir + _normpath(f)
367 fullpath = dir + _normpath(f)
356 if fl == b't':
368 if fl == b't':
357 if not match.visitdir(fullpath):
369 if not match.visitdir(fullpath):
358 continue
370 continue
359 sdn = subdirnodes.setdefault(fullpath + b'/', {})
371 sdn = subdirnodes.setdefault(fullpath + b'/', {})
360 sdn.setdefault(fn, []).append(lr)
372 sdn.setdefault(fn, []).append(lr)
361 else:
373 else:
362 if not match(fullpath):
374 if not match(fullpath):
363 continue
375 continue
364 filenodes.setdefault(fullpath, {}).setdefault(fn, lr)
376 filenodes.setdefault(fullpath, {}).setdefault(fn, lr)
365 except Exception as inst:
377 except Exception as inst:
366 self._exc(lr, _(b"reading delta %s") % short(n), inst, label)
378 self._exc(lr, _(b"reading delta %s") % short(n), inst, label)
367 if self._level >= VERIFY_FULL:
379 if self._level >= VERIFY_FULL:
368 try:
380 try:
369 # Various issues can affect manifest. So we read each full
381 # Various issues can affect manifest. So we read each full
370 # text from storage. This triggers the checks from the core
382 # text from storage. This triggers the checks from the core
371 # code (eg: hash verification, filename are ordered, etc.)
383 # code (eg: hash verification, filename are ordered, etc.)
372 mfdelta = mfl.get(dir, n).read()
384 mfdelta = mfl.get(dir, n).read()
373 except Exception as inst:
385 except Exception as inst:
374 msg = _(b"reading full manifest %s") % short(n)
386 msg = _(b"reading full manifest %s") % short(n)
375 self._exc(lr, msg, inst, label)
387 self._exc(lr, msg, inst, label)
376
388
377 if not dir:
389 if not dir:
378 progress.complete()
390 progress.complete()
379
391
380 if self.havemf:
392 if self.havemf:
381 # since we delete entry in `mflinkrevs` during iteration, any
393 # since we delete entry in `mflinkrevs` during iteration, any
382 # remaining entries are "missing". We need to issue errors for them.
394 # remaining entries are "missing". We need to issue errors for them.
383 changesetpairs = [(c, m) for m in mflinkrevs for c in mflinkrevs[m]]
395 changesetpairs = [(c, m) for m in mflinkrevs for c in mflinkrevs[m]]
384 for c, m in sorted(changesetpairs):
396 for c, m in sorted(changesetpairs):
385 if dir:
397 if dir:
386 self._err(c, WARN_PARENT_DIR_UNKNOWN_REV % short(m), label)
398 self._err(c, WARN_PARENT_DIR_UNKNOWN_REV % short(m), label)
387 else:
399 else:
388 msg = _(b"changeset refers to unknown revision %s")
400 msg = _(b"changeset refers to unknown revision %s")
389 msg %= short(m)
401 msg %= short(m)
390 self._err(c, msg, label)
402 self._err(c, msg, label)
391
403
392 if not dir and subdirnodes:
404 if not dir and subdirnodes:
393 self.ui.status(_(b"checking directory manifests\n"))
405 self.ui.status(_(b"checking directory manifests\n"))
394 storefiles = set()
406 storefiles = set()
395 subdirs = set()
407 subdirs = set()
396 revlogv1 = self.revlogv1
408 revlogv1 = self.revlogv1
397 undecodable = []
409 undecodable = []
398 for t, f, size in repo.store.datafiles(undecodable=undecodable):
410 for t, f, size in repo.store.datafiles(undecodable=undecodable):
399 if (size > 0 or not revlogv1) and f.startswith(b'meta/'):
411 if (size > 0 or not revlogv1) and f.startswith(b'meta/'):
400 storefiles.add(_normpath(f))
412 storefiles.add(_normpath(f))
401 subdirs.add(os.path.dirname(f))
413 subdirs.add(os.path.dirname(f))
402 for f in undecodable:
414 for f in undecodable:
403 self._err(None, _(b"cannot decode filename '%s'") % f)
415 self._err(None, _(b"cannot decode filename '%s'") % f)
404 subdirprogress = ui.makeprogress(
416 subdirprogress = ui.makeprogress(
405 _(b'checking'), unit=_(b'manifests'), total=len(subdirs)
417 _(b'checking'), unit=_(b'manifests'), total=len(subdirs)
406 )
418 )
407
419
408 for subdir, linkrevs in subdirnodes.items():
420 for subdir, linkrevs in subdirnodes.items():
409 subdirfilenodes = self._verifymanifest(
421 subdirfilenodes = self._verifymanifest(
410 linkrevs, subdir, storefiles, subdirprogress
422 linkrevs, subdir, storefiles, subdirprogress
411 )
423 )
412 for f, onefilenodes in subdirfilenodes.items():
424 for f, onefilenodes in subdirfilenodes.items():
413 filenodes.setdefault(f, {}).update(onefilenodes)
425 filenodes.setdefault(f, {}).update(onefilenodes)
414
426
415 if not dir and subdirnodes:
427 if not dir and subdirnodes:
416 assert subdirprogress is not None # help pytype
428 assert subdirprogress is not None # help pytype
417 subdirprogress.complete()
429 subdirprogress.complete()
418 if self.warnorphanstorefiles:
430 if self.warnorphanstorefiles:
419 for f in sorted(storefiles):
431 for f in sorted(storefiles):
420 self._warn(_(b"warning: orphan data file '%s'") % f)
432 self._warn(_(b"warning: orphan data file '%s'") % f)
421
433
422 return filenodes
434 return filenodes
423
435
424 def _crosscheckfiles(self, filelinkrevs, filenodes):
436 def _crosscheckfiles(self, filelinkrevs, filenodes):
425 repo = self.repo
437 repo = self.repo
426 ui = self.ui
438 ui = self.ui
427 ui.status(_(b"crosschecking files in changesets and manifests\n"))
439 ui.status(_(b"crosschecking files in changesets and manifests\n"))
428
440
429 total = len(filelinkrevs) + len(filenodes)
441 total = len(filelinkrevs) + len(filenodes)
430 progress = ui.makeprogress(
442 progress = ui.makeprogress(
431 _(b'crosschecking'), unit=_(b'files'), total=total
443 _(b'crosschecking'), unit=_(b'files'), total=total
432 )
444 )
433 if self.havemf:
445 if self.havemf:
434 for f in sorted(filelinkrevs):
446 for f in sorted(filelinkrevs):
435 progress.increment()
447 progress.increment()
436 if f not in filenodes:
448 if f not in filenodes:
437 lr = filelinkrevs[f][0]
449 lr = filelinkrevs[f][0]
438 self._err(lr, _(b"in changeset but not in manifest"), f)
450 self._err(lr, _(b"in changeset but not in manifest"), f)
439
451
440 if self.havecl:
452 if self.havecl:
441 for f in sorted(filenodes):
453 for f in sorted(filenodes):
442 progress.increment()
454 progress.increment()
443 if f not in filelinkrevs:
455 if f not in filelinkrevs:
444 try:
456 try:
445 fl = repo.file(f)
457 fl = repo.file(f)
446 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
458 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
447 except Exception:
459 except Exception:
448 lr = None
460 lr = None
449 self._err(lr, _(b"in manifest but not in changeset"), f)
461 self._err(lr, _(b"in manifest but not in changeset"), f)
450
462
451 progress.complete()
463 progress.complete()
452
464
453 def _verifyfiles(self, filenodes, filelinkrevs):
465 def _verifyfiles(self, filenodes, filelinkrevs):
454 repo = self.repo
466 repo = self.repo
455 ui = self.ui
467 ui = self.ui
456 lrugetctx = self.lrugetctx
468 lrugetctx = self.lrugetctx
457 revlogv1 = self.revlogv1
469 revlogv1 = self.revlogv1
458 havemf = self.havemf
470 havemf = self.havemf
459 ui.status(_(b"checking files\n"))
471 ui.status(_(b"checking files\n"))
460
472
461 storefiles = set()
473 storefiles = set()
462 undecodable = []
474 undecodable = []
463 for t, f, size in repo.store.datafiles(undecodable=undecodable):
475 for t, f, size in repo.store.datafiles(undecodable=undecodable):
464 if (size > 0 or not revlogv1) and f.startswith(b'data/'):
476 if (size > 0 or not revlogv1) and f.startswith(b'data/'):
465 storefiles.add(_normpath(f))
477 storefiles.add(_normpath(f))
466 for f in undecodable:
478 for f in undecodable:
467 self._err(None, _(b"cannot decode filename '%s'") % f)
479 self._err(None, _(b"cannot decode filename '%s'") % f)
468
480
469 state = {
481 state = {
470 # TODO this assumes revlog storage for changelog.
482 # TODO this assumes revlog storage for changelog.
471 b'expectedversion': self.repo.changelog._format_version,
483 b'expectedversion': self.repo.changelog._format_version,
472 b'skipflags': self.skipflags,
484 b'skipflags': self.skipflags,
473 # experimental config: censor.policy
485 # experimental config: censor.policy
474 b'erroroncensored': ui.config(b'censor', b'policy') == b'abort',
486 b'erroroncensored': ui.config(b'censor', b'policy') == b'abort',
475 }
487 }
476
488
477 files = sorted(set(filenodes) | set(filelinkrevs))
489 files = sorted(set(filenodes) | set(filelinkrevs))
478 revisions = 0
490 revisions = 0
479 progress = ui.makeprogress(
491 progress = ui.makeprogress(
480 _(b'checking'), unit=_(b'files'), total=len(files)
492 _(b'checking'), unit=_(b'files'), total=len(files)
481 )
493 )
482 for i, f in enumerate(files):
494 for i, f in enumerate(files):
483 progress.update(i, item=f)
495 progress.update(i, item=f)
484 try:
496 try:
485 linkrevs = filelinkrevs[f]
497 linkrevs = filelinkrevs[f]
486 except KeyError:
498 except KeyError:
487 # in manifest but not in changelog
499 # in manifest but not in changelog
488 linkrevs = []
500 linkrevs = []
489
501
490 if linkrevs:
502 if linkrevs:
491 lr = linkrevs[0]
503 lr = linkrevs[0]
492 else:
504 else:
493 lr = None
505 lr = None
494
506
495 try:
507 try:
496 fl = repo.file(f)
508 fl = repo.file(f)
497 except error.StorageError as e:
509 except error.StorageError as e:
498 self._err(lr, _(b"broken revlog! (%s)") % e, f)
510 self._err(lr, _(b"broken revlog! (%s)") % e, f)
499 continue
511 continue
500
512
501 for ff in fl.files():
513 for ff in fl.files():
502 try:
514 try:
503 storefiles.remove(ff)
515 storefiles.remove(ff)
504 except KeyError:
516 except KeyError:
505 if self.warnorphanstorefiles:
517 if self.warnorphanstorefiles:
506 msg = _(b" warning: revlog '%s' not in fncache!")
518 msg = _(b" warning: revlog '%s' not in fncache!")
507 self._warn(msg % ff)
519 self._warn(msg % ff)
508 self.fncachewarned = True
520 self.fncachewarned = True
509
521
510 if not len(fl) and (self.havecl or self.havemf):
522 if not len(fl) and (self.havecl or self.havemf):
511 self._err(lr, _(b"empty or missing %s") % f)
523 self._err(lr, _(b"empty or missing %s") % f)
512 else:
524 else:
513 # Guard against implementations not setting this.
525 # Guard against implementations not setting this.
514 state[b'skipread'] = set()
526 state[b'skipread'] = set()
515 state[b'safe_renamed'] = set()
527 state[b'safe_renamed'] = set()
516
528
517 for problem in fl.verifyintegrity(state):
529 for problem in fl.verifyintegrity(state):
518 if problem.node is not None:
530 if problem.node is not None:
519 linkrev = fl.linkrev(fl.rev(problem.node))
531 linkrev = fl.linkrev(fl.rev(problem.node))
520 else:
532 else:
521 linkrev = None
533 linkrev = None
522
534
523 if problem.warning:
535 if problem.warning:
524 self._warn(problem.warning)
536 self._warn(problem.warning)
525 elif problem.error:
537 elif problem.error:
526 linkrev_msg = linkrev if linkrev is not None else lr
538 linkrev_msg = linkrev if linkrev is not None else lr
527 self._err(linkrev_msg, problem.error, f)
539 self._err(linkrev_msg, problem.error, f)
528 else:
540 else:
529 raise error.ProgrammingError(
541 raise error.ProgrammingError(
530 b'problem instance does not set warning or error '
542 b'problem instance does not set warning or error '
531 b'attribute: %s' % problem.msg
543 b'attribute: %s' % problem.msg
532 )
544 )
533
545
534 seen = {}
546 seen = {}
535 for i in fl:
547 for i in fl:
536 revisions += 1
548 revisions += 1
537 n = fl.node(i)
549 n = fl.node(i)
538 lr = self._checkentry(fl, i, n, seen, linkrevs, f)
550 lr = self._checkentry(fl, i, n, seen, linkrevs, f)
539 if f in filenodes:
551 if f in filenodes:
540 if havemf and n not in filenodes[f]:
552 if havemf and n not in filenodes[f]:
541 self._err(lr, _(b"%s not in manifests") % (short(n)), f)
553 self._err(lr, _(b"%s not in manifests") % (short(n)), f)
542 else:
554 else:
543 del filenodes[f][n]
555 del filenodes[f][n]
544
556
545 if n in state[b'skipread'] and n not in state[b'safe_renamed']:
557 if n in state[b'skipread'] and n not in state[b'safe_renamed']:
546 continue
558 continue
547
559
548 # check renames
560 # check renames
549 try:
561 try:
550 # This requires resolving fulltext (at least on revlogs,
562 # This requires resolving fulltext (at least on revlogs,
551 # though not with LFS revisions). We may want
563 # though not with LFS revisions). We may want
552 # ``verifyintegrity()`` to pass a set of nodes with
564 # ``verifyintegrity()`` to pass a set of nodes with
553 # rename metadata as an optimization.
565 # rename metadata as an optimization.
554 rp = fl.renamed(n)
566 rp = fl.renamed(n)
555 if rp:
567 if rp:
556 if lr is not None and ui.verbose:
568 if lr is not None and ui.verbose:
557 ctx = lrugetctx(lr)
569 ctx = lrugetctx(lr)
558 if not any(rp[0] in pctx for pctx in ctx.parents()):
570 if not any(rp[0] in pctx for pctx in ctx.parents()):
559 self._warn(WARN_UNKNOWN_COPY_SOURCE % (f, ctx))
571 self._warn(WARN_UNKNOWN_COPY_SOURCE % (f, ctx))
560 fl2 = repo.file(rp[0])
572 fl2 = repo.file(rp[0])
561 if not len(fl2):
573 if not len(fl2):
562 m = _(b"empty or missing copy source revlog %s:%s")
574 m = _(b"empty or missing copy source revlog %s:%s")
563 self._err(lr, m % (rp[0], short(rp[1])), f)
575 self._err(lr, m % (rp[0], short(rp[1])), f)
564 elif rp[1] == self.repo.nullid:
576 elif rp[1] == self.repo.nullid:
565 msg = WARN_NULLID_COPY_SOURCE
577 msg = WARN_NULLID_COPY_SOURCE
566 msg %= (f, lr, rp[0], short(rp[1]))
578 msg %= (f, lr, rp[0], short(rp[1]))
567 ui.note(msg)
579 ui.note(msg)
568 else:
580 else:
569 fl2.rev(rp[1])
581 fl2.rev(rp[1])
570 except Exception as inst:
582 except Exception as inst:
571 self._exc(
583 self._exc(
572 lr, _(b"checking rename of %s") % short(n), inst, f
584 lr, _(b"checking rename of %s") % short(n), inst, f
573 )
585 )
574
586
575 # cross-check
587 # cross-check
576 if f in filenodes:
588 if f in filenodes:
577 fns = [(v, k) for k, v in filenodes[f].items()]
589 fns = [(v, k) for k, v in filenodes[f].items()]
578 for lr, node in sorted(fns):
590 for lr, node in sorted(fns):
579 msg = _(b"manifest refers to unknown revision %s")
591 msg = _(b"manifest refers to unknown revision %s")
580 self._err(lr, msg % short(node), f)
592 self._err(lr, msg % short(node), f)
581 progress.complete()
593 progress.complete()
582
594
583 if self.warnorphanstorefiles:
595 if self.warnorphanstorefiles:
584 for f in sorted(storefiles):
596 for f in sorted(storefiles):
585 self._warn(_(b"warning: orphan data file '%s'") % f)
597 self._warn(_(b"warning: orphan data file '%s'") % f)
586
598
587 return len(files), revisions
599 return len(files), revisions
600
601 def _verify_dirstate(self):
602 """Check that the dirstate is consistent with the parent's manifest"""
603 repo = self.repo
604 ui = self.ui
605 ui.status(_(b"checking dirstate\n"))
606
607 parent1, parent2 = repo.dirstate.parents()
608 m1 = repo[parent1].manifest()
609 m2 = repo[parent2].manifest()
610 dirstate_errors = 0
611
612 is_narrow = requirements.NARROW_REQUIREMENT in repo.requirements
613 narrow_matcher = repo.narrowmatch() if is_narrow else None
614
615 for err in repo.dirstate.verify(m1, m2, narrow_matcher):
616 ui.error(err)
617 dirstate_errors += 1
618
619 if dirstate_errors:
620 self.errors += dirstate_errors
621 return dirstate_errors
@@ -1,198 +1,199 b''
1 #testcases obsstore-off obsstore-on
1 #testcases obsstore-off obsstore-on
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [extensions]
4 > [extensions]
5 > amend =
5 > amend =
6 > EOF
6 > EOF
7
7
8 #if obsstore-on
8 #if obsstore-on
9 $ cat << EOF >> $HGRCPATH
9 $ cat << EOF >> $HGRCPATH
10 > [experimental]
10 > [experimental]
11 > evolution.createmarkers = True
11 > evolution.createmarkers = True
12 > EOF
12 > EOF
13 #endif
13 #endif
14
14
15 Prepare parent repo
15 Prepare parent repo
16 -------------------
16 -------------------
17
17
18 $ hg init r
18 $ hg init r
19 $ cd r
19 $ cd r
20
20
21 $ echo a > a
21 $ echo a > a
22 $ hg ci -Am0
22 $ hg ci -Am0
23 adding a
23 adding a
24
24
25 Link first subrepo
25 Link first subrepo
26 ------------------
26 ------------------
27
27
28 $ echo 's = s' >> .hgsub
28 $ echo 's = s' >> .hgsub
29 $ hg add .hgsub
29 $ hg add .hgsub
30 $ hg init s
30 $ hg init s
31
31
32 amend without .hgsub
32 amend without .hgsub
33
33
34 $ hg amend s
34 $ hg amend s
35 abort: can't commit subrepos without .hgsub
35 abort: can't commit subrepos without .hgsub
36 [255]
36 [255]
37
37
38 amend with subrepo
38 amend with subrepo
39
39
40 $ hg amend
40 $ hg amend
41 saved backup bundle to * (glob) (obsstore-off !)
41 saved backup bundle to * (glob) (obsstore-off !)
42 $ hg status --change .
42 $ hg status --change .
43 A .hgsub
43 A .hgsub
44 A .hgsubstate
44 A .hgsubstate
45 A a
45 A a
46 $ cat .hgsubstate
46 $ cat .hgsubstate
47 0000000000000000000000000000000000000000 s
47 0000000000000000000000000000000000000000 s
48
48
49 Update subrepo
49 Update subrepo
50 --------------
50 --------------
51
51
52 add new commit to be amended
52 add new commit to be amended
53
53
54 $ echo a >> a
54 $ echo a >> a
55 $ hg ci -m1
55 $ hg ci -m1
56
56
57 amend with dirty subrepo
57 amend with dirty subrepo
58
58
59 $ echo a >> s/a
59 $ echo a >> s/a
60 $ hg add -R s
60 $ hg add -R s
61 adding s/a
61 adding s/a
62 $ hg amend
62 $ hg amend
63 abort: uncommitted changes in subrepository "s"
63 abort: uncommitted changes in subrepository "s"
64 (use --subrepos for recursive commit)
64 (use --subrepos for recursive commit)
65 [255]
65 [255]
66
66
67 amend with modified subrepo
67 amend with modified subrepo
68
68
69 $ hg ci -R s -m0
69 $ hg ci -R s -m0
70 $ hg amend
70 $ hg amend
71 saved backup bundle to * (glob) (obsstore-off !)
71 saved backup bundle to * (glob) (obsstore-off !)
72 $ hg status --change .
72 $ hg status --change .
73 M .hgsubstate
73 M .hgsubstate
74 M a
74 M a
75 $ cat .hgsubstate
75 $ cat .hgsubstate
76 f7b1eb17ad24730a1651fccd46c43826d1bbc2ac s
76 f7b1eb17ad24730a1651fccd46c43826d1bbc2ac s
77
77
78 revert subrepo change
78 revert subrepo change
79
79
80 $ hg up -R s -q null
80 $ hg up -R s -q null
81 $ hg amend
81 $ hg amend
82 saved backup bundle to * (glob) (obsstore-off !)
82 saved backup bundle to * (glob) (obsstore-off !)
83 $ hg status --change .
83 $ hg status --change .
84 M a
84 M a
85
85
86 Link another subrepo
86 Link another subrepo
87 --------------------
87 --------------------
88
88
89 add new commit to be amended
89 add new commit to be amended
90
90
91 $ echo b >> b
91 $ echo b >> b
92 $ hg ci -qAm2
92 $ hg ci -qAm2
93
93
94 also checks if non-subrepo change is included
94 also checks if non-subrepo change is included
95
95
96 $ echo a >> a
96 $ echo a >> a
97
97
98 amend with another subrepo
98 amend with another subrepo
99
99
100 $ hg init t
100 $ hg init t
101 $ echo b >> t/b
101 $ echo b >> t/b
102 $ hg ci -R t -Am0
102 $ hg ci -R t -Am0
103 adding b
103 adding b
104 $ echo 't = t' >> .hgsub
104 $ echo 't = t' >> .hgsub
105 $ hg amend
105 $ hg amend
106 saved backup bundle to * (glob) (obsstore-off !)
106 saved backup bundle to * (glob) (obsstore-off !)
107 $ hg status --change .
107 $ hg status --change .
108 M .hgsub
108 M .hgsub
109 M .hgsubstate
109 M .hgsubstate
110 M a
110 M a
111 A b
111 A b
112 $ cat .hgsubstate
112 $ cat .hgsubstate
113 0000000000000000000000000000000000000000 s
113 0000000000000000000000000000000000000000 s
114 bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
114 bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
115
115
116 Unlink one subrepo
116 Unlink one subrepo
117 ------------------
117 ------------------
118
118
119 add new commit to be amended
119 add new commit to be amended
120
120
121 $ echo a >> a
121 $ echo a >> a
122 $ hg ci -m3
122 $ hg ci -m3
123
123
124 $ echo 't = t' > .hgsub
124 $ echo 't = t' > .hgsub
125
125
126 --interactive won't silently ignore dirty subrepos
126 --interactive won't silently ignore dirty subrepos
127
127
128 $ echo modified > t/b
128 $ echo modified > t/b
129 $ hg amend --interactive --config ui.interactive=True
129 $ hg amend --interactive --config ui.interactive=True
130 abort: uncommitted changes in subrepository "t"
130 abort: uncommitted changes in subrepository "t"
131 [255]
131 [255]
132 $ hg amend --interactive --config ui.interactive=True --config ui.commitsubrepos=True
132 $ hg amend --interactive --config ui.interactive=True --config ui.commitsubrepos=True
133 abort: uncommitted changes in subrepository "t"
133 abort: uncommitted changes in subrepository "t"
134 [255]
134 [255]
135
135
136 $ hg -R t revert -q --all --no-backup
136 $ hg -R t revert -q --all --no-backup
137
137
138 amend with one subrepo dropped
138 amend with one subrepo dropped
139
139
140 $ hg amend
140 $ hg amend
141 saved backup bundle to * (glob) (obsstore-off !)
141 saved backup bundle to * (glob) (obsstore-off !)
142 $ hg status --change .
142 $ hg status --change .
143 M .hgsub
143 M .hgsub
144 M .hgsubstate
144 M .hgsubstate
145 M a
145 M a
146 $ cat .hgsubstate
146 $ cat .hgsubstate
147 bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
147 bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
148
148
149 Unlink subrepos completely
149 Unlink subrepos completely
150 --------------------------
150 --------------------------
151
151
152 add new commit to be amended
152 add new commit to be amended
153
153
154 $ echo a >> a
154 $ echo a >> a
155 $ hg ci -m3
155 $ hg ci -m3
156
156
157 amend with .hgsub removed
157 amend with .hgsub removed
158
158
159 $ hg rm .hgsub
159 $ hg rm .hgsub
160 $ hg amend
160 $ hg amend
161 saved backup bundle to * (glob) (obsstore-off !)
161 saved backup bundle to * (glob) (obsstore-off !)
162 $ hg status --change .
162 $ hg status --change .
163 M a
163 M a
164 R .hgsub
164 R .hgsub
165 R .hgsubstate
165 R .hgsubstate
166
166
167 broken repositories will refuse to push
167 broken repositories will refuse to push
168
168
169 #if obsstore-off
169 #if obsstore-off
170 $ hg up -q -C 2
170 $ hg up -q -C 2
171 #else
171 #else
172 $ hg up -q -C 6
172 $ hg up -q -C 6
173 #endif
173 #endif
174 $ echo c >> t/b
174 $ echo c >> t/b
175 $ hg amend -q -R t
175 $ hg amend -q -R t
176
176
177 $ hg init ../dest
177 $ hg init ../dest
178 $ hg init ../dest/t
178 $ hg init ../dest/t
179 $ hg init ../dest/s
179 $ hg init ../dest/s
180 $ hg push -q ../dest
180 $ hg push -q ../dest
181 abort: subrepo 't' is hidden in revision 04aa62396ec6 (obsstore-on !)
181 abort: subrepo 't' is hidden in revision 04aa62396ec6 (obsstore-on !)
182 abort: subrepo 't' not found in revision 04aa62396ec6 (obsstore-off !)
182 abort: subrepo 't' not found in revision 04aa62396ec6 (obsstore-off !)
183 [255]
183 [255]
184
184
185 ... unless forced
185 ... unless forced
186
186
187 $ hg push --force -q ../dest
187 $ hg push --force -q ../dest
188 $ hg verify -R ../dest
188 $ hg verify -R ../dest
189 checking changesets
189 checking changesets
190 checking manifests
190 checking manifests
191 crosschecking files in changesets and manifests
191 crosschecking files in changesets and manifests
192 checking files
192 checking files
193 checking dirstate
193 checked 5 changesets with 12 changes to 4 files
194 checked 5 changesets with 12 changes to 4 files
194 checking subrepo links
195 checking subrepo links
195 subrepo 't' not found in revision 04aa62396ec6
196 subrepo 't' not found in revision 04aa62396ec6
196 subrepo 't' not found in revision 6bce99600681
197 subrepo 't' not found in revision 6bce99600681
197
198
198 $ cd ..
199 $ cd ..
@@ -1,259 +1,260 b''
1 Create a repository:
1 Create a repository:
2
2
3 #if no-extraextensions
3 #if no-extraextensions
4 $ hg config
4 $ hg config
5 chgserver.idletimeout=60
5 chgserver.idletimeout=60
6 devel.all-warnings=true
6 devel.all-warnings=true
7 devel.default-date=0 0
7 devel.default-date=0 0
8 extensions.fsmonitor= (fsmonitor !)
8 extensions.fsmonitor= (fsmonitor !)
9 format.use-dirstate-v2=1 (dirstate-v2 !)
9 format.use-dirstate-v2=1 (dirstate-v2 !)
10 largefiles.usercache=$TESTTMP/.cache/largefiles
10 largefiles.usercache=$TESTTMP/.cache/largefiles
11 lfs.usercache=$TESTTMP/.cache/lfs
11 lfs.usercache=$TESTTMP/.cache/lfs
12 ui.slash=True
12 ui.slash=True
13 ui.interactive=False
13 ui.interactive=False
14 ui.detailed-exit-code=True
14 ui.detailed-exit-code=True
15 ui.merge=internal:merge
15 ui.merge=internal:merge
16 ui.mergemarkers=detailed
16 ui.mergemarkers=detailed
17 ui.promptecho=True
17 ui.promptecho=True
18 ui.ssh=* (glob)
18 ui.ssh=* (glob)
19 ui.timeout.warn=15
19 ui.timeout.warn=15
20 web.address=localhost
20 web.address=localhost
21 web\.ipv6=(?:True|False) (re)
21 web\.ipv6=(?:True|False) (re)
22 web.server-header=testing stub value
22 web.server-header=testing stub value
23 #endif
23 #endif
24
24
25 $ hg init t
25 $ hg init t
26 $ cd t
26 $ cd t
27
27
28 Prepare a changeset:
28 Prepare a changeset:
29
29
30 $ echo a > a
30 $ echo a > a
31 $ hg add a
31 $ hg add a
32
32
33 $ hg status
33 $ hg status
34 A a
34 A a
35
35
36 Writes to stdio succeed and fail appropriately
36 Writes to stdio succeed and fail appropriately
37
37
38 #if devfull
38 #if devfull
39 $ hg status 2>/dev/full
39 $ hg status 2>/dev/full
40 A a
40 A a
41
41
42 $ hg status >/dev/full
42 $ hg status >/dev/full
43 abort: No space left on device* (glob)
43 abort: No space left on device* (glob)
44 [255]
44 [255]
45 #endif
45 #endif
46
46
47 #if devfull
47 #if devfull
48 $ hg status >/dev/full 2>&1
48 $ hg status >/dev/full 2>&1
49 [255]
49 [255]
50
50
51 $ hg status ENOENT 2>/dev/full
51 $ hg status ENOENT 2>/dev/full
52 [255]
52 [255]
53 #endif
53 #endif
54
54
55 On Python 3, stdio may be None:
55 On Python 3, stdio may be None:
56
56
57 $ hg debuguiprompt --config ui.interactive=true 0<&-
57 $ hg debuguiprompt --config ui.interactive=true 0<&-
58 abort: Bad file descriptor (no-rhg !)
58 abort: Bad file descriptor (no-rhg !)
59 abort: response expected (rhg !)
59 abort: response expected (rhg !)
60 [255]
60 [255]
61 $ hg version -q 0<&-
61 $ hg version -q 0<&-
62 Mercurial Distributed SCM * (glob)
62 Mercurial Distributed SCM * (glob)
63
63
64 #if py3 no-rhg
64 #if py3 no-rhg
65 $ hg version -q 1>&-
65 $ hg version -q 1>&-
66 abort: Bad file descriptor
66 abort: Bad file descriptor
67 [255]
67 [255]
68 #else
68 #else
69 $ hg version -q 1>&-
69 $ hg version -q 1>&-
70 #endif
70 #endif
71 $ hg unknown -q 1>&-
71 $ hg unknown -q 1>&-
72 hg: unknown command 'unknown'
72 hg: unknown command 'unknown'
73 (did you mean debugknown?)
73 (did you mean debugknown?)
74 [10]
74 [10]
75
75
76 $ hg version -q 2>&-
76 $ hg version -q 2>&-
77 Mercurial Distributed SCM * (glob)
77 Mercurial Distributed SCM * (glob)
78 $ hg unknown -q 2>&-
78 $ hg unknown -q 2>&-
79 [10]
79 [10]
80
80
81 $ hg commit -m test
81 $ hg commit -m test
82
82
83 This command is ancient:
83 This command is ancient:
84
84
85 $ hg history
85 $ hg history
86 changeset: 0:acb14030fe0a
86 changeset: 0:acb14030fe0a
87 tag: tip
87 tag: tip
88 user: test
88 user: test
89 date: Thu Jan 01 00:00:00 1970 +0000
89 date: Thu Jan 01 00:00:00 1970 +0000
90 summary: test
90 summary: test
91
91
92
92
93 Verify that updating to revision 0 via commands.update() works properly
93 Verify that updating to revision 0 via commands.update() works properly
94
94
95 $ cat <<EOF > update_to_rev0.py
95 $ cat <<EOF > update_to_rev0.py
96 > from mercurial import commands, hg, ui as uimod
96 > from mercurial import commands, hg, ui as uimod
97 > myui = uimod.ui.load()
97 > myui = uimod.ui.load()
98 > repo = hg.repository(myui, path=b'.')
98 > repo = hg.repository(myui, path=b'.')
99 > commands.update(myui, repo, rev=b"0")
99 > commands.update(myui, repo, rev=b"0")
100 > EOF
100 > EOF
101 $ hg up null
101 $ hg up null
102 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
102 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
103 $ "$PYTHON" ./update_to_rev0.py
103 $ "$PYTHON" ./update_to_rev0.py
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
105 $ hg identify -n
105 $ hg identify -n
106 0
106 0
107
107
108
108
109 Poke around at hashes:
109 Poke around at hashes:
110
110
111 $ hg manifest --debug
111 $ hg manifest --debug
112 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
112 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
113
113
114 $ hg cat a
114 $ hg cat a
115 a
115 a
116
116
117 Verify should succeed:
117 Verify should succeed:
118
118
119 $ hg verify
119 $ hg verify
120 checking changesets
120 checking changesets
121 checking manifests
121 checking manifests
122 crosschecking files in changesets and manifests
122 crosschecking files in changesets and manifests
123 checking files
123 checking files
124 checking dirstate
124 checked 1 changesets with 1 changes to 1 files
125 checked 1 changesets with 1 changes to 1 files
125
126
126 Repository root:
127 Repository root:
127
128
128 $ hg root
129 $ hg root
129 $TESTTMP/t
130 $TESTTMP/t
130 $ hg log -l1 -T '{reporoot}\n'
131 $ hg log -l1 -T '{reporoot}\n'
131 $TESTTMP/t
132 $TESTTMP/t
132 $ hg root -Tjson | sed 's|\\\\|\\|g'
133 $ hg root -Tjson | sed 's|\\\\|\\|g'
133 [
134 [
134 {
135 {
135 "hgpath": "$TESTTMP/t/.hg",
136 "hgpath": "$TESTTMP/t/.hg",
136 "reporoot": "$TESTTMP/t",
137 "reporoot": "$TESTTMP/t",
137 "storepath": "$TESTTMP/t/.hg/store"
138 "storepath": "$TESTTMP/t/.hg/store"
138 }
139 }
139 ]
140 ]
140
141
141 At the end...
142 At the end...
142
143
143 $ cd ..
144 $ cd ..
144
145
145 Status message redirection:
146 Status message redirection:
146
147
147 $ hg init empty
148 $ hg init empty
148
149
149 status messages are sent to stdout by default:
150 status messages are sent to stdout by default:
150
151
151 $ hg outgoing -R t empty -Tjson 2>/dev/null
152 $ hg outgoing -R t empty -Tjson 2>/dev/null
152 comparing with empty
153 comparing with empty
153 searching for changes
154 searching for changes
154 [
155 [
155 {
156 {
156 "bookmarks": [],
157 "bookmarks": [],
157 "branch": "default",
158 "branch": "default",
158 "date": [0, 0],
159 "date": [0, 0],
159 "desc": "test",
160 "desc": "test",
160 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
161 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
161 "parents": ["0000000000000000000000000000000000000000"],
162 "parents": ["0000000000000000000000000000000000000000"],
162 "phase": "draft",
163 "phase": "draft",
163 "rev": 0,
164 "rev": 0,
164 "tags": ["tip"],
165 "tags": ["tip"],
165 "user": "test"
166 "user": "test"
166 }
167 }
167 ]
168 ]
168
169
169 which can be configured to send to stderr, so the output wouldn't be
170 which can be configured to send to stderr, so the output wouldn't be
170 interleaved:
171 interleaved:
171
172
172 $ cat <<'EOF' >> "$HGRCPATH"
173 $ cat <<'EOF' >> "$HGRCPATH"
173 > [ui]
174 > [ui]
174 > message-output = stderr
175 > message-output = stderr
175 > EOF
176 > EOF
176 $ hg outgoing -R t empty -Tjson 2>/dev/null
177 $ hg outgoing -R t empty -Tjson 2>/dev/null
177 [
178 [
178 {
179 {
179 "bookmarks": [],
180 "bookmarks": [],
180 "branch": "default",
181 "branch": "default",
181 "date": [0, 0],
182 "date": [0, 0],
182 "desc": "test",
183 "desc": "test",
183 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
184 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
184 "parents": ["0000000000000000000000000000000000000000"],
185 "parents": ["0000000000000000000000000000000000000000"],
185 "phase": "draft",
186 "phase": "draft",
186 "rev": 0,
187 "rev": 0,
187 "tags": ["tip"],
188 "tags": ["tip"],
188 "user": "test"
189 "user": "test"
189 }
190 }
190 ]
191 ]
191 $ hg outgoing -R t empty -Tjson >/dev/null
192 $ hg outgoing -R t empty -Tjson >/dev/null
192 comparing with empty
193 comparing with empty
193 searching for changes
194 searching for changes
194
195
195 this option should be turned off by HGPLAIN= since it may break scripting use:
196 this option should be turned off by HGPLAIN= since it may break scripting use:
196
197
197 $ HGPLAIN= hg outgoing -R t empty -Tjson 2>/dev/null
198 $ HGPLAIN= hg outgoing -R t empty -Tjson 2>/dev/null
198 comparing with empty
199 comparing with empty
199 searching for changes
200 searching for changes
200 [
201 [
201 {
202 {
202 "bookmarks": [],
203 "bookmarks": [],
203 "branch": "default",
204 "branch": "default",
204 "date": [0, 0],
205 "date": [0, 0],
205 "desc": "test",
206 "desc": "test",
206 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
207 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
207 "parents": ["0000000000000000000000000000000000000000"],
208 "parents": ["0000000000000000000000000000000000000000"],
208 "phase": "draft",
209 "phase": "draft",
209 "rev": 0,
210 "rev": 0,
210 "tags": ["tip"],
211 "tags": ["tip"],
211 "user": "test"
212 "user": "test"
212 }
213 }
213 ]
214 ]
214
215
215 but still overridden by --config:
216 but still overridden by --config:
216
217
217 $ HGPLAIN= hg outgoing -R t empty -Tjson --config ui.message-output=stderr \
218 $ HGPLAIN= hg outgoing -R t empty -Tjson --config ui.message-output=stderr \
218 > 2>/dev/null
219 > 2>/dev/null
219 [
220 [
220 {
221 {
221 "bookmarks": [],
222 "bookmarks": [],
222 "branch": "default",
223 "branch": "default",
223 "date": [0, 0],
224 "date": [0, 0],
224 "desc": "test",
225 "desc": "test",
225 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
226 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
226 "parents": ["0000000000000000000000000000000000000000"],
227 "parents": ["0000000000000000000000000000000000000000"],
227 "phase": "draft",
228 "phase": "draft",
228 "rev": 0,
229 "rev": 0,
229 "tags": ["tip"],
230 "tags": ["tip"],
230 "user": "test"
231 "user": "test"
231 }
232 }
232 ]
233 ]
233
234
234 Invalid ui.message-output option:
235 Invalid ui.message-output option:
235
236
236 $ hg log -R t --config ui.message-output=bad
237 $ hg log -R t --config ui.message-output=bad
237 abort: invalid ui.message-output destination: bad
238 abort: invalid ui.message-output destination: bad
238 [255]
239 [255]
239
240
240 Underlying message streams should be updated when ui.fout/ferr are set:
241 Underlying message streams should be updated when ui.fout/ferr are set:
241
242
242 $ cat <<'EOF' > capui.py
243 $ cat <<'EOF' > capui.py
243 > import io
244 > import io
244 > from mercurial import registrar
245 > from mercurial import registrar
245 > cmdtable = {}
246 > cmdtable = {}
246 > command = registrar.command(cmdtable)
247 > command = registrar.command(cmdtable)
247 > @command(b'capui', norepo=True)
248 > @command(b'capui', norepo=True)
248 > def capui(ui):
249 > def capui(ui):
249 > out = ui.fout
250 > out = ui.fout
250 > ui.fout = io.BytesIO()
251 > ui.fout = io.BytesIO()
251 > ui.status(b'status\n')
252 > ui.status(b'status\n')
252 > ui.ferr = io.BytesIO()
253 > ui.ferr = io.BytesIO()
253 > ui.warn(b'warn\n')
254 > ui.warn(b'warn\n')
254 > out.write(b'stdout: %s' % ui.fout.getvalue())
255 > out.write(b'stdout: %s' % ui.fout.getvalue())
255 > out.write(b'stderr: %s' % ui.ferr.getvalue())
256 > out.write(b'stderr: %s' % ui.ferr.getvalue())
256 > EOF
257 > EOF
257 $ hg --config extensions.capui=capui.py --config ui.message-output=stdio capui
258 $ hg --config extensions.capui=capui.py --config ui.message-output=stdio capui
258 stdout: status
259 stdout: status
259 stderr: warn
260 stderr: warn
@@ -1,531 +1,532 b''
1 #require no-reposimplestore
1 #require no-reposimplestore
2 #testcases revlogv1 revlogv2
2 #testcases revlogv1 revlogv2
3
3
4 #if revlogv2
4 #if revlogv2
5
5
6 $ cat >> $HGRCPATH <<EOF
6 $ cat >> $HGRCPATH <<EOF
7 > [experimental]
7 > [experimental]
8 > revlogv2=enable-unstable-format-and-corrupt-my-data
8 > revlogv2=enable-unstable-format-and-corrupt-my-data
9 > EOF
9 > EOF
10
10
11 #endif
11 #endif
12
12
13 $ cp $HGRCPATH $HGRCPATH.orig
13 $ cp $HGRCPATH $HGRCPATH.orig
14
14
15 Create repo with unimpeachable content
15 Create repo with unimpeachable content
16
16
17 $ hg init r
17 $ hg init r
18 $ cd r
18 $ cd r
19 $ echo 'Initially untainted file' > target
19 $ echo 'Initially untainted file' > target
20 $ echo 'Normal file here' > bystander
20 $ echo 'Normal file here' > bystander
21 $ hg add target bystander
21 $ hg add target bystander
22 $ hg ci -m init
22 $ hg ci -m init
23
23
24 Clone repo so we can test pull later
24 Clone repo so we can test pull later
25
25
26 $ cd ..
26 $ cd ..
27 $ hg clone r rpull
27 $ hg clone r rpull
28 updating to branch default
28 updating to branch default
29 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 $ cd r
30 $ cd r
31
31
32 Introduce content which will ultimately require censorship. Name the first
32 Introduce content which will ultimately require censorship. Name the first
33 censored node C1, second C2, and so on
33 censored node C1, second C2, and so on
34
34
35 $ echo 'Tainted file' > target
35 $ echo 'Tainted file' > target
36 $ echo 'Passwords: hunter2' >> target
36 $ echo 'Passwords: hunter2' >> target
37 $ hg ci -m taint target
37 $ hg ci -m taint target
38 $ C1=`hg id --debug -i`
38 $ C1=`hg id --debug -i`
39
39
40 $ echo 'hunter3' >> target
40 $ echo 'hunter3' >> target
41 $ echo 'Normal file v2' > bystander
41 $ echo 'Normal file v2' > bystander
42 $ hg ci -m moretaint target bystander
42 $ hg ci -m moretaint target bystander
43 $ C2=`hg id --debug -i`
43 $ C2=`hg id --debug -i`
44
44
45 Add a new sanitized versions to correct our mistake. Name the first head H1,
45 Add a new sanitized versions to correct our mistake. Name the first head H1,
46 the second head H2, and so on
46 the second head H2, and so on
47
47
48 $ echo 'Tainted file is now sanitized' > target
48 $ echo 'Tainted file is now sanitized' > target
49 $ hg ci -m sanitized target
49 $ hg ci -m sanitized target
50 $ H1=`hg id --debug -i`
50 $ H1=`hg id --debug -i`
51
51
52 $ hg update -r $C2
52 $ hg update -r $C2
53 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 $ echo 'Tainted file now super sanitized' > target
54 $ echo 'Tainted file now super sanitized' > target
55 $ hg ci -m 'super sanitized' target
55 $ hg ci -m 'super sanitized' target
56 created new head
56 created new head
57 $ H2=`hg id --debug -i`
57 $ H2=`hg id --debug -i`
58
58
59 Verify target contents before censorship at each revision
59 Verify target contents before censorship at each revision
60
60
61 $ hg cat -r $H1 target | head -n 10
61 $ hg cat -r $H1 target | head -n 10
62 Tainted file is now sanitized
62 Tainted file is now sanitized
63 $ hg cat -r $H2 target | head -n 10
63 $ hg cat -r $H2 target | head -n 10
64 Tainted file now super sanitized
64 Tainted file now super sanitized
65 $ hg cat -r $C2 target | head -n 10
65 $ hg cat -r $C2 target | head -n 10
66 Tainted file
66 Tainted file
67 Passwords: hunter2
67 Passwords: hunter2
68 hunter3
68 hunter3
69 $ hg cat -r $C1 target | head -n 10
69 $ hg cat -r $C1 target | head -n 10
70 Tainted file
70 Tainted file
71 Passwords: hunter2
71 Passwords: hunter2
72 $ hg cat -r 0 target | head -n 10
72 $ hg cat -r 0 target | head -n 10
73 Initially untainted file
73 Initially untainted file
74
74
75 Censor revision with 2 offenses
75 Censor revision with 2 offenses
76
76
77 (this also tests file pattern matching: path relative to cwd case)
77 (this also tests file pattern matching: path relative to cwd case)
78
78
79 $ mkdir -p foo/bar/baz
79 $ mkdir -p foo/bar/baz
80 $ hg --config extensions.censor= --cwd foo/bar/baz censor -r $C2 -t "remove password" ../../../target
80 $ hg --config extensions.censor= --cwd foo/bar/baz censor -r $C2 -t "remove password" ../../../target
81 $ hg cat -r $H1 target | head -n 10
81 $ hg cat -r $H1 target | head -n 10
82 Tainted file is now sanitized
82 Tainted file is now sanitized
83 $ hg cat -r $H2 target | head -n 10
83 $ hg cat -r $H2 target | head -n 10
84 Tainted file now super sanitized
84 Tainted file now super sanitized
85 $ hg cat -r $C2 target | head -n 10
85 $ hg cat -r $C2 target | head -n 10
86 abort: censored node: 1e0247a9a4b7
86 abort: censored node: 1e0247a9a4b7
87 (set censor.policy to ignore errors)
87 (set censor.policy to ignore errors)
88 $ hg cat -r $C1 target | head -n 10
88 $ hg cat -r $C1 target | head -n 10
89 Tainted file
89 Tainted file
90 Passwords: hunter2
90 Passwords: hunter2
91 $ hg cat -r 0 target | head -n 10
91 $ hg cat -r 0 target | head -n 10
92 Initially untainted file
92 Initially untainted file
93
93
94 Censor revision with 1 offense
94 Censor revision with 1 offense
95
95
96 (this also tests file pattern matching: with 'path:' scheme)
96 (this also tests file pattern matching: with 'path:' scheme)
97
97
98 $ hg --config extensions.censor= --cwd foo/bar/baz censor -r $C1 path:target
98 $ hg --config extensions.censor= --cwd foo/bar/baz censor -r $C1 path:target
99 $ hg cat -r $H1 target | head -n 10
99 $ hg cat -r $H1 target | head -n 10
100 Tainted file is now sanitized
100 Tainted file is now sanitized
101 $ hg cat -r $H2 target | head -n 10
101 $ hg cat -r $H2 target | head -n 10
102 Tainted file now super sanitized
102 Tainted file now super sanitized
103 $ hg cat -r $C2 target | head -n 10
103 $ hg cat -r $C2 target | head -n 10
104 abort: censored node: 1e0247a9a4b7
104 abort: censored node: 1e0247a9a4b7
105 (set censor.policy to ignore errors)
105 (set censor.policy to ignore errors)
106 $ hg cat -r $C1 target | head -n 10
106 $ hg cat -r $C1 target | head -n 10
107 abort: censored node: 613bc869fceb
107 abort: censored node: 613bc869fceb
108 (set censor.policy to ignore errors)
108 (set censor.policy to ignore errors)
109 $ hg cat -r 0 target | head -n 10
109 $ hg cat -r 0 target | head -n 10
110 Initially untainted file
110 Initially untainted file
111
111
112 Can only checkout target at uncensored revisions, -X is workaround for --all
112 Can only checkout target at uncensored revisions, -X is workaround for --all
113
113
114 $ hg revert -r $C2 target | head -n 10
114 $ hg revert -r $C2 target | head -n 10
115 abort: censored node: 1e0247a9a4b7
115 abort: censored node: 1e0247a9a4b7
116 (set censor.policy to ignore errors)
116 (set censor.policy to ignore errors)
117 $ hg revert -r $C1 target | head -n 10
117 $ hg revert -r $C1 target | head -n 10
118 abort: censored node: 613bc869fceb
118 abort: censored node: 613bc869fceb
119 (set censor.policy to ignore errors)
119 (set censor.policy to ignore errors)
120 $ hg revert -r $C1 --all
120 $ hg revert -r $C1 --all
121 reverting bystander
121 reverting bystander
122 reverting target
122 reverting target
123 abort: censored node: 613bc869fceb
123 abort: censored node: 613bc869fceb
124 (set censor.policy to ignore errors)
124 (set censor.policy to ignore errors)
125 [255]
125 [255]
126 $ hg revert -r $C1 --all -X target
126 $ hg revert -r $C1 --all -X target
127 $ cat target | head -n 10
127 $ cat target | head -n 10
128 Tainted file now super sanitized
128 Tainted file now super sanitized
129 $ hg revert -r 0 --all
129 $ hg revert -r 0 --all
130 reverting target
130 reverting target
131 $ cat target | head -n 10
131 $ cat target | head -n 10
132 Initially untainted file
132 Initially untainted file
133 $ hg revert -r $H2 --all
133 $ hg revert -r $H2 --all
134 reverting bystander
134 reverting bystander
135 reverting target
135 reverting target
136 $ cat target | head -n 10
136 $ cat target | head -n 10
137 Tainted file now super sanitized
137 Tainted file now super sanitized
138
138
139 Uncensored file can be viewed at any revision
139 Uncensored file can be viewed at any revision
140
140
141 $ hg cat -r $H1 bystander | head -n 10
141 $ hg cat -r $H1 bystander | head -n 10
142 Normal file v2
142 Normal file v2
143 $ hg cat -r $C2 bystander | head -n 10
143 $ hg cat -r $C2 bystander | head -n 10
144 Normal file v2
144 Normal file v2
145 $ hg cat -r $C1 bystander | head -n 10
145 $ hg cat -r $C1 bystander | head -n 10
146 Normal file here
146 Normal file here
147 $ hg cat -r 0 bystander | head -n 10
147 $ hg cat -r 0 bystander | head -n 10
148 Normal file here
148 Normal file here
149
149
150 Can update to children of censored revision
150 Can update to children of censored revision
151
151
152 $ hg update -r $H1
152 $ hg update -r $H1
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 $ cat target | head -n 10
154 $ cat target | head -n 10
155 Tainted file is now sanitized
155 Tainted file is now sanitized
156 $ hg update -r $H2
156 $ hg update -r $H2
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ cat target | head -n 10
158 $ cat target | head -n 10
159 Tainted file now super sanitized
159 Tainted file now super sanitized
160
160
161 Set censor policy to abort in trusted $HGRC so hg verify fails
161 Set censor policy to abort in trusted $HGRC so hg verify fails
162
162
163 $ cp $HGRCPATH.orig $HGRCPATH
163 $ cp $HGRCPATH.orig $HGRCPATH
164 $ cat >> $HGRCPATH <<EOF
164 $ cat >> $HGRCPATH <<EOF
165 > [censor]
165 > [censor]
166 > policy = abort
166 > policy = abort
167 > EOF
167 > EOF
168
168
169 Repo fails verification due to censorship
169 Repo fails verification due to censorship
170
170
171 $ hg verify
171 $ hg verify
172 checking changesets
172 checking changesets
173 checking manifests
173 checking manifests
174 crosschecking files in changesets and manifests
174 crosschecking files in changesets and manifests
175 checking files
175 checking files
176 target@1: censored file data
176 target@1: censored file data
177 target@2: censored file data
177 target@2: censored file data
178 not checking dirstate because of previous errors
178 checked 5 changesets with 7 changes to 2 files
179 checked 5 changesets with 7 changes to 2 files
179 2 integrity errors encountered!
180 2 integrity errors encountered!
180 (first damaged changeset appears to be 1)
181 (first damaged changeset appears to be 1)
181 [1]
182 [1]
182
183
183 Cannot update to revision with censored data
184 Cannot update to revision with censored data
184
185
185 $ hg update -r $C2
186 $ hg update -r $C2
186 abort: censored node: 1e0247a9a4b7
187 abort: censored node: 1e0247a9a4b7
187 (set censor.policy to ignore errors)
188 (set censor.policy to ignore errors)
188 [255]
189 [255]
189 $ hg update -r $C1
190 $ hg update -r $C1
190 abort: censored node: 613bc869fceb
191 abort: censored node: 613bc869fceb
191 (set censor.policy to ignore errors)
192 (set censor.policy to ignore errors)
192 [255]
193 [255]
193 $ hg update -r 0
194 $ hg update -r 0
194 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 $ hg update -r $H2
196 $ hg update -r $H2
196 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
197
198
198 Set censor policy to ignore in trusted $HGRC so hg verify passes
199 Set censor policy to ignore in trusted $HGRC so hg verify passes
199
200
200 $ cp $HGRCPATH.orig $HGRCPATH
201 $ cp $HGRCPATH.orig $HGRCPATH
201 $ cat >> $HGRCPATH <<EOF
202 $ cat >> $HGRCPATH <<EOF
202 > [censor]
203 > [censor]
203 > policy = ignore
204 > policy = ignore
204 > EOF
205 > EOF
205
206
206 Repo passes verification with warnings with explicit config
207 Repo passes verification with warnings with explicit config
207
208
208 $ hg verify -q
209 $ hg verify -q
209
210
210 May update to revision with censored data with explicit config
211 May update to revision with censored data with explicit config
211
212
212 $ hg update -r $C2
213 $ hg update -r $C2
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 $ cat target | head -n 10
215 $ cat target | head -n 10
215 $ hg update -r $C1
216 $ hg update -r $C1
216 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 $ cat target | head -n 10
218 $ cat target | head -n 10
218 $ hg update -r 0
219 $ hg update -r 0
219 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 $ cat target | head -n 10
221 $ cat target | head -n 10
221 Initially untainted file
222 Initially untainted file
222 $ hg update -r $H2
223 $ hg update -r $H2
223 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 $ cat target | head -n 10
225 $ cat target | head -n 10
225 Tainted file now super sanitized
226 Tainted file now super sanitized
226
227
227 Can merge in revision with censored data. Test requires one branch of history
228 Can merge in revision with censored data. Test requires one branch of history
228 with the file censored, but we can't censor at a head, so advance H1.
229 with the file censored, but we can't censor at a head, so advance H1.
229
230
230 $ hg update -r $H1
231 $ hg update -r $H1
231 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 $ C3=$H1
233 $ C3=$H1
233 $ echo 'advanced head H1' > target
234 $ echo 'advanced head H1' > target
234 $ hg ci -m 'advance head H1' target
235 $ hg ci -m 'advance head H1' target
235 $ H1=`hg id --debug -i`
236 $ H1=`hg id --debug -i`
236 $ hg --config extensions.censor= censor -r $C3 target
237 $ hg --config extensions.censor= censor -r $C3 target
237 $ hg update -r $H2
238 $ hg update -r $H2
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 $ hg merge -r $C3
240 $ hg merge -r $C3
240 merging target
241 merging target
241 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
242 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
242 (branch merge, don't forget to commit)
243 (branch merge, don't forget to commit)
243
244
244 Revisions present in repository heads may not be censored
245 Revisions present in repository heads may not be censored
245
246
246 $ hg update -C -r $H2
247 $ hg update -C -r $H2
247 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 $ hg --config extensions.censor= censor -r $H2 target
249 $ hg --config extensions.censor= censor -r $H2 target
249 abort: cannot censor file in heads (78a8fc215e79)
250 abort: cannot censor file in heads (78a8fc215e79)
250 (clean/delete and commit first)
251 (clean/delete and commit first)
251 [255]
252 [255]
252 $ echo 'twiddling thumbs' > bystander
253 $ echo 'twiddling thumbs' > bystander
253 $ hg ci -m 'bystander commit'
254 $ hg ci -m 'bystander commit'
254 $ H2=`hg id --debug -i`
255 $ H2=`hg id --debug -i`
255 $ hg --config extensions.censor= censor -r "$H2^" target
256 $ hg --config extensions.censor= censor -r "$H2^" target
256 abort: cannot censor file in heads (efbe78065929)
257 abort: cannot censor file in heads (efbe78065929)
257 (clean/delete and commit first)
258 (clean/delete and commit first)
258 [255]
259 [255]
259
260
260 Cannot censor working directory
261 Cannot censor working directory
261
262
262 $ echo 'seriously no passwords' > target
263 $ echo 'seriously no passwords' > target
263 $ hg ci -m 'extend second head arbitrarily' target
264 $ hg ci -m 'extend second head arbitrarily' target
264 $ H2=`hg id --debug -i`
265 $ H2=`hg id --debug -i`
265 $ hg update -r "$H2^"
266 $ hg update -r "$H2^"
266 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 $ hg --config extensions.censor= censor -r . target
268 $ hg --config extensions.censor= censor -r . target
268 abort: cannot censor working directory
269 abort: cannot censor working directory
269 (clean/delete/update first)
270 (clean/delete/update first)
270 [255]
271 [255]
271 $ hg update -r $H2
272 $ hg update -r $H2
272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273
274
274 Can re-add file after being deleted + censored
275 Can re-add file after being deleted + censored
275
276
276 $ C4=$H2
277 $ C4=$H2
277 $ hg rm target
278 $ hg rm target
278 $ hg ci -m 'delete target so it may be censored'
279 $ hg ci -m 'delete target so it may be censored'
279 $ H2=`hg id --debug -i`
280 $ H2=`hg id --debug -i`
280 $ hg --config extensions.censor= censor -r $C4 target
281 $ hg --config extensions.censor= censor -r $C4 target
281 $ hg cat -r $C4 target | head -n 10
282 $ hg cat -r $C4 target | head -n 10
282 $ hg cat -r "$H2^^" target | head -n 10
283 $ hg cat -r "$H2^^" target | head -n 10
283 Tainted file now super sanitized
284 Tainted file now super sanitized
284 $ echo 'fresh start' > target
285 $ echo 'fresh start' > target
285 $ hg add target
286 $ hg add target
286 $ hg ci -m reincarnated target
287 $ hg ci -m reincarnated target
287 $ H2=`hg id --debug -i`
288 $ H2=`hg id --debug -i`
288 $ hg cat -r $H2 target | head -n 10
289 $ hg cat -r $H2 target | head -n 10
289 fresh start
290 fresh start
290 $ hg cat -r "$H2^" target | head -n 10
291 $ hg cat -r "$H2^" target | head -n 10
291 target: no such file in rev 452ec1762369
292 target: no such file in rev 452ec1762369
292 $ hg cat -r $C4 target | head -n 10
293 $ hg cat -r $C4 target | head -n 10
293 $ hg cat -r "$H2^^^" target | head -n 10
294 $ hg cat -r "$H2^^^" target | head -n 10
294 Tainted file now super sanitized
295 Tainted file now super sanitized
295
296
296 Can censor after revlog has expanded to no longer permit inline storage
297 Can censor after revlog has expanded to no longer permit inline storage
297
298
298 $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
299 $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
299 > do
300 > do
300 > echo "Password: hunter$x" >> target
301 > echo "Password: hunter$x" >> target
301 > done
302 > done
302 $ hg ci -m 'add 100k passwords'
303 $ hg ci -m 'add 100k passwords'
303 $ H2=`hg id --debug -i`
304 $ H2=`hg id --debug -i`
304 $ C5=$H2
305 $ C5=$H2
305 $ hg revert -r "$H2^" target
306 $ hg revert -r "$H2^" target
306 $ hg ci -m 'cleaned 100k passwords'
307 $ hg ci -m 'cleaned 100k passwords'
307 $ H2=`hg id --debug -i`
308 $ H2=`hg id --debug -i`
308 $ hg --config extensions.censor= censor -r $C5 target
309 $ hg --config extensions.censor= censor -r $C5 target
309 $ hg cat -r $C5 target | head -n 10
310 $ hg cat -r $C5 target | head -n 10
310 $ hg cat -r $H2 target | head -n 10
311 $ hg cat -r $H2 target | head -n 10
311 fresh start
312 fresh start
312
313
313 Repo with censored nodes can be cloned and cloned nodes are censored
314 Repo with censored nodes can be cloned and cloned nodes are censored
314
315
315 $ cd ..
316 $ cd ..
316 $ hg clone r rclone
317 $ hg clone r rclone
317 updating to branch default
318 updating to branch default
318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 $ cd rclone
320 $ cd rclone
320 $ hg cat -r $H1 target | head -n 10
321 $ hg cat -r $H1 target | head -n 10
321 advanced head H1
322 advanced head H1
322 $ hg cat -r $H2~5 target | head -n 10
323 $ hg cat -r $H2~5 target | head -n 10
323 Tainted file now super sanitized
324 Tainted file now super sanitized
324 $ hg cat -r $C2 target | head -n 10
325 $ hg cat -r $C2 target | head -n 10
325 $ hg cat -r $C1 target | head -n 10
326 $ hg cat -r $C1 target | head -n 10
326 $ hg cat -r 0 target | head -n 10
327 $ hg cat -r 0 target | head -n 10
327 Initially untainted file
328 Initially untainted file
328 $ hg verify -q
329 $ hg verify -q
329
330
330 Repo cloned before tainted content introduced can pull censored nodes
331 Repo cloned before tainted content introduced can pull censored nodes
331
332
332 $ cd ../rpull
333 $ cd ../rpull
333 $ hg cat -r tip target | head -n 10
334 $ hg cat -r tip target | head -n 10
334 Initially untainted file
335 Initially untainted file
335 $ hg verify -q
336 $ hg verify -q
336 $ hg pull -r $H1 -r $H2
337 $ hg pull -r $H1 -r $H2
337 pulling from $TESTTMP/r
338 pulling from $TESTTMP/r
338 searching for changes
339 searching for changes
339 adding changesets
340 adding changesets
340 adding manifests
341 adding manifests
341 adding file changes
342 adding file changes
342 added 11 changesets with 11 changes to 2 files (+1 heads)
343 added 11 changesets with 11 changes to 2 files (+1 heads)
343 new changesets 186fb27560c3:683e4645fded
344 new changesets 186fb27560c3:683e4645fded
344 (run 'hg heads' to see heads, 'hg merge' to merge)
345 (run 'hg heads' to see heads, 'hg merge' to merge)
345 $ hg update 4
346 $ hg update 4
346 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 $ cat target | head -n 10
348 $ cat target | head -n 10
348 Tainted file now super sanitized
349 Tainted file now super sanitized
349 $ hg cat -r $H1 target | head -n 10
350 $ hg cat -r $H1 target | head -n 10
350 advanced head H1
351 advanced head H1
351 $ hg cat -r $H2~5 target | head -n 10
352 $ hg cat -r $H2~5 target | head -n 10
352 Tainted file now super sanitized
353 Tainted file now super sanitized
353 $ hg cat -r $C2 target | head -n 10
354 $ hg cat -r $C2 target | head -n 10
354 $ hg cat -r $C1 target | head -n 10
355 $ hg cat -r $C1 target | head -n 10
355 $ hg cat -r 0 target | head -n 10
356 $ hg cat -r 0 target | head -n 10
356 Initially untainted file
357 Initially untainted file
357 $ hg verify -q
358 $ hg verify -q
358
359
359 Censored nodes can be pushed if they censor previously unexchanged nodes
360 Censored nodes can be pushed if they censor previously unexchanged nodes
360
361
361 $ echo 'Passwords: hunter2hunter2' > target
362 $ echo 'Passwords: hunter2hunter2' > target
362 $ hg ci -m 're-add password from clone' target
363 $ hg ci -m 're-add password from clone' target
363 created new head
364 created new head
364 $ H3=`hg id --debug -i`
365 $ H3=`hg id --debug -i`
365 $ REV=$H3
366 $ REV=$H3
366 $ echo 'Re-sanitized; nothing to see here' > target
367 $ echo 'Re-sanitized; nothing to see here' > target
367 $ hg ci -m 're-sanitized' target
368 $ hg ci -m 're-sanitized' target
368 $ H2=`hg id --debug -i`
369 $ H2=`hg id --debug -i`
369 $ CLEANREV=$H2
370 $ CLEANREV=$H2
370 $ hg cat -r $REV target | head -n 10
371 $ hg cat -r $REV target | head -n 10
371 Passwords: hunter2hunter2
372 Passwords: hunter2hunter2
372 $ hg --config extensions.censor= censor -r $REV target
373 $ hg --config extensions.censor= censor -r $REV target
373 $ hg cat -r $REV target | head -n 10
374 $ hg cat -r $REV target | head -n 10
374 $ hg cat -r $CLEANREV target | head -n 10
375 $ hg cat -r $CLEANREV target | head -n 10
375 Re-sanitized; nothing to see here
376 Re-sanitized; nothing to see here
376 $ hg push -f -r $H2
377 $ hg push -f -r $H2
377 pushing to $TESTTMP/r
378 pushing to $TESTTMP/r
378 searching for changes
379 searching for changes
379 adding changesets
380 adding changesets
380 adding manifests
381 adding manifests
381 adding file changes
382 adding file changes
382 added 2 changesets with 2 changes to 1 files (+1 heads)
383 added 2 changesets with 2 changes to 1 files (+1 heads)
383
384
384 $ cd ../r
385 $ cd ../r
385 $ hg cat -r $REV target | head -n 10
386 $ hg cat -r $REV target | head -n 10
386 $ hg cat -r $CLEANREV target | head -n 10
387 $ hg cat -r $CLEANREV target | head -n 10
387 Re-sanitized; nothing to see here
388 Re-sanitized; nothing to see here
388 $ hg update $CLEANREV
389 $ hg update $CLEANREV
389 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
390 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
390 $ cat target | head -n 10
391 $ cat target | head -n 10
391 Re-sanitized; nothing to see here
392 Re-sanitized; nothing to see here
392
393
393 Censored nodes can be bundled up and unbundled in another repo
394 Censored nodes can be bundled up and unbundled in another repo
394
395
395 $ hg bundle --base 0 ../pwbundle
396 $ hg bundle --base 0 ../pwbundle
396 13 changesets found
397 13 changesets found
397 $ cd ../rclone
398 $ cd ../rclone
398 $ hg unbundle ../pwbundle
399 $ hg unbundle ../pwbundle
399 adding changesets
400 adding changesets
400 adding manifests
401 adding manifests
401 adding file changes
402 adding file changes
402 added 2 changesets with 2 changes to 2 files (+1 heads)
403 added 2 changesets with 2 changes to 2 files (+1 heads)
403 new changesets 075be80ac777:dcbaf17bf3a1 (2 drafts)
404 new changesets 075be80ac777:dcbaf17bf3a1 (2 drafts)
404 (run 'hg heads .' to see heads, 'hg merge' to merge)
405 (run 'hg heads .' to see heads, 'hg merge' to merge)
405 $ hg cat -r $REV target | head -n 10
406 $ hg cat -r $REV target | head -n 10
406 $ hg cat -r $CLEANREV target | head -n 10
407 $ hg cat -r $CLEANREV target | head -n 10
407 Re-sanitized; nothing to see here
408 Re-sanitized; nothing to see here
408 $ hg update $CLEANREV
409 $ hg update $CLEANREV
409 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 $ cat target | head -n 10
411 $ cat target | head -n 10
411 Re-sanitized; nothing to see here
412 Re-sanitized; nothing to see here
412 $ hg verify -q
413 $ hg verify -q
413
414
414 Grepping only warns, doesn't error out
415 Grepping only warns, doesn't error out
415
416
416 $ cd ../rpull
417 $ cd ../rpull
417 $ hg grep 'Normal file'
418 $ hg grep 'Normal file'
418 bystander:Normal file v2
419 bystander:Normal file v2
419 $ hg grep nothing
420 $ hg grep nothing
420 target:Re-sanitized; nothing to see here
421 target:Re-sanitized; nothing to see here
421 $ hg grep --diff 'Normal file'
422 $ hg grep --diff 'Normal file'
422 cannot search in censored file: target:7
423 cannot search in censored file: target:7
423 cannot search in censored file: target:10
424 cannot search in censored file: target:10
424 cannot search in censored file: target:12
425 cannot search in censored file: target:12
425 bystander:6:-:Normal file v2
426 bystander:6:-:Normal file v2
426 cannot search in censored file: target:1
427 cannot search in censored file: target:1
427 cannot search in censored file: target:2
428 cannot search in censored file: target:2
428 cannot search in censored file: target:3
429 cannot search in censored file: target:3
429 bystander:2:-:Normal file here
430 bystander:2:-:Normal file here
430 bystander:2:+:Normal file v2
431 bystander:2:+:Normal file v2
431 bystander:0:+:Normal file here
432 bystander:0:+:Normal file here
432 $ hg grep --diff nothing
433 $ hg grep --diff nothing
433 cannot search in censored file: target:7
434 cannot search in censored file: target:7
434 cannot search in censored file: target:10
435 cannot search in censored file: target:10
435 cannot search in censored file: target:12
436 cannot search in censored file: target:12
436 target:13:+:Re-sanitized; nothing to see here
437 target:13:+:Re-sanitized; nothing to see here
437 cannot search in censored file: target:1
438 cannot search in censored file: target:1
438 cannot search in censored file: target:2
439 cannot search in censored file: target:2
439 cannot search in censored file: target:3
440 cannot search in censored file: target:3
440
441
441 Censored nodes can be imported on top of censored nodes, consecutively
442 Censored nodes can be imported on top of censored nodes, consecutively
442
443
443 $ hg init ../rimport
444 $ hg init ../rimport
444 $ hg bundle --base 1 ../rimport/splitbundle
445 $ hg bundle --base 1 ../rimport/splitbundle
445 12 changesets found
446 12 changesets found
446 $ cd ../rimport
447 $ cd ../rimport
447 $ hg pull -r $H1 -r $H2 ../r
448 $ hg pull -r $H1 -r $H2 ../r
448 pulling from ../r
449 pulling from ../r
449 adding changesets
450 adding changesets
450 adding manifests
451 adding manifests
451 adding file changes
452 adding file changes
452 added 8 changesets with 10 changes to 2 files (+1 heads)
453 added 8 changesets with 10 changes to 2 files (+1 heads)
453 new changesets e97f55b2665a:dcbaf17bf3a1
454 new changesets e97f55b2665a:dcbaf17bf3a1
454 (run 'hg heads' to see heads, 'hg merge' to merge)
455 (run 'hg heads' to see heads, 'hg merge' to merge)
455 $ hg unbundle splitbundle
456 $ hg unbundle splitbundle
456 adding changesets
457 adding changesets
457 adding manifests
458 adding manifests
458 adding file changes
459 adding file changes
459 added 6 changesets with 5 changes to 2 files (+1 heads)
460 added 6 changesets with 5 changes to 2 files (+1 heads)
460 new changesets efbe78065929:683e4645fded (6 drafts)
461 new changesets efbe78065929:683e4645fded (6 drafts)
461 (run 'hg heads .' to see heads, 'hg merge' to merge)
462 (run 'hg heads .' to see heads, 'hg merge' to merge)
462 $ hg update $H2
463 $ hg update $H2
463 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
464 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
464 $ cat target | head -n 10
465 $ cat target | head -n 10
465 Re-sanitized; nothing to see here
466 Re-sanitized; nothing to see here
466 $ hg verify -q
467 $ hg verify -q
467 $ cd ../r
468 $ cd ../r
468
469
469 Can import bundle where first revision of a file is censored
470 Can import bundle where first revision of a file is censored
470
471
471 $ hg init ../rinit
472 $ hg init ../rinit
472 $ hg --config extensions.censor= censor -r 0 target
473 $ hg --config extensions.censor= censor -r 0 target
473 $ hg bundle -r 0 --base null ../rinit/initbundle
474 $ hg bundle -r 0 --base null ../rinit/initbundle
474 1 changesets found
475 1 changesets found
475 $ cd ../rinit
476 $ cd ../rinit
476 $ hg unbundle initbundle
477 $ hg unbundle initbundle
477 adding changesets
478 adding changesets
478 adding manifests
479 adding manifests
479 adding file changes
480 adding file changes
480 added 1 changesets with 2 changes to 2 files
481 added 1 changesets with 2 changes to 2 files
481 new changesets e97f55b2665a (1 drafts)
482 new changesets e97f55b2665a (1 drafts)
482 (run 'hg update' to get a working copy)
483 (run 'hg update' to get a working copy)
483 $ hg cat -r 0 target | head -n 10
484 $ hg cat -r 0 target | head -n 10
484
485
485 #if revlogv2
486 #if revlogv2
486
487
487 Testing feature that does not work in revlog v1
488 Testing feature that does not work in revlog v1
488 ===============================================
489 ===============================================
489
490
490 Censoring a revision that is used as delta base
491 Censoring a revision that is used as delta base
491 -----------------------------------------------
492 -----------------------------------------------
492
493
493 $ cd ..
494 $ cd ..
494 $ hg init censor-with-delta
495 $ hg init censor-with-delta
495 $ cd censor-with-delta
496 $ cd censor-with-delta
496 $ echo root > target
497 $ echo root > target
497 $ hg add target
498 $ hg add target
498 $ hg commit -m root
499 $ hg commit -m root
499 $ B0=`hg id --debug -i`
500 $ B0=`hg id --debug -i`
500 $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
501 $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
501 > do
502 > do
502 > echo "Password: hunter$x" >> target
503 > echo "Password: hunter$x" >> target
503 > done
504 > done
504 $ hg ci -m 'write a long file'
505 $ hg ci -m 'write a long file'
505 $ B1=`hg id --debug -i`
506 $ B1=`hg id --debug -i`
506 $ echo 'small change (should create a delta)' >> target
507 $ echo 'small change (should create a delta)' >> target
507 $ hg ci -m 'create a delta over the password'
508 $ hg ci -m 'create a delta over the password'
508 (should show that the last revision is a delta, not a snapshot)
509 (should show that the last revision is a delta, not a snapshot)
509 $ B2=`hg id --debug -i`
510 $ B2=`hg id --debug -i`
510
511
511 Make sure the last revision is a delta against the revision we will censor
512 Make sure the last revision is a delta against the revision we will censor
512
513
513 $ hg debugdeltachain target -T '{rev} {chainid} {chainlen} {prevrev}\n'
514 $ hg debugdeltachain target -T '{rev} {chainid} {chainlen} {prevrev}\n'
514 0 1 1 -1
515 0 1 1 -1
515 1 2 1 -1
516 1 2 1 -1
516 2 2 2 1
517 2 2 2 1
517
518
518 Censor the file
519 Censor the file
519
520
520 $ hg cat -r $B1 target | wc -l
521 $ hg cat -r $B1 target | wc -l
521 *50002 (re)
522 *50002 (re)
522 $ hg --config extensions.censor= censor -r $B1 target
523 $ hg --config extensions.censor= censor -r $B1 target
523 $ hg cat -r $B1 target | wc -l
524 $ hg cat -r $B1 target | wc -l
524 *0 (re)
525 *0 (re)
525
526
526 Check the children is fine
527 Check the children is fine
527
528
528 $ hg cat -r $B2 target | wc -l
529 $ hg cat -r $B2 target | wc -l
529 *50003 (re)
530 *50003 (re)
530
531
531 #endif
532 #endif
@@ -1,1173 +1,1175 b''
1 #require no-rhg no-chg
1 #require no-rhg no-chg
2
2
3 XXX-RHG this test hangs if `hg` is really `rhg`. This was hidden by the use of
3 XXX-RHG this test hangs if `hg` is really `rhg`. This was hidden by the use of
4 `alias hg=rhg` by run-tests.py. With such alias removed, this test is revealed
4 `alias hg=rhg` by run-tests.py. With such alias removed, this test is revealed
5 buggy. This need to be resolved sooner than later.
5 buggy. This need to be resolved sooner than later.
6
6
7 XXX-CHG this test hangs if `hg` is really `chg`. This was hidden by the use of
7 XXX-CHG this test hangs if `hg` is really `chg`. This was hidden by the use of
8 `alias hg=chg` by run-tests.py. With such alias removed, this test is revealed
8 `alias hg=chg` by run-tests.py. With such alias removed, this test is revealed
9 buggy. This need to be resolved sooner than later.
9 buggy. This need to be resolved sooner than later.
10
10
11 #if windows
11 #if windows
12 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
12 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
13 #else
13 #else
14 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
14 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
15 #endif
15 #endif
16 $ export PYTHONPATH
16 $ export PYTHONPATH
17
17
18 typical client does not want echo-back messages, so test without it:
18 typical client does not want echo-back messages, so test without it:
19
19
20 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
20 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
21 $ mv $HGRCPATH.new $HGRCPATH
21 $ mv $HGRCPATH.new $HGRCPATH
22
22
23 $ hg init repo
23 $ hg init repo
24 $ cd repo
24 $ cd repo
25
25
26 >>> import os
26 >>> import os
27 >>> import sys
27 >>> import sys
28 >>> from hgclient import bprint, check, readchannel, runcommand
28 >>> from hgclient import bprint, check, readchannel, runcommand
29 >>> @check
29 >>> @check
30 ... def hellomessage(server):
30 ... def hellomessage(server):
31 ... ch, data = readchannel(server)
31 ... ch, data = readchannel(server)
32 ... bprint(b'%c, %r' % (ch, data))
32 ... bprint(b'%c, %r' % (ch, data))
33 ... # run an arbitrary command to make sure the next thing the server
33 ... # run an arbitrary command to make sure the next thing the server
34 ... # sends isn't part of the hello message
34 ... # sends isn't part of the hello message
35 ... runcommand(server, [b'id'])
35 ... runcommand(server, [b'id'])
36 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
36 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
37 *** runcommand id
37 *** runcommand id
38 000000000000 tip
38 000000000000 tip
39
39
40 >>> from hgclient import check
40 >>> from hgclient import check
41 >>> @check
41 >>> @check
42 ... def unknowncommand(server):
42 ... def unknowncommand(server):
43 ... server.stdin.write(b'unknowncommand\n')
43 ... server.stdin.write(b'unknowncommand\n')
44 abort: unknown command unknowncommand
44 abort: unknown command unknowncommand
45
45
46 >>> from hgclient import check, readchannel, runcommand
46 >>> from hgclient import check, readchannel, runcommand
47 >>> @check
47 >>> @check
48 ... def checkruncommand(server):
48 ... def checkruncommand(server):
49 ... # hello block
49 ... # hello block
50 ... readchannel(server)
50 ... readchannel(server)
51 ...
51 ...
52 ... # no args
52 ... # no args
53 ... runcommand(server, [])
53 ... runcommand(server, [])
54 ...
54 ...
55 ... # global options
55 ... # global options
56 ... runcommand(server, [b'id', b'--quiet'])
56 ... runcommand(server, [b'id', b'--quiet'])
57 ...
57 ...
58 ... # make sure global options don't stick through requests
58 ... # make sure global options don't stick through requests
59 ... runcommand(server, [b'id'])
59 ... runcommand(server, [b'id'])
60 ...
60 ...
61 ... # --config
61 ... # --config
62 ... runcommand(server, [b'id', b'--config', b'ui.quiet=True'])
62 ... runcommand(server, [b'id', b'--config', b'ui.quiet=True'])
63 ...
63 ...
64 ... # make sure --config doesn't stick
64 ... # make sure --config doesn't stick
65 ... runcommand(server, [b'id'])
65 ... runcommand(server, [b'id'])
66 ...
66 ...
67 ... # negative return code should be masked
67 ... # negative return code should be masked
68 ... runcommand(server, [b'id', b'-runknown'])
68 ... runcommand(server, [b'id', b'-runknown'])
69 *** runcommand
69 *** runcommand
70 Mercurial Distributed SCM
70 Mercurial Distributed SCM
71
71
72 basic commands:
72 basic commands:
73
73
74 add add the specified files on the next commit
74 add add the specified files on the next commit
75 annotate show changeset information by line for each file
75 annotate show changeset information by line for each file
76 clone make a copy of an existing repository
76 clone make a copy of an existing repository
77 commit commit the specified files or all outstanding changes
77 commit commit the specified files or all outstanding changes
78 diff diff repository (or selected files)
78 diff diff repository (or selected files)
79 export dump the header and diffs for one or more changesets
79 export dump the header and diffs for one or more changesets
80 forget forget the specified files on the next commit
80 forget forget the specified files on the next commit
81 init create a new repository in the given directory
81 init create a new repository in the given directory
82 log show revision history of entire repository or files
82 log show revision history of entire repository or files
83 merge merge another revision into working directory
83 merge merge another revision into working directory
84 pull pull changes from the specified source
84 pull pull changes from the specified source
85 push push changes to the specified destination
85 push push changes to the specified destination
86 remove remove the specified files on the next commit
86 remove remove the specified files on the next commit
87 serve start stand-alone webserver
87 serve start stand-alone webserver
88 status show changed files in the working directory
88 status show changed files in the working directory
89 summary summarize working directory state
89 summary summarize working directory state
90 update update working directory (or switch revisions)
90 update update working directory (or switch revisions)
91
91
92 (use 'hg help' for the full list of commands or 'hg -v' for details)
92 (use 'hg help' for the full list of commands or 'hg -v' for details)
93 *** runcommand id --quiet
93 *** runcommand id --quiet
94 000000000000
94 000000000000
95 *** runcommand id
95 *** runcommand id
96 000000000000 tip
96 000000000000 tip
97 *** runcommand id --config ui.quiet=True
97 *** runcommand id --config ui.quiet=True
98 000000000000
98 000000000000
99 *** runcommand id
99 *** runcommand id
100 000000000000 tip
100 000000000000 tip
101 *** runcommand id -runknown
101 *** runcommand id -runknown
102 abort: unknown revision 'unknown'
102 abort: unknown revision 'unknown'
103 [10]
103 [10]
104
104
105 >>> from hgclient import bprint, check, readchannel
105 >>> from hgclient import bprint, check, readchannel
106 >>> @check
106 >>> @check
107 ... def inputeof(server):
107 ... def inputeof(server):
108 ... readchannel(server)
108 ... readchannel(server)
109 ... server.stdin.write(b'runcommand\n')
109 ... server.stdin.write(b'runcommand\n')
110 ... # close stdin while server is waiting for input
110 ... # close stdin while server is waiting for input
111 ... server.stdin.close()
111 ... server.stdin.close()
112 ...
112 ...
113 ... # server exits with 1 if the pipe closed while reading the command
113 ... # server exits with 1 if the pipe closed while reading the command
114 ... bprint(b'server exit code =', b'%d' % server.wait())
114 ... bprint(b'server exit code =', b'%d' % server.wait())
115 server exit code = 1
115 server exit code = 1
116
116
117 >>> from hgclient import check, readchannel, runcommand, stringio
117 >>> from hgclient import check, readchannel, runcommand, stringio
118 >>> @check
118 >>> @check
119 ... def serverinput(server):
119 ... def serverinput(server):
120 ... readchannel(server)
120 ... readchannel(server)
121 ...
121 ...
122 ... patch = b"""
122 ... patch = b"""
123 ... # HG changeset patch
123 ... # HG changeset patch
124 ... # User test
124 ... # User test
125 ... # Date 0 0
125 ... # Date 0 0
126 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
126 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
127 ... # Parent 0000000000000000000000000000000000000000
127 ... # Parent 0000000000000000000000000000000000000000
128 ... 1
128 ... 1
129 ...
129 ...
130 ... diff -r 000000000000 -r c103a3dec114 a
130 ... diff -r 000000000000 -r c103a3dec114 a
131 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
132 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
132 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
133 ... @@ -0,0 +1,1 @@
133 ... @@ -0,0 +1,1 @@
134 ... +1
134 ... +1
135 ... """
135 ... """
136 ...
136 ...
137 ... runcommand(server, [b'import', b'-'], input=stringio(patch))
137 ... runcommand(server, [b'import', b'-'], input=stringio(patch))
138 ... runcommand(server, [b'log'])
138 ... runcommand(server, [b'log'])
139 *** runcommand import -
139 *** runcommand import -
140 applying patch from stdin
140 applying patch from stdin
141 *** runcommand log
141 *** runcommand log
142 changeset: 0:eff892de26ec
142 changeset: 0:eff892de26ec
143 tag: tip
143 tag: tip
144 user: test
144 user: test
145 date: Thu Jan 01 00:00:00 1970 +0000
145 date: Thu Jan 01 00:00:00 1970 +0000
146 summary: 1
146 summary: 1
147
147
148
148
149 check strict parsing of early options:
149 check strict parsing of early options:
150
150
151 >>> import os
151 >>> import os
152 >>> from hgclient import check, readchannel, runcommand
152 >>> from hgclient import check, readchannel, runcommand
153 >>> os.environ['HGPLAIN'] = '+strictflags'
153 >>> os.environ['HGPLAIN'] = '+strictflags'
154 >>> @check
154 >>> @check
155 ... def cwd(server):
155 ... def cwd(server):
156 ... readchannel(server)
156 ... readchannel(server)
157 ... runcommand(server, [b'log', b'-b', b'--config=alias.log=!echo pwned',
157 ... runcommand(server, [b'log', b'-b', b'--config=alias.log=!echo pwned',
158 ... b'default'])
158 ... b'default'])
159 *** runcommand log -b --config=alias.log=!echo pwned default
159 *** runcommand log -b --config=alias.log=!echo pwned default
160 abort: unknown revision '--config=alias.log=!echo pwned'
160 abort: unknown revision '--config=alias.log=!echo pwned'
161 [10]
161 [10]
162
162
163 check that "histedit --commands=-" can read rules from the input channel:
163 check that "histedit --commands=-" can read rules from the input channel:
164
164
165 >>> from hgclient import check, readchannel, runcommand, stringio
165 >>> from hgclient import check, readchannel, runcommand, stringio
166 >>> @check
166 >>> @check
167 ... def serverinput(server):
167 ... def serverinput(server):
168 ... readchannel(server)
168 ... readchannel(server)
169 ... rules = b'pick eff892de26ec\n'
169 ... rules = b'pick eff892de26ec\n'
170 ... runcommand(server, [b'histedit', b'0', b'--commands=-',
170 ... runcommand(server, [b'histedit', b'0', b'--commands=-',
171 ... b'--config', b'extensions.histedit='],
171 ... b'--config', b'extensions.histedit='],
172 ... input=stringio(rules))
172 ... input=stringio(rules))
173 *** runcommand histedit 0 --commands=- --config extensions.histedit=
173 *** runcommand histedit 0 --commands=- --config extensions.histedit=
174
174
175 check that --cwd doesn't persist between requests:
175 check that --cwd doesn't persist between requests:
176
176
177 $ mkdir foo
177 $ mkdir foo
178 $ touch foo/bar
178 $ touch foo/bar
179 >>> from hgclient import check, readchannel, runcommand
179 >>> from hgclient import check, readchannel, runcommand
180 >>> @check
180 >>> @check
181 ... def cwd(server):
181 ... def cwd(server):
182 ... readchannel(server)
182 ... readchannel(server)
183 ... runcommand(server, [b'--cwd', b'foo', b'st', b'bar'])
183 ... runcommand(server, [b'--cwd', b'foo', b'st', b'bar'])
184 ... runcommand(server, [b'st', b'foo/bar'])
184 ... runcommand(server, [b'st', b'foo/bar'])
185 *** runcommand --cwd foo st bar
185 *** runcommand --cwd foo st bar
186 ? bar
186 ? bar
187 *** runcommand st foo/bar
187 *** runcommand st foo/bar
188 ? foo/bar
188 ? foo/bar
189
189
190 $ rm foo/bar
190 $ rm foo/bar
191
191
192
192
193 check that local configs for the cached repo aren't inherited when -R is used:
193 check that local configs for the cached repo aren't inherited when -R is used:
194
194
195 $ cat <<EOF >> .hg/hgrc
195 $ cat <<EOF >> .hg/hgrc
196 > [ui]
196 > [ui]
197 > foo = bar
197 > foo = bar
198 > EOF
198 > EOF
199
199
200 #if no-extraextensions
200 #if no-extraextensions
201
201
202 >>> from hgclient import check, readchannel, runcommand, sep
202 >>> from hgclient import check, readchannel, runcommand, sep
203 >>> @check
203 >>> @check
204 ... def localhgrc(server):
204 ... def localhgrc(server):
205 ... readchannel(server)
205 ... readchannel(server)
206 ...
206 ...
207 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
207 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
208 ... # show it
208 ... # show it
209 ... runcommand(server, [b'showconfig'], outfilter=sep)
209 ... runcommand(server, [b'showconfig'], outfilter=sep)
210 ...
210 ...
211 ... # but not for this repo
211 ... # but not for this repo
212 ... runcommand(server, [b'init', b'foo'])
212 ... runcommand(server, [b'init', b'foo'])
213 ... runcommand(server, [b'-R', b'foo', b'showconfig', b'ui', b'defaults'])
213 ... runcommand(server, [b'-R', b'foo', b'showconfig', b'ui', b'defaults'])
214 *** runcommand showconfig
214 *** runcommand showconfig
215 bundle.mainreporoot=$TESTTMP/repo
215 bundle.mainreporoot=$TESTTMP/repo
216 chgserver.idletimeout=60
216 chgserver.idletimeout=60
217 devel.all-warnings=true
217 devel.all-warnings=true
218 devel.default-date=0 0
218 devel.default-date=0 0
219 extensions.fsmonitor= (fsmonitor !)
219 extensions.fsmonitor= (fsmonitor !)
220 format.use-dirstate-v2=1 (dirstate-v2 !)
220 format.use-dirstate-v2=1 (dirstate-v2 !)
221 largefiles.usercache=$TESTTMP/.cache/largefiles
221 largefiles.usercache=$TESTTMP/.cache/largefiles
222 lfs.usercache=$TESTTMP/.cache/lfs
222 lfs.usercache=$TESTTMP/.cache/lfs
223 ui.slash=True
223 ui.slash=True
224 ui.interactive=False
224 ui.interactive=False
225 ui.detailed-exit-code=True
225 ui.detailed-exit-code=True
226 ui.merge=internal:merge
226 ui.merge=internal:merge
227 ui.mergemarkers=detailed
227 ui.mergemarkers=detailed
228 ui.ssh=* (glob)
228 ui.ssh=* (glob)
229 ui.timeout.warn=15
229 ui.timeout.warn=15
230 ui.foo=bar
230 ui.foo=bar
231 ui.nontty=true
231 ui.nontty=true
232 web.address=localhost
232 web.address=localhost
233 web\.ipv6=(?:True|False) (re)
233 web\.ipv6=(?:True|False) (re)
234 web.server-header=testing stub value
234 web.server-header=testing stub value
235 *** runcommand init foo
235 *** runcommand init foo
236 *** runcommand -R foo showconfig ui defaults
236 *** runcommand -R foo showconfig ui defaults
237 ui.slash=True
237 ui.slash=True
238 ui.interactive=False
238 ui.interactive=False
239 ui.detailed-exit-code=True
239 ui.detailed-exit-code=True
240 ui.merge=internal:merge
240 ui.merge=internal:merge
241 ui.mergemarkers=detailed
241 ui.mergemarkers=detailed
242 ui.ssh=* (glob)
242 ui.ssh=* (glob)
243 ui.timeout.warn=15
243 ui.timeout.warn=15
244 ui.nontty=true
244 ui.nontty=true
245 #endif
245 #endif
246
246
247 $ rm -R foo
247 $ rm -R foo
248
248
249 #if windows
249 #if windows
250 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
250 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
251 #else
251 #else
252 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
252 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
253 #endif
253 #endif
254
254
255 $ cat <<EOF > hook.py
255 $ cat <<EOF > hook.py
256 > import sys
256 > import sys
257 > from hgclient import bprint
257 > from hgclient import bprint
258 > def hook(**args):
258 > def hook(**args):
259 > bprint(b'hook talking')
259 > bprint(b'hook talking')
260 > bprint(b'now try to read something: %r' % sys.stdin.read())
260 > bprint(b'now try to read something: %r' % sys.stdin.read())
261 > EOF
261 > EOF
262
262
263 >>> from hgclient import check, readchannel, runcommand, stringio
263 >>> from hgclient import check, readchannel, runcommand, stringio
264 >>> @check
264 >>> @check
265 ... def hookoutput(server):
265 ... def hookoutput(server):
266 ... readchannel(server)
266 ... readchannel(server)
267 ... runcommand(server, [b'--config',
267 ... runcommand(server, [b'--config',
268 ... b'hooks.pre-identify=python:hook.hook',
268 ... b'hooks.pre-identify=python:hook.hook',
269 ... b'id'],
269 ... b'id'],
270 ... input=stringio(b'some input'))
270 ... input=stringio(b'some input'))
271 *** runcommand --config hooks.pre-identify=python:hook.hook id
271 *** runcommand --config hooks.pre-identify=python:hook.hook id
272 eff892de26ec tip
272 eff892de26ec tip
273 hook talking
273 hook talking
274 now try to read something: ''
274 now try to read something: ''
275
275
276 Clean hook cached version
276 Clean hook cached version
277 $ rm hook.py*
277 $ rm hook.py*
278 $ rm -Rf __pycache__
278 $ rm -Rf __pycache__
279
279
280 $ echo a >> a
280 $ echo a >> a
281 >>> import os
281 >>> import os
282 >>> from hgclient import check, readchannel, runcommand
282 >>> from hgclient import check, readchannel, runcommand
283 >>> @check
283 >>> @check
284 ... def outsidechanges(server):
284 ... def outsidechanges(server):
285 ... readchannel(server)
285 ... readchannel(server)
286 ... runcommand(server, [b'status'])
286 ... runcommand(server, [b'status'])
287 ... os.system('hg ci -Am2')
287 ... os.system('hg ci -Am2')
288 ... runcommand(server, [b'tip'])
288 ... runcommand(server, [b'tip'])
289 ... runcommand(server, [b'status'])
289 ... runcommand(server, [b'status'])
290 *** runcommand status
290 *** runcommand status
291 M a
291 M a
292 *** runcommand tip
292 *** runcommand tip
293 changeset: 1:d3a0a68be6de
293 changeset: 1:d3a0a68be6de
294 tag: tip
294 tag: tip
295 user: test
295 user: test
296 date: Thu Jan 01 00:00:00 1970 +0000
296 date: Thu Jan 01 00:00:00 1970 +0000
297 summary: 2
297 summary: 2
298
298
299 *** runcommand status
299 *** runcommand status
300
300
301 >>> import os
301 >>> import os
302 >>> from hgclient import bprint, check, readchannel, runcommand
302 >>> from hgclient import bprint, check, readchannel, runcommand
303 >>> @check
303 >>> @check
304 ... def bookmarks(server):
304 ... def bookmarks(server):
305 ... readchannel(server)
305 ... readchannel(server)
306 ... runcommand(server, [b'bookmarks'])
306 ... runcommand(server, [b'bookmarks'])
307 ...
307 ...
308 ... # changes .hg/bookmarks
308 ... # changes .hg/bookmarks
309 ... os.system('hg bookmark -i bm1')
309 ... os.system('hg bookmark -i bm1')
310 ... os.system('hg bookmark -i bm2')
310 ... os.system('hg bookmark -i bm2')
311 ... runcommand(server, [b'bookmarks'])
311 ... runcommand(server, [b'bookmarks'])
312 ...
312 ...
313 ... # changes .hg/bookmarks.current
313 ... # changes .hg/bookmarks.current
314 ... os.system('hg upd bm1 -q')
314 ... os.system('hg upd bm1 -q')
315 ... runcommand(server, [b'bookmarks'])
315 ... runcommand(server, [b'bookmarks'])
316 ...
316 ...
317 ... runcommand(server, [b'bookmarks', b'bm3'])
317 ... runcommand(server, [b'bookmarks', b'bm3'])
318 ... f = open('a', 'ab')
318 ... f = open('a', 'ab')
319 ... f.write(b'a\n') and None
319 ... f.write(b'a\n') and None
320 ... f.close()
320 ... f.close()
321 ... runcommand(server, [b'commit', b'-Amm'])
321 ... runcommand(server, [b'commit', b'-Amm'])
322 ... runcommand(server, [b'bookmarks'])
322 ... runcommand(server, [b'bookmarks'])
323 ... bprint(b'')
323 ... bprint(b'')
324 *** runcommand bookmarks
324 *** runcommand bookmarks
325 no bookmarks set
325 no bookmarks set
326 *** runcommand bookmarks
326 *** runcommand bookmarks
327 bm1 1:d3a0a68be6de
327 bm1 1:d3a0a68be6de
328 bm2 1:d3a0a68be6de
328 bm2 1:d3a0a68be6de
329 *** runcommand bookmarks
329 *** runcommand bookmarks
330 * bm1 1:d3a0a68be6de
330 * bm1 1:d3a0a68be6de
331 bm2 1:d3a0a68be6de
331 bm2 1:d3a0a68be6de
332 *** runcommand bookmarks bm3
332 *** runcommand bookmarks bm3
333 *** runcommand commit -Amm
333 *** runcommand commit -Amm
334 *** runcommand bookmarks
334 *** runcommand bookmarks
335 bm1 1:d3a0a68be6de
335 bm1 1:d3a0a68be6de
336 bm2 1:d3a0a68be6de
336 bm2 1:d3a0a68be6de
337 * bm3 2:aef17e88f5f0
337 * bm3 2:aef17e88f5f0
338
338
339
339
340 >>> import os
340 >>> import os
341 >>> from hgclient import check, readchannel, runcommand
341 >>> from hgclient import check, readchannel, runcommand
342 >>> @check
342 >>> @check
343 ... def tagscache(server):
343 ... def tagscache(server):
344 ... readchannel(server)
344 ... readchannel(server)
345 ... runcommand(server, [b'id', b'-t', b'-r', b'0'])
345 ... runcommand(server, [b'id', b'-t', b'-r', b'0'])
346 ... os.system('hg tag -r 0 foo')
346 ... os.system('hg tag -r 0 foo')
347 ... runcommand(server, [b'id', b'-t', b'-r', b'0'])
347 ... runcommand(server, [b'id', b'-t', b'-r', b'0'])
348 *** runcommand id -t -r 0
348 *** runcommand id -t -r 0
349
349
350 *** runcommand id -t -r 0
350 *** runcommand id -t -r 0
351 foo
351 foo
352
352
353 >>> import os
353 >>> import os
354 >>> from hgclient import check, readchannel, runcommand
354 >>> from hgclient import check, readchannel, runcommand
355 >>> @check
355 >>> @check
356 ... def setphase(server):
356 ... def setphase(server):
357 ... readchannel(server)
357 ... readchannel(server)
358 ... runcommand(server, [b'phase', b'-r', b'.'])
358 ... runcommand(server, [b'phase', b'-r', b'.'])
359 ... os.system('hg phase -r . -p')
359 ... os.system('hg phase -r . -p')
360 ... runcommand(server, [b'phase', b'-r', b'.'])
360 ... runcommand(server, [b'phase', b'-r', b'.'])
361 *** runcommand phase -r .
361 *** runcommand phase -r .
362 3: draft
362 3: draft
363 *** runcommand phase -r .
363 *** runcommand phase -r .
364 3: public
364 3: public
365
365
366 $ echo a >> a
366 $ echo a >> a
367 >>> from hgclient import bprint, check, readchannel, runcommand
367 >>> from hgclient import bprint, check, readchannel, runcommand
368 >>> @check
368 >>> @check
369 ... def rollback(server):
369 ... def rollback(server):
370 ... readchannel(server)
370 ... readchannel(server)
371 ... runcommand(server, [b'phase', b'-r', b'.', b'-p'])
371 ... runcommand(server, [b'phase', b'-r', b'.', b'-p'])
372 ... runcommand(server, [b'commit', b'-Am.'])
372 ... runcommand(server, [b'commit', b'-Am.'])
373 ... runcommand(server, [b'rollback'])
373 ... runcommand(server, [b'rollback'])
374 ... runcommand(server, [b'phase', b'-r', b'.'])
374 ... runcommand(server, [b'phase', b'-r', b'.'])
375 ... bprint(b'')
375 ... bprint(b'')
376 *** runcommand phase -r . -p
376 *** runcommand phase -r . -p
377 no phases changed
377 no phases changed
378 *** runcommand commit -Am.
378 *** runcommand commit -Am.
379 *** runcommand rollback
379 *** runcommand rollback
380 repository tip rolled back to revision 3 (undo commit)
380 repository tip rolled back to revision 3 (undo commit)
381 working directory now based on revision 3
381 working directory now based on revision 3
382 *** runcommand phase -r .
382 *** runcommand phase -r .
383 3: public
383 3: public
384
384
385
385
386 >>> import os
386 >>> import os
387 >>> from hgclient import check, readchannel, runcommand
387 >>> from hgclient import check, readchannel, runcommand
388 >>> @check
388 >>> @check
389 ... def branch(server):
389 ... def branch(server):
390 ... readchannel(server)
390 ... readchannel(server)
391 ... runcommand(server, [b'branch'])
391 ... runcommand(server, [b'branch'])
392 ... os.system('hg branch foo')
392 ... os.system('hg branch foo')
393 ... runcommand(server, [b'branch'])
393 ... runcommand(server, [b'branch'])
394 ... os.system('hg branch default')
394 ... os.system('hg branch default')
395 *** runcommand branch
395 *** runcommand branch
396 default
396 default
397 marked working directory as branch foo
397 marked working directory as branch foo
398 (branches are permanent and global, did you want a bookmark?)
398 (branches are permanent and global, did you want a bookmark?)
399 *** runcommand branch
399 *** runcommand branch
400 foo
400 foo
401 marked working directory as branch default
401 marked working directory as branch default
402 (branches are permanent and global, did you want a bookmark?)
402 (branches are permanent and global, did you want a bookmark?)
403
403
404 $ touch .hgignore
404 $ touch .hgignore
405 >>> import os
405 >>> import os
406 >>> from hgclient import bprint, check, readchannel, runcommand
406 >>> from hgclient import bprint, check, readchannel, runcommand
407 >>> @check
407 >>> @check
408 ... def hgignore(server):
408 ... def hgignore(server):
409 ... readchannel(server)
409 ... readchannel(server)
410 ... runcommand(server, [b'commit', b'-Am.'])
410 ... runcommand(server, [b'commit', b'-Am.'])
411 ... f = open('ignored-file', 'ab')
411 ... f = open('ignored-file', 'ab')
412 ... f.write(b'') and None
412 ... f.write(b'') and None
413 ... f.close()
413 ... f.close()
414 ... f = open('.hgignore', 'ab')
414 ... f = open('.hgignore', 'ab')
415 ... f.write(b'ignored-file')
415 ... f.write(b'ignored-file')
416 ... f.close()
416 ... f.close()
417 ... runcommand(server, [b'status', b'-i', b'-u'])
417 ... runcommand(server, [b'status', b'-i', b'-u'])
418 ... bprint(b'')
418 ... bprint(b'')
419 *** runcommand commit -Am.
419 *** runcommand commit -Am.
420 adding .hgignore
420 adding .hgignore
421 *** runcommand status -i -u
421 *** runcommand status -i -u
422 I ignored-file
422 I ignored-file
423
423
424
424
425 cache of non-public revisions should be invalidated on repository change
425 cache of non-public revisions should be invalidated on repository change
426 (issue4855):
426 (issue4855):
427
427
428 >>> import os
428 >>> import os
429 >>> from hgclient import bprint, check, readchannel, runcommand
429 >>> from hgclient import bprint, check, readchannel, runcommand
430 >>> @check
430 >>> @check
431 ... def phasesetscacheaftercommit(server):
431 ... def phasesetscacheaftercommit(server):
432 ... readchannel(server)
432 ... readchannel(server)
433 ... # load _phasecache._phaserevs and _phasesets
433 ... # load _phasecache._phaserevs and _phasesets
434 ... runcommand(server, [b'log', b'-qr', b'draft()'])
434 ... runcommand(server, [b'log', b'-qr', b'draft()'])
435 ... # create draft commits by another process
435 ... # create draft commits by another process
436 ... for i in range(5, 7):
436 ... for i in range(5, 7):
437 ... f = open('a', 'ab')
437 ... f = open('a', 'ab')
438 ... f.seek(0, os.SEEK_END)
438 ... f.seek(0, os.SEEK_END)
439 ... f.write(b'a\n') and None
439 ... f.write(b'a\n') and None
440 ... f.close()
440 ... f.close()
441 ... os.system('hg commit -Aqm%d' % i)
441 ... os.system('hg commit -Aqm%d' % i)
442 ... # new commits should be listed as draft revisions
442 ... # new commits should be listed as draft revisions
443 ... runcommand(server, [b'log', b'-qr', b'draft()'])
443 ... runcommand(server, [b'log', b'-qr', b'draft()'])
444 ... bprint(b'')
444 ... bprint(b'')
445 *** runcommand log -qr draft()
445 *** runcommand log -qr draft()
446 4:7966c8e3734d
446 4:7966c8e3734d
447 *** runcommand log -qr draft()
447 *** runcommand log -qr draft()
448 4:7966c8e3734d
448 4:7966c8e3734d
449 5:41f6602d1c4f
449 5:41f6602d1c4f
450 6:10501e202c35
450 6:10501e202c35
451
451
452
452
453 >>> import os
453 >>> import os
454 >>> from hgclient import bprint, check, readchannel, runcommand
454 >>> from hgclient import bprint, check, readchannel, runcommand
455 >>> @check
455 >>> @check
456 ... def phasesetscacheafterstrip(server):
456 ... def phasesetscacheafterstrip(server):
457 ... readchannel(server)
457 ... readchannel(server)
458 ... # load _phasecache._phaserevs and _phasesets
458 ... # load _phasecache._phaserevs and _phasesets
459 ... runcommand(server, [b'log', b'-qr', b'draft()'])
459 ... runcommand(server, [b'log', b'-qr', b'draft()'])
460 ... # strip cached revisions by another process
460 ... # strip cached revisions by another process
461 ... os.system('hg --config extensions.strip= strip -q 5')
461 ... os.system('hg --config extensions.strip= strip -q 5')
462 ... # shouldn't abort by "unknown revision '6'"
462 ... # shouldn't abort by "unknown revision '6'"
463 ... runcommand(server, [b'log', b'-qr', b'draft()'])
463 ... runcommand(server, [b'log', b'-qr', b'draft()'])
464 ... bprint(b'')
464 ... bprint(b'')
465 *** runcommand log -qr draft()
465 *** runcommand log -qr draft()
466 4:7966c8e3734d
466 4:7966c8e3734d
467 5:41f6602d1c4f
467 5:41f6602d1c4f
468 6:10501e202c35
468 6:10501e202c35
469 *** runcommand log -qr draft()
469 *** runcommand log -qr draft()
470 4:7966c8e3734d
470 4:7966c8e3734d
471
471
472
472
473 cache of phase roots should be invalidated on strip (issue3827):
473 cache of phase roots should be invalidated on strip (issue3827):
474
474
475 >>> import os
475 >>> import os
476 >>> from hgclient import check, readchannel, runcommand, sep
476 >>> from hgclient import check, readchannel, runcommand, sep
477 >>> @check
477 >>> @check
478 ... def phasecacheafterstrip(server):
478 ... def phasecacheafterstrip(server):
479 ... readchannel(server)
479 ... readchannel(server)
480 ...
480 ...
481 ... # create new head, 5:731265503d86
481 ... # create new head, 5:731265503d86
482 ... runcommand(server, [b'update', b'-C', b'0'])
482 ... runcommand(server, [b'update', b'-C', b'0'])
483 ... f = open('a', 'ab')
483 ... f = open('a', 'ab')
484 ... f.write(b'a\n') and None
484 ... f.write(b'a\n') and None
485 ... f.close()
485 ... f.close()
486 ... runcommand(server, [b'commit', b'-Am.', b'a'])
486 ... runcommand(server, [b'commit', b'-Am.', b'a'])
487 ... runcommand(server, [b'log', b'-Gq'])
487 ... runcommand(server, [b'log', b'-Gq'])
488 ...
488 ...
489 ... # make it public; draft marker moves to 4:7966c8e3734d
489 ... # make it public; draft marker moves to 4:7966c8e3734d
490 ... runcommand(server, [b'phase', b'-p', b'.'])
490 ... runcommand(server, [b'phase', b'-p', b'.'])
491 ... # load _phasecache.phaseroots
491 ... # load _phasecache.phaseroots
492 ... runcommand(server, [b'phase', b'.'], outfilter=sep)
492 ... runcommand(server, [b'phase', b'.'], outfilter=sep)
493 ...
493 ...
494 ... # strip 1::4 outside server
494 ... # strip 1::4 outside server
495 ... os.system('hg -q --config extensions.mq= strip 1')
495 ... os.system('hg -q --config extensions.mq= strip 1')
496 ...
496 ...
497 ... # shouldn't raise "7966c8e3734d: no node!"
497 ... # shouldn't raise "7966c8e3734d: no node!"
498 ... runcommand(server, [b'branches'])
498 ... runcommand(server, [b'branches'])
499 *** runcommand update -C 0
499 *** runcommand update -C 0
500 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
500 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
501 (leaving bookmark bm3)
501 (leaving bookmark bm3)
502 *** runcommand commit -Am. a
502 *** runcommand commit -Am. a
503 created new head
503 created new head
504 *** runcommand log -Gq
504 *** runcommand log -Gq
505 @ 5:731265503d86
505 @ 5:731265503d86
506 |
506 |
507 | o 4:7966c8e3734d
507 | o 4:7966c8e3734d
508 | |
508 | |
509 | o 3:b9b85890c400
509 | o 3:b9b85890c400
510 | |
510 | |
511 | o 2:aef17e88f5f0
511 | o 2:aef17e88f5f0
512 | |
512 | |
513 | o 1:d3a0a68be6de
513 | o 1:d3a0a68be6de
514 |/
514 |/
515 o 0:eff892de26ec
515 o 0:eff892de26ec
516
516
517 *** runcommand phase -p .
517 *** runcommand phase -p .
518 *** runcommand phase .
518 *** runcommand phase .
519 5: public
519 5: public
520 *** runcommand branches
520 *** runcommand branches
521 default 1:731265503d86
521 default 1:731265503d86
522
522
523 in-memory cache must be reloaded if transaction is aborted. otherwise
523 in-memory cache must be reloaded if transaction is aborted. otherwise
524 changelog and manifest would have invalid node:
524 changelog and manifest would have invalid node:
525
525
526 $ echo a >> a
526 $ echo a >> a
527 >>> from hgclient import check, readchannel, runcommand
527 >>> from hgclient import check, readchannel, runcommand
528 >>> @check
528 >>> @check
529 ... def txabort(server):
529 ... def txabort(server):
530 ... readchannel(server)
530 ... readchannel(server)
531 ... runcommand(server, [b'commit', b'--config', b'hooks.pretxncommit=false',
531 ... runcommand(server, [b'commit', b'--config', b'hooks.pretxncommit=false',
532 ... b'-mfoo'])
532 ... b'-mfoo'])
533 ... runcommand(server, [b'verify'])
533 ... runcommand(server, [b'verify'])
534 *** runcommand commit --config hooks.pretxncommit=false -mfoo
534 *** runcommand commit --config hooks.pretxncommit=false -mfoo
535 transaction abort!
535 transaction abort!
536 rollback completed
536 rollback completed
537 abort: pretxncommit hook exited with status 1
537 abort: pretxncommit hook exited with status 1
538 [40]
538 [40]
539 *** runcommand verify
539 *** runcommand verify
540 checking changesets
540 checking changesets
541 checking manifests
541 checking manifests
542 crosschecking files in changesets and manifests
542 crosschecking files in changesets and manifests
543 checking files
543 checking files
544 checking dirstate
544 checked 2 changesets with 2 changes to 1 files
545 checked 2 changesets with 2 changes to 1 files
545 $ hg revert --no-backup -aq
546 $ hg revert --no-backup -aq
546
547
547 $ cat >> .hg/hgrc << EOF
548 $ cat >> .hg/hgrc << EOF
548 > [experimental]
549 > [experimental]
549 > evolution.createmarkers=True
550 > evolution.createmarkers=True
550 > EOF
551 > EOF
551
552
552 >>> import os
553 >>> import os
553 >>> from hgclient import check, readchannel, runcommand
554 >>> from hgclient import check, readchannel, runcommand
554 >>> @check
555 >>> @check
555 ... def obsolete(server):
556 ... def obsolete(server):
556 ... readchannel(server)
557 ... readchannel(server)
557 ...
558 ...
558 ... runcommand(server, [b'up', b'null'])
559 ... runcommand(server, [b'up', b'null'])
559 ... runcommand(server, [b'phase', b'-df', b'tip'])
560 ... runcommand(server, [b'phase', b'-df', b'tip'])
560 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
561 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
561 ... if os.name == 'nt':
562 ... if os.name == 'nt':
562 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
563 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
563 ... os.system(cmd)
564 ... os.system(cmd)
564 ... runcommand(server, [b'log', b'--hidden'])
565 ... runcommand(server, [b'log', b'--hidden'])
565 ... runcommand(server, [b'log'])
566 ... runcommand(server, [b'log'])
566 *** runcommand up null
567 *** runcommand up null
567 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
568 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
568 *** runcommand phase -df tip
569 *** runcommand phase -df tip
569 1 new obsolescence markers
570 1 new obsolescence markers
570 obsoleted 1 changesets
571 obsoleted 1 changesets
571 *** runcommand log --hidden
572 *** runcommand log --hidden
572 changeset: 1:731265503d86
573 changeset: 1:731265503d86
573 tag: tip
574 tag: tip
574 user: test
575 user: test
575 date: Thu Jan 01 00:00:00 1970 +0000
576 date: Thu Jan 01 00:00:00 1970 +0000
576 obsolete: pruned
577 obsolete: pruned
577 summary: .
578 summary: .
578
579
579 changeset: 0:eff892de26ec
580 changeset: 0:eff892de26ec
580 bookmark: bm1
581 bookmark: bm1
581 bookmark: bm2
582 bookmark: bm2
582 bookmark: bm3
583 bookmark: bm3
583 user: test
584 user: test
584 date: Thu Jan 01 00:00:00 1970 +0000
585 date: Thu Jan 01 00:00:00 1970 +0000
585 summary: 1
586 summary: 1
586
587
587 *** runcommand log
588 *** runcommand log
588 changeset: 0:eff892de26ec
589 changeset: 0:eff892de26ec
589 bookmark: bm1
590 bookmark: bm1
590 bookmark: bm2
591 bookmark: bm2
591 bookmark: bm3
592 bookmark: bm3
592 tag: tip
593 tag: tip
593 user: test
594 user: test
594 date: Thu Jan 01 00:00:00 1970 +0000
595 date: Thu Jan 01 00:00:00 1970 +0000
595 summary: 1
596 summary: 1
596
597
597
598
598 $ cat <<EOF >> .hg/hgrc
599 $ cat <<EOF >> .hg/hgrc
599 > [extensions]
600 > [extensions]
600 > mq =
601 > mq =
601 > EOF
602 > EOF
602
603
603 >>> import os
604 >>> import os
604 >>> from hgclient import check, readchannel, runcommand
605 >>> from hgclient import check, readchannel, runcommand
605 >>> @check
606 >>> @check
606 ... def mqoutsidechanges(server):
607 ... def mqoutsidechanges(server):
607 ... readchannel(server)
608 ... readchannel(server)
608 ...
609 ...
609 ... # load repo.mq
610 ... # load repo.mq
610 ... runcommand(server, [b'qapplied'])
611 ... runcommand(server, [b'qapplied'])
611 ... os.system('hg qnew 0.diff')
612 ... os.system('hg qnew 0.diff')
612 ... # repo.mq should be invalidated
613 ... # repo.mq should be invalidated
613 ... runcommand(server, [b'qapplied'])
614 ... runcommand(server, [b'qapplied'])
614 ...
615 ...
615 ... runcommand(server, [b'qpop', b'--all'])
616 ... runcommand(server, [b'qpop', b'--all'])
616 ... os.system('hg qqueue --create foo')
617 ... os.system('hg qqueue --create foo')
617 ... # repo.mq should be recreated to point to new queue
618 ... # repo.mq should be recreated to point to new queue
618 ... runcommand(server, [b'qqueue', b'--active'])
619 ... runcommand(server, [b'qqueue', b'--active'])
619 *** runcommand qapplied
620 *** runcommand qapplied
620 *** runcommand qapplied
621 *** runcommand qapplied
621 0.diff
622 0.diff
622 *** runcommand qpop --all
623 *** runcommand qpop --all
623 popping 0.diff
624 popping 0.diff
624 patch queue now empty
625 patch queue now empty
625 *** runcommand qqueue --active
626 *** runcommand qqueue --active
626 foo
627 foo
627
628
628 $ cat <<'EOF' > ../dbgui.py
629 $ cat <<'EOF' > ../dbgui.py
629 > import os
630 > import os
630 > import sys
631 > import sys
631 > from mercurial import commands, registrar
632 > from mercurial import commands, registrar
632 > cmdtable = {}
633 > cmdtable = {}
633 > command = registrar.command(cmdtable)
634 > command = registrar.command(cmdtable)
634 > @command(b"debuggetpass", norepo=True)
635 > @command(b"debuggetpass", norepo=True)
635 > def debuggetpass(ui):
636 > def debuggetpass(ui):
636 > ui.write(b"%s\n" % ui.getpass())
637 > ui.write(b"%s\n" % ui.getpass())
637 > @command(b"debugprompt", norepo=True)
638 > @command(b"debugprompt", norepo=True)
638 > def debugprompt(ui):
639 > def debugprompt(ui):
639 > ui.write(b"%s\n" % ui.prompt(b"prompt:"))
640 > ui.write(b"%s\n" % ui.prompt(b"prompt:"))
640 > @command(b"debugpromptchoice", norepo=True)
641 > @command(b"debugpromptchoice", norepo=True)
641 > def debugpromptchoice(ui):
642 > def debugpromptchoice(ui):
642 > msg = b"promptchoice (y/n)? $$ &Yes $$ &No"
643 > msg = b"promptchoice (y/n)? $$ &Yes $$ &No"
643 > ui.write(b"%d\n" % ui.promptchoice(msg))
644 > ui.write(b"%d\n" % ui.promptchoice(msg))
644 > @command(b"debugreadstdin", norepo=True)
645 > @command(b"debugreadstdin", norepo=True)
645 > def debugreadstdin(ui):
646 > def debugreadstdin(ui):
646 > ui.write(b"read: %r\n" % sys.stdin.read(1))
647 > ui.write(b"read: %r\n" % sys.stdin.read(1))
647 > @command(b"debugwritestdout", norepo=True)
648 > @command(b"debugwritestdout", norepo=True)
648 > def debugwritestdout(ui):
649 > def debugwritestdout(ui):
649 > os.write(1, b"low-level stdout fd and\n")
650 > os.write(1, b"low-level stdout fd and\n")
650 > sys.stdout.write("stdout should be redirected to stderr\n")
651 > sys.stdout.write("stdout should be redirected to stderr\n")
651 > sys.stdout.flush()
652 > sys.stdout.flush()
652 > EOF
653 > EOF
653 $ cat <<EOF >> .hg/hgrc
654 $ cat <<EOF >> .hg/hgrc
654 > [extensions]
655 > [extensions]
655 > dbgui = ../dbgui.py
656 > dbgui = ../dbgui.py
656 > EOF
657 > EOF
657
658
658 >>> from hgclient import check, readchannel, runcommand, stringio
659 >>> from hgclient import check, readchannel, runcommand, stringio
659 >>> @check
660 >>> @check
660 ... def getpass(server):
661 ... def getpass(server):
661 ... readchannel(server)
662 ... readchannel(server)
662 ... runcommand(server, [b'debuggetpass', b'--config',
663 ... runcommand(server, [b'debuggetpass', b'--config',
663 ... b'ui.interactive=True'],
664 ... b'ui.interactive=True'],
664 ... input=stringio(b'1234\n'))
665 ... input=stringio(b'1234\n'))
665 ... runcommand(server, [b'debuggetpass', b'--config',
666 ... runcommand(server, [b'debuggetpass', b'--config',
666 ... b'ui.interactive=True'],
667 ... b'ui.interactive=True'],
667 ... input=stringio(b'\n'))
668 ... input=stringio(b'\n'))
668 ... runcommand(server, [b'debuggetpass', b'--config',
669 ... runcommand(server, [b'debuggetpass', b'--config',
669 ... b'ui.interactive=True'],
670 ... b'ui.interactive=True'],
670 ... input=stringio(b''))
671 ... input=stringio(b''))
671 ... runcommand(server, [b'debugprompt', b'--config',
672 ... runcommand(server, [b'debugprompt', b'--config',
672 ... b'ui.interactive=True'],
673 ... b'ui.interactive=True'],
673 ... input=stringio(b'5678\n'))
674 ... input=stringio(b'5678\n'))
674 ... runcommand(server, [b'debugprompt', b'--config',
675 ... runcommand(server, [b'debugprompt', b'--config',
675 ... b'ui.interactive=True'],
676 ... b'ui.interactive=True'],
676 ... input=stringio(b'\nremainder\nshould\nnot\nbe\nread\n'))
677 ... input=stringio(b'\nremainder\nshould\nnot\nbe\nread\n'))
677 ... runcommand(server, [b'debugreadstdin'])
678 ... runcommand(server, [b'debugreadstdin'])
678 ... runcommand(server, [b'debugwritestdout'])
679 ... runcommand(server, [b'debugwritestdout'])
679 *** runcommand debuggetpass --config ui.interactive=True
680 *** runcommand debuggetpass --config ui.interactive=True
680 password: 1234
681 password: 1234
681 *** runcommand debuggetpass --config ui.interactive=True
682 *** runcommand debuggetpass --config ui.interactive=True
682 password:
683 password:
683 *** runcommand debuggetpass --config ui.interactive=True
684 *** runcommand debuggetpass --config ui.interactive=True
684 password: abort: response expected
685 password: abort: response expected
685 [255]
686 [255]
686 *** runcommand debugprompt --config ui.interactive=True
687 *** runcommand debugprompt --config ui.interactive=True
687 prompt: 5678
688 prompt: 5678
688 *** runcommand debugprompt --config ui.interactive=True
689 *** runcommand debugprompt --config ui.interactive=True
689 prompt: y
690 prompt: y
690 *** runcommand debugreadstdin
691 *** runcommand debugreadstdin
691 read: ''
692 read: ''
692 *** runcommand debugwritestdout
693 *** runcommand debugwritestdout
693 low-level stdout fd and
694 low-level stdout fd and
694 stdout should be redirected to stderr
695 stdout should be redirected to stderr
695
696
696
697
697 run commandserver in commandserver, which is silly but should work:
698 run commandserver in commandserver, which is silly but should work:
698
699
699 >>> from hgclient import bprint, check, readchannel, runcommand, stringio
700 >>> from hgclient import bprint, check, readchannel, runcommand, stringio
700 >>> @check
701 >>> @check
701 ... def nested(server):
702 ... def nested(server):
702 ... bprint(b'%c, %r' % readchannel(server))
703 ... bprint(b'%c, %r' % readchannel(server))
703 ... class nestedserver(object):
704 ... class nestedserver(object):
704 ... stdin = stringio(b'getencoding\n')
705 ... stdin = stringio(b'getencoding\n')
705 ... stdout = stringio()
706 ... stdout = stringio()
706 ... runcommand(server, [b'serve', b'--cmdserver', b'pipe'],
707 ... runcommand(server, [b'serve', b'--cmdserver', b'pipe'],
707 ... output=nestedserver.stdout, input=nestedserver.stdin)
708 ... output=nestedserver.stdout, input=nestedserver.stdin)
708 ... nestedserver.stdout.seek(0)
709 ... nestedserver.stdout.seek(0)
709 ... bprint(b'%c, %r' % readchannel(nestedserver)) # hello
710 ... bprint(b'%c, %r' % readchannel(nestedserver)) # hello
710 ... bprint(b'%c, %r' % readchannel(nestedserver)) # getencoding
711 ... bprint(b'%c, %r' % readchannel(nestedserver)) # getencoding
711 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
712 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
712 *** runcommand serve --cmdserver pipe
713 *** runcommand serve --cmdserver pipe
713 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
714 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
714 r, '*' (glob)
715 r, '*' (glob)
715
716
716
717
717 start without repository:
718 start without repository:
718
719
719 $ cd ..
720 $ cd ..
720
721
721 >>> from hgclient import bprint, check, readchannel, runcommand
722 >>> from hgclient import bprint, check, readchannel, runcommand
722 >>> @check
723 >>> @check
723 ... def hellomessage(server):
724 ... def hellomessage(server):
724 ... ch, data = readchannel(server)
725 ... ch, data = readchannel(server)
725 ... bprint(b'%c, %r' % (ch, data))
726 ... bprint(b'%c, %r' % (ch, data))
726 ... # run an arbitrary command to make sure the next thing the server
727 ... # run an arbitrary command to make sure the next thing the server
727 ... # sends isn't part of the hello message
728 ... # sends isn't part of the hello message
728 ... runcommand(server, [b'id'])
729 ... runcommand(server, [b'id'])
729 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
730 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
730 *** runcommand id
731 *** runcommand id
731 abort: there is no Mercurial repository here (.hg not found)
732 abort: there is no Mercurial repository here (.hg not found)
732 [10]
733 [10]
733
734
734 >>> from hgclient import check, readchannel, runcommand
735 >>> from hgclient import check, readchannel, runcommand
735 >>> @check
736 >>> @check
736 ... def startwithoutrepo(server):
737 ... def startwithoutrepo(server):
737 ... readchannel(server)
738 ... readchannel(server)
738 ... runcommand(server, [b'init', b'repo2'])
739 ... runcommand(server, [b'init', b'repo2'])
739 ... runcommand(server, [b'id', b'-R', b'repo2'])
740 ... runcommand(server, [b'id', b'-R', b'repo2'])
740 *** runcommand init repo2
741 *** runcommand init repo2
741 *** runcommand id -R repo2
742 *** runcommand id -R repo2
742 000000000000 tip
743 000000000000 tip
743
744
744
745
745 don't fall back to cwd if invalid -R path is specified (issue4805):
746 don't fall back to cwd if invalid -R path is specified (issue4805):
746
747
747 $ cd repo
748 $ cd repo
748 $ hg serve --cmdserver pipe -R ../nonexistent
749 $ hg serve --cmdserver pipe -R ../nonexistent
749 abort: repository ../nonexistent not found
750 abort: repository ../nonexistent not found
750 [255]
751 [255]
751 $ cd ..
752 $ cd ..
752
753
753
754
754 #if no-windows
755 #if no-windows
755
756
756 option to not shutdown on SIGINT:
757 option to not shutdown on SIGINT:
757
758
758 $ cat <<'EOF' > dbgint.py
759 $ cat <<'EOF' > dbgint.py
759 > import os
760 > import os
760 > import signal
761 > import signal
761 > import time
762 > import time
762 > from mercurial import commands, registrar
763 > from mercurial import commands, registrar
763 > cmdtable = {}
764 > cmdtable = {}
764 > command = registrar.command(cmdtable)
765 > command = registrar.command(cmdtable)
765 > @command(b"debugsleep", norepo=True)
766 > @command(b"debugsleep", norepo=True)
766 > def debugsleep(ui):
767 > def debugsleep(ui):
767 > time.sleep(1)
768 > time.sleep(1)
768 > @command(b"debugsuicide", norepo=True)
769 > @command(b"debugsuicide", norepo=True)
769 > def debugsuicide(ui):
770 > def debugsuicide(ui):
770 > os.kill(os.getpid(), signal.SIGINT)
771 > os.kill(os.getpid(), signal.SIGINT)
771 > time.sleep(1)
772 > time.sleep(1)
772 > EOF
773 > EOF
773
774
774 >>> import signal
775 >>> import signal
775 >>> import time
776 >>> import time
776 >>> from hgclient import checkwith, readchannel, runcommand
777 >>> from hgclient import checkwith, readchannel, runcommand
777 >>> @checkwith(extraargs=[b'--config', b'cmdserver.shutdown-on-interrupt=False',
778 >>> @checkwith(extraargs=[b'--config', b'cmdserver.shutdown-on-interrupt=False',
778 ... b'--config', b'extensions.dbgint=dbgint.py'])
779 ... b'--config', b'extensions.dbgint=dbgint.py'])
779 ... def nointr(server):
780 ... def nointr(server):
780 ... readchannel(server)
781 ... readchannel(server)
781 ... server.send_signal(signal.SIGINT) # server won't be terminated
782 ... server.send_signal(signal.SIGINT) # server won't be terminated
782 ... time.sleep(1)
783 ... time.sleep(1)
783 ... runcommand(server, [b'debugsleep'])
784 ... runcommand(server, [b'debugsleep'])
784 ... server.send_signal(signal.SIGINT) # server won't be terminated
785 ... server.send_signal(signal.SIGINT) # server won't be terminated
785 ... runcommand(server, [b'debugsleep'])
786 ... runcommand(server, [b'debugsleep'])
786 ... runcommand(server, [b'debugsuicide']) # command can be interrupted
787 ... runcommand(server, [b'debugsuicide']) # command can be interrupted
787 ... server.send_signal(signal.SIGTERM) # server will be terminated
788 ... server.send_signal(signal.SIGTERM) # server will be terminated
788 ... time.sleep(1)
789 ... time.sleep(1)
789 *** runcommand debugsleep
790 *** runcommand debugsleep
790 *** runcommand debugsleep
791 *** runcommand debugsleep
791 *** runcommand debugsuicide
792 *** runcommand debugsuicide
792 interrupted!
793 interrupted!
793 killed!
794 killed!
794 [255]
795 [255]
795
796
796 #endif
797 #endif
797
798
798
799
799 structured message channel:
800 structured message channel:
800
801
801 $ cat <<'EOF' >> repo2/.hg/hgrc
802 $ cat <<'EOF' >> repo2/.hg/hgrc
802 > [ui]
803 > [ui]
803 > # server --config should precede repository option
804 > # server --config should precede repository option
804 > message-output = stdio
805 > message-output = stdio
805 > EOF
806 > EOF
806
807
807 >>> from hgclient import bprint, checkwith, readchannel, runcommand
808 >>> from hgclient import bprint, checkwith, readchannel, runcommand
808 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel',
809 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel',
809 ... b'--config', b'cmdserver.message-encodings=foo cbor'])
810 ... b'--config', b'cmdserver.message-encodings=foo cbor'])
810 ... def verify(server):
811 ... def verify(server):
811 ... _ch, data = readchannel(server)
812 ... _ch, data = readchannel(server)
812 ... bprint(data)
813 ... bprint(data)
813 ... runcommand(server, [b'-R', b'repo2', b'verify'])
814 ... runcommand(server, [b'-R', b'repo2', b'verify'])
814 capabilities: getencoding runcommand
815 capabilities: getencoding runcommand
815 encoding: ascii
816 encoding: ascii
816 message-encoding: cbor
817 message-encoding: cbor
817 pid: * (glob)
818 pid: * (glob)
818 pgid: * (glob) (no-windows !)
819 pgid: * (glob) (no-windows !)
819 *** runcommand -R repo2 verify
820 *** runcommand -R repo2 verify
820 message: '\xa2DdataTchecking changesets\nDtypeFstatus'
821 message: '\xa2DdataTchecking changesets\nDtypeFstatus'
821 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
822 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
822 message: '\xa2DdataSchecking manifests\nDtypeFstatus'
823 message: '\xa2DdataSchecking manifests\nDtypeFstatus'
823 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
824 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
824 message: '\xa2DdataX0crosschecking files in changesets and manifests\nDtypeFstatus'
825 message: '\xa2DdataX0crosschecking files in changesets and manifests\nDtypeFstatus'
825 message: '\xa6Ditem@Cpos\xf6EtopicMcrosscheckingEtotal\xf6DtypeHprogressDunit@'
826 message: '\xa6Ditem@Cpos\xf6EtopicMcrosscheckingEtotal\xf6DtypeHprogressDunit@'
826 message: '\xa2DdataOchecking files\nDtypeFstatus'
827 message: '\xa2DdataOchecking files\nDtypeFstatus'
827 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
828 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@'
829 message: '\xa2DdataRchecking dirstate\nDtypeFstatus'
828 message: '\xa2DdataX/checked 0 changesets with 0 changes to 0 files\nDtypeFstatus'
830 message: '\xa2DdataX/checked 0 changesets with 0 changes to 0 files\nDtypeFstatus'
829
831
830 >>> from hgclient import checkwith, readchannel, runcommand, stringio
832 >>> from hgclient import checkwith, readchannel, runcommand, stringio
831 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel',
833 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel',
832 ... b'--config', b'cmdserver.message-encodings=cbor',
834 ... b'--config', b'cmdserver.message-encodings=cbor',
833 ... b'--config', b'extensions.dbgui=dbgui.py'])
835 ... b'--config', b'extensions.dbgui=dbgui.py'])
834 ... def prompt(server):
836 ... def prompt(server):
835 ... readchannel(server)
837 ... readchannel(server)
836 ... interactive = [b'--config', b'ui.interactive=True']
838 ... interactive = [b'--config', b'ui.interactive=True']
837 ... runcommand(server, [b'debuggetpass'] + interactive,
839 ... runcommand(server, [b'debuggetpass'] + interactive,
838 ... input=stringio(b'1234\n'))
840 ... input=stringio(b'1234\n'))
839 ... runcommand(server, [b'debugprompt'] + interactive,
841 ... runcommand(server, [b'debugprompt'] + interactive,
840 ... input=stringio(b'5678\n'))
842 ... input=stringio(b'5678\n'))
841 ... runcommand(server, [b'debugpromptchoice'] + interactive,
843 ... runcommand(server, [b'debugpromptchoice'] + interactive,
842 ... input=stringio(b'n\n'))
844 ... input=stringio(b'n\n'))
843 *** runcommand debuggetpass --config ui.interactive=True
845 *** runcommand debuggetpass --config ui.interactive=True
844 message: '\xa3DdataJpassword: Hpassword\xf5DtypeFprompt'
846 message: '\xa3DdataJpassword: Hpassword\xf5DtypeFprompt'
845 1234
847 1234
846 *** runcommand debugprompt --config ui.interactive=True
848 *** runcommand debugprompt --config ui.interactive=True
847 message: '\xa3DdataGprompt:GdefaultAyDtypeFprompt'
849 message: '\xa3DdataGprompt:GdefaultAyDtypeFprompt'
848 5678
850 5678
849 *** runcommand debugpromptchoice --config ui.interactive=True
851 *** runcommand debugpromptchoice --config ui.interactive=True
850 message: '\xa4Gchoices\x82\x82AyCYes\x82AnBNoDdataTpromptchoice (y/n)? GdefaultAyDtypeFprompt'
852 message: '\xa4Gchoices\x82\x82AyCYes\x82AnBNoDdataTpromptchoice (y/n)? GdefaultAyDtypeFprompt'
851 1
853 1
852
854
853 bad message encoding:
855 bad message encoding:
854
856
855 $ hg serve --cmdserver pipe --config ui.message-output=channel
857 $ hg serve --cmdserver pipe --config ui.message-output=channel
856 abort: no supported message encodings:
858 abort: no supported message encodings:
857 [255]
859 [255]
858 $ hg serve --cmdserver pipe --config ui.message-output=channel \
860 $ hg serve --cmdserver pipe --config ui.message-output=channel \
859 > --config cmdserver.message-encodings='foo bar'
861 > --config cmdserver.message-encodings='foo bar'
860 abort: no supported message encodings: foo bar
862 abort: no supported message encodings: foo bar
861 [255]
863 [255]
862
864
863 unix domain socket:
865 unix domain socket:
864
866
865 $ cd repo
867 $ cd repo
866 $ hg update -q
868 $ hg update -q
867
869
868 #if unix-socket unix-permissions
870 #if unix-socket unix-permissions
869
871
870 >>> from hgclient import bprint, check, readchannel, runcommand, stringio, unixserver
872 >>> from hgclient import bprint, check, readchannel, runcommand, stringio, unixserver
871 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log')
873 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log')
872 >>> def hellomessage(conn):
874 >>> def hellomessage(conn):
873 ... ch, data = readchannel(conn)
875 ... ch, data = readchannel(conn)
874 ... bprint(b'%c, %r' % (ch, data))
876 ... bprint(b'%c, %r' % (ch, data))
875 ... runcommand(conn, [b'id'])
877 ... runcommand(conn, [b'id'])
876 >>> check(hellomessage, server.connect)
878 >>> check(hellomessage, server.connect)
877 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
879 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
878 *** runcommand id
880 *** runcommand id
879 eff892de26ec tip bm1/bm2/bm3
881 eff892de26ec tip bm1/bm2/bm3
880 >>> def unknowncommand(conn):
882 >>> def unknowncommand(conn):
881 ... readchannel(conn)
883 ... readchannel(conn)
882 ... conn.stdin.write(b'unknowncommand\n')
884 ... conn.stdin.write(b'unknowncommand\n')
883 >>> check(unknowncommand, server.connect) # error sent to server.log
885 >>> check(unknowncommand, server.connect) # error sent to server.log
884 >>> def serverinput(conn):
886 >>> def serverinput(conn):
885 ... readchannel(conn)
887 ... readchannel(conn)
886 ... patch = b"""
888 ... patch = b"""
887 ... # HG changeset patch
889 ... # HG changeset patch
888 ... # User test
890 ... # User test
889 ... # Date 0 0
891 ... # Date 0 0
890 ... 2
892 ... 2
891 ...
893 ...
892 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
894 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
893 ... --- a/a
895 ... --- a/a
894 ... +++ b/a
896 ... +++ b/a
895 ... @@ -1,1 +1,2 @@
897 ... @@ -1,1 +1,2 @@
896 ... 1
898 ... 1
897 ... +2
899 ... +2
898 ... """
900 ... """
899 ... runcommand(conn, [b'import', b'-'], input=stringio(patch))
901 ... runcommand(conn, [b'import', b'-'], input=stringio(patch))
900 ... runcommand(conn, [b'log', b'-rtip', b'-q'])
902 ... runcommand(conn, [b'log', b'-rtip', b'-q'])
901 >>> check(serverinput, server.connect)
903 >>> check(serverinput, server.connect)
902 *** runcommand import -
904 *** runcommand import -
903 applying patch from stdin
905 applying patch from stdin
904 *** runcommand log -rtip -q
906 *** runcommand log -rtip -q
905 2:1ed24be7e7a0
907 2:1ed24be7e7a0
906 >>> server.shutdown()
908 >>> server.shutdown()
907
909
908 $ cat .hg/server.log
910 $ cat .hg/server.log
909 listening at .hg/server.sock
911 listening at .hg/server.sock
910 abort: unknown command unknowncommand
912 abort: unknown command unknowncommand
911 killed!
913 killed!
912 $ rm .hg/server.log
914 $ rm .hg/server.log
913
915
914 if server crashed before hello, traceback will be sent to 'e' channel as
916 if server crashed before hello, traceback will be sent to 'e' channel as
915 last ditch:
917 last ditch:
916
918
917 $ cat <<'EOF' > ../earlycrasher.py
919 $ cat <<'EOF' > ../earlycrasher.py
918 > from mercurial import commandserver, extensions
920 > from mercurial import commandserver, extensions
919 > def _serverequest(orig, ui, repo, conn, createcmdserver, prereposetups):
921 > def _serverequest(orig, ui, repo, conn, createcmdserver, prereposetups):
920 > def createcmdserver(*args, **kwargs):
922 > def createcmdserver(*args, **kwargs):
921 > raise Exception('crash')
923 > raise Exception('crash')
922 > return orig(ui, repo, conn, createcmdserver, prereposetups)
924 > return orig(ui, repo, conn, createcmdserver, prereposetups)
923 > def extsetup(ui):
925 > def extsetup(ui):
924 > extensions.wrapfunction(commandserver, b'_serverequest', _serverequest)
926 > extensions.wrapfunction(commandserver, b'_serverequest', _serverequest)
925 > EOF
927 > EOF
926 $ cat <<EOF >> .hg/hgrc
928 $ cat <<EOF >> .hg/hgrc
927 > [extensions]
929 > [extensions]
928 > earlycrasher = ../earlycrasher.py
930 > earlycrasher = ../earlycrasher.py
929 > EOF
931 > EOF
930 >>> from hgclient import bprint, check, readchannel, unixserver
932 >>> from hgclient import bprint, check, readchannel, unixserver
931 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log')
933 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log')
932 >>> def earlycrash(conn):
934 >>> def earlycrash(conn):
933 ... while True:
935 ... while True:
934 ... try:
936 ... try:
935 ... ch, data = readchannel(conn)
937 ... ch, data = readchannel(conn)
936 ... for l in data.splitlines(True):
938 ... for l in data.splitlines(True):
937 ... if not l.startswith(b' '):
939 ... if not l.startswith(b' '):
938 ... bprint(b'%c, %r' % (ch, l))
940 ... bprint(b'%c, %r' % (ch, l))
939 ... except EOFError:
941 ... except EOFError:
940 ... break
942 ... break
941 >>> check(earlycrash, server.connect)
943 >>> check(earlycrash, server.connect)
942 e, 'Traceback (most recent call last):\n'
944 e, 'Traceback (most recent call last):\n'
943 e, 'Exception: crash\n'
945 e, 'Exception: crash\n'
944 >>> server.shutdown()
946 >>> server.shutdown()
945
947
946 $ cat .hg/server.log | grep -v '^ '
948 $ cat .hg/server.log | grep -v '^ '
947 listening at .hg/server.sock
949 listening at .hg/server.sock
948 Traceback (most recent call last):
950 Traceback (most recent call last):
949 Exception: crash
951 Exception: crash
950 killed!
952 killed!
951 #endif
953 #endif
952 #if no-unix-socket
954 #if no-unix-socket
953
955
954 $ hg serve --cmdserver unix -a .hg/server.sock
956 $ hg serve --cmdserver unix -a .hg/server.sock
955 abort: unsupported platform
957 abort: unsupported platform
956 [255]
958 [255]
957
959
958 #endif
960 #endif
959
961
960 $ cd ..
962 $ cd ..
961
963
962 Test that accessing to invalid changelog cache is avoided at
964 Test that accessing to invalid changelog cache is avoided at
963 subsequent operations even if repo object is reused even after failure
965 subsequent operations even if repo object is reused even after failure
964 of transaction (see 0a7610758c42 also)
966 of transaction (see 0a7610758c42 also)
965
967
966 "hg log" after failure of transaction is needed to detect invalid
968 "hg log" after failure of transaction is needed to detect invalid
967 cache in repoview: this can't detect by "hg verify" only.
969 cache in repoview: this can't detect by "hg verify" only.
968
970
969 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
971 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
970 4) are tested, because '00changelog.i' are differently changed in each
972 4) are tested, because '00changelog.i' are differently changed in each
971 cases.
973 cases.
972
974
973 $ cat > $TESTTMP/failafterfinalize.py <<EOF
975 $ cat > $TESTTMP/failafterfinalize.py <<EOF
974 > # extension to abort transaction after finalization forcibly
976 > # extension to abort transaction after finalization forcibly
975 > from mercurial import commands, error, extensions, lock as lockmod
977 > from mercurial import commands, error, extensions, lock as lockmod
976 > from mercurial import registrar
978 > from mercurial import registrar
977 > cmdtable = {}
979 > cmdtable = {}
978 > command = registrar.command(cmdtable)
980 > command = registrar.command(cmdtable)
979 > configtable = {}
981 > configtable = {}
980 > configitem = registrar.configitem(configtable)
982 > configitem = registrar.configitem(configtable)
981 > configitem(b'failafterfinalize', b'fail',
983 > configitem(b'failafterfinalize', b'fail',
982 > default=None,
984 > default=None,
983 > )
985 > )
984 > def fail(tr):
986 > def fail(tr):
985 > raise error.Abort(b'fail after finalization')
987 > raise error.Abort(b'fail after finalization')
986 > def reposetup(ui, repo):
988 > def reposetup(ui, repo):
987 > class failrepo(repo.__class__):
989 > class failrepo(repo.__class__):
988 > def commitctx(self, ctx, error=False, origctx=None):
990 > def commitctx(self, ctx, error=False, origctx=None):
989 > if self.ui.configbool(b'failafterfinalize', b'fail'):
991 > if self.ui.configbool(b'failafterfinalize', b'fail'):
990 > # 'sorted()' by ASCII code on category names causes
992 > # 'sorted()' by ASCII code on category names causes
991 > # invoking 'fail' after finalization of changelog
993 > # invoking 'fail' after finalization of changelog
992 > # using "'cl-%i' % id(self)" as category name
994 > # using "'cl-%i' % id(self)" as category name
993 > self.currenttransaction().addfinalize(b'zzzzzzzz', fail)
995 > self.currenttransaction().addfinalize(b'zzzzzzzz', fail)
994 > return super(failrepo, self).commitctx(ctx, error, origctx)
996 > return super(failrepo, self).commitctx(ctx, error, origctx)
995 > repo.__class__ = failrepo
997 > repo.__class__ = failrepo
996 > EOF
998 > EOF
997
999
998 $ hg init repo3
1000 $ hg init repo3
999 $ cd repo3
1001 $ cd repo3
1000
1002
1001 $ cat <<EOF >> $HGRCPATH
1003 $ cat <<EOF >> $HGRCPATH
1002 > [command-templates]
1004 > [command-templates]
1003 > log = {rev} {desc|firstline} ({files})\n
1005 > log = {rev} {desc|firstline} ({files})\n
1004 >
1006 >
1005 > [extensions]
1007 > [extensions]
1006 > failafterfinalize = $TESTTMP/failafterfinalize.py
1008 > failafterfinalize = $TESTTMP/failafterfinalize.py
1007 > EOF
1009 > EOF
1008
1010
1009 - test failure with "empty changelog"
1011 - test failure with "empty changelog"
1010
1012
1011 $ echo foo > foo
1013 $ echo foo > foo
1012 $ hg add foo
1014 $ hg add foo
1013
1015
1014 (failure before finalization)
1016 (failure before finalization)
1015
1017
1016 >>> from hgclient import check, readchannel, runcommand
1018 >>> from hgclient import check, readchannel, runcommand
1017 >>> @check
1019 >>> @check
1018 ... def abort(server):
1020 ... def abort(server):
1019 ... readchannel(server)
1021 ... readchannel(server)
1020 ... runcommand(server, [b'commit',
1022 ... runcommand(server, [b'commit',
1021 ... b'--config', b'hooks.pretxncommit=false',
1023 ... b'--config', b'hooks.pretxncommit=false',
1022 ... b'-mfoo'])
1024 ... b'-mfoo'])
1023 ... runcommand(server, [b'log'])
1025 ... runcommand(server, [b'log'])
1024 ... runcommand(server, [b'verify', b'-q'])
1026 ... runcommand(server, [b'verify', b'-q'])
1025 *** runcommand commit --config hooks.pretxncommit=false -mfoo
1027 *** runcommand commit --config hooks.pretxncommit=false -mfoo
1026 transaction abort!
1028 transaction abort!
1027 rollback completed
1029 rollback completed
1028 abort: pretxncommit hook exited with status 1
1030 abort: pretxncommit hook exited with status 1
1029 [40]
1031 [40]
1030 *** runcommand log
1032 *** runcommand log
1031 *** runcommand verify -q
1033 *** runcommand verify -q
1032
1034
1033 (failure after finalization)
1035 (failure after finalization)
1034
1036
1035 >>> from hgclient import check, readchannel, runcommand
1037 >>> from hgclient import check, readchannel, runcommand
1036 >>> @check
1038 >>> @check
1037 ... def abort(server):
1039 ... def abort(server):
1038 ... readchannel(server)
1040 ... readchannel(server)
1039 ... runcommand(server, [b'commit',
1041 ... runcommand(server, [b'commit',
1040 ... b'--config', b'failafterfinalize.fail=true',
1042 ... b'--config', b'failafterfinalize.fail=true',
1041 ... b'-mfoo'])
1043 ... b'-mfoo'])
1042 ... runcommand(server, [b'log'])
1044 ... runcommand(server, [b'log'])
1043 ... runcommand(server, [b'verify', b'-q'])
1045 ... runcommand(server, [b'verify', b'-q'])
1044 *** runcommand commit --config failafterfinalize.fail=true -mfoo
1046 *** runcommand commit --config failafterfinalize.fail=true -mfoo
1045 transaction abort!
1047 transaction abort!
1046 rollback completed
1048 rollback completed
1047 abort: fail after finalization
1049 abort: fail after finalization
1048 [255]
1050 [255]
1049 *** runcommand log
1051 *** runcommand log
1050 *** runcommand verify -q
1052 *** runcommand verify -q
1051
1053
1052 - test failure with "not-empty changelog"
1054 - test failure with "not-empty changelog"
1053
1055
1054 $ echo bar > bar
1056 $ echo bar > bar
1055 $ hg add bar
1057 $ hg add bar
1056 $ hg commit -mbar bar
1058 $ hg commit -mbar bar
1057
1059
1058 (failure before finalization)
1060 (failure before finalization)
1059
1061
1060 >>> from hgclient import check, readchannel, runcommand
1062 >>> from hgclient import check, readchannel, runcommand
1061 >>> @check
1063 >>> @check
1062 ... def abort(server):
1064 ... def abort(server):
1063 ... readchannel(server)
1065 ... readchannel(server)
1064 ... runcommand(server, [b'commit',
1066 ... runcommand(server, [b'commit',
1065 ... b'--config', b'hooks.pretxncommit=false',
1067 ... b'--config', b'hooks.pretxncommit=false',
1066 ... b'-mfoo', b'foo'])
1068 ... b'-mfoo', b'foo'])
1067 ... runcommand(server, [b'log'])
1069 ... runcommand(server, [b'log'])
1068 ... runcommand(server, [b'verify', b'-q'])
1070 ... runcommand(server, [b'verify', b'-q'])
1069 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
1071 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
1070 transaction abort!
1072 transaction abort!
1071 rollback completed
1073 rollback completed
1072 abort: pretxncommit hook exited with status 1
1074 abort: pretxncommit hook exited with status 1
1073 [40]
1075 [40]
1074 *** runcommand log
1076 *** runcommand log
1075 0 bar (bar)
1077 0 bar (bar)
1076 *** runcommand verify -q
1078 *** runcommand verify -q
1077
1079
1078 (failure after finalization)
1080 (failure after finalization)
1079
1081
1080 >>> from hgclient import check, readchannel, runcommand
1082 >>> from hgclient import check, readchannel, runcommand
1081 >>> @check
1083 >>> @check
1082 ... def abort(server):
1084 ... def abort(server):
1083 ... readchannel(server)
1085 ... readchannel(server)
1084 ... runcommand(server, [b'commit',
1086 ... runcommand(server, [b'commit',
1085 ... b'--config', b'failafterfinalize.fail=true',
1087 ... b'--config', b'failafterfinalize.fail=true',
1086 ... b'-mfoo', b'foo'])
1088 ... b'-mfoo', b'foo'])
1087 ... runcommand(server, [b'log'])
1089 ... runcommand(server, [b'log'])
1088 ... runcommand(server, [b'verify', b'-q'])
1090 ... runcommand(server, [b'verify', b'-q'])
1089 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
1091 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
1090 transaction abort!
1092 transaction abort!
1091 rollback completed
1093 rollback completed
1092 abort: fail after finalization
1094 abort: fail after finalization
1093 [255]
1095 [255]
1094 *** runcommand log
1096 *** runcommand log
1095 0 bar (bar)
1097 0 bar (bar)
1096 *** runcommand verify -q
1098 *** runcommand verify -q
1097
1099
1098 $ cd ..
1100 $ cd ..
1099
1101
1100 Test symlink traversal over cached audited paths:
1102 Test symlink traversal over cached audited paths:
1101 -------------------------------------------------
1103 -------------------------------------------------
1102
1104
1103 #if symlink
1105 #if symlink
1104
1106
1105 set up symlink hell
1107 set up symlink hell
1106
1108
1107 $ mkdir merge-symlink-out
1109 $ mkdir merge-symlink-out
1108 $ hg init merge-symlink
1110 $ hg init merge-symlink
1109 $ cd merge-symlink
1111 $ cd merge-symlink
1110 $ touch base
1112 $ touch base
1111 $ hg commit -qAm base
1113 $ hg commit -qAm base
1112 $ ln -s ../merge-symlink-out a
1114 $ ln -s ../merge-symlink-out a
1113 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
1115 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
1114 $ hg up -q 0
1116 $ hg up -q 0
1115 $ mkdir a
1117 $ mkdir a
1116 $ touch a/poisoned
1118 $ touch a/poisoned
1117 $ hg commit -qAm 'file a/poisoned'
1119 $ hg commit -qAm 'file a/poisoned'
1118 $ hg log -G -T '{rev}: {desc}\n'
1120 $ hg log -G -T '{rev}: {desc}\n'
1119 @ 2: file a/poisoned
1121 @ 2: file a/poisoned
1120 |
1122 |
1121 | o 1: symlink a -> ../merge-symlink-out
1123 | o 1: symlink a -> ../merge-symlink-out
1122 |/
1124 |/
1123 o 0: base
1125 o 0: base
1124
1126
1125
1127
1126 try trivial merge after update: cache of audited paths should be discarded,
1128 try trivial merge after update: cache of audited paths should be discarded,
1127 and the merge should fail (issue5628)
1129 and the merge should fail (issue5628)
1128
1130
1129 $ hg up -q null
1131 $ hg up -q null
1130 >>> from hgclient import check, readchannel, runcommand
1132 >>> from hgclient import check, readchannel, runcommand
1131 >>> @check
1133 >>> @check
1132 ... def merge(server):
1134 ... def merge(server):
1133 ... readchannel(server)
1135 ... readchannel(server)
1134 ... # audit a/poisoned as a good path
1136 ... # audit a/poisoned as a good path
1135 ... runcommand(server, [b'up', b'-qC', b'2'])
1137 ... runcommand(server, [b'up', b'-qC', b'2'])
1136 ... runcommand(server, [b'up', b'-qC', b'1'])
1138 ... runcommand(server, [b'up', b'-qC', b'1'])
1137 ... # here a is a symlink, so a/poisoned is bad
1139 ... # here a is a symlink, so a/poisoned is bad
1138 ... runcommand(server, [b'merge', b'2'])
1140 ... runcommand(server, [b'merge', b'2'])
1139 *** runcommand up -qC 2
1141 *** runcommand up -qC 2
1140 *** runcommand up -qC 1
1142 *** runcommand up -qC 1
1141 *** runcommand merge 2
1143 *** runcommand merge 2
1142 abort: path 'a/poisoned' traverses symbolic link 'a'
1144 abort: path 'a/poisoned' traverses symbolic link 'a'
1143 [255]
1145 [255]
1144 $ ls ../merge-symlink-out
1146 $ ls ../merge-symlink-out
1145
1147
1146 cache of repo.auditor should be discarded, so matcher would never traverse
1148 cache of repo.auditor should be discarded, so matcher would never traverse
1147 symlinks:
1149 symlinks:
1148
1150
1149 $ hg up -qC 0
1151 $ hg up -qC 0
1150 $ touch ../merge-symlink-out/poisoned
1152 $ touch ../merge-symlink-out/poisoned
1151 >>> from hgclient import check, readchannel, runcommand
1153 >>> from hgclient import check, readchannel, runcommand
1152 >>> @check
1154 >>> @check
1153 ... def files(server):
1155 ... def files(server):
1154 ... readchannel(server)
1156 ... readchannel(server)
1155 ... runcommand(server, [b'up', b'-qC', b'2'])
1157 ... runcommand(server, [b'up', b'-qC', b'2'])
1156 ... # audit a/poisoned as a good path
1158 ... # audit a/poisoned as a good path
1157 ... runcommand(server, [b'files', b'a/poisoned'])
1159 ... runcommand(server, [b'files', b'a/poisoned'])
1158 ... runcommand(server, [b'up', b'-qC', b'0'])
1160 ... runcommand(server, [b'up', b'-qC', b'0'])
1159 ... runcommand(server, [b'up', b'-qC', b'1'])
1161 ... runcommand(server, [b'up', b'-qC', b'1'])
1160 ... # here 'a' is a symlink, so a/poisoned should be warned
1162 ... # here 'a' is a symlink, so a/poisoned should be warned
1161 ... runcommand(server, [b'files', b'a/poisoned'])
1163 ... runcommand(server, [b'files', b'a/poisoned'])
1162 *** runcommand up -qC 2
1164 *** runcommand up -qC 2
1163 *** runcommand files a/poisoned
1165 *** runcommand files a/poisoned
1164 a/poisoned
1166 a/poisoned
1165 *** runcommand up -qC 0
1167 *** runcommand up -qC 0
1166 *** runcommand up -qC 1
1168 *** runcommand up -qC 1
1167 *** runcommand files a/poisoned
1169 *** runcommand files a/poisoned
1168 abort: path 'a/poisoned' traverses symbolic link 'a'
1170 abort: path 'a/poisoned' traverses symbolic link 'a'
1169 [255]
1171 [255]
1170
1172
1171 $ cd ..
1173 $ cd ..
1172
1174
1173 #endif
1175 #endif
@@ -1,535 +1,537 b''
1 #require repofncache
1 #require repofncache
2
2
3 An extension which will set fncache chunksize to 1 byte to make sure that logic
3 An extension which will set fncache chunksize to 1 byte to make sure that logic
4 does not break
4 does not break
5
5
6 $ cat > chunksize.py <<EOF
6 $ cat > chunksize.py <<EOF
7 > from mercurial import store
7 > from mercurial import store
8 > store.fncache_chunksize = 1
8 > store.fncache_chunksize = 1
9 > EOF
9 > EOF
10
10
11 $ cat >> $HGRCPATH <<EOF
11 $ cat >> $HGRCPATH <<EOF
12 > [extensions]
12 > [extensions]
13 > chunksize = $TESTTMP/chunksize.py
13 > chunksize = $TESTTMP/chunksize.py
14 > EOF
14 > EOF
15
15
16 Init repo1:
16 Init repo1:
17
17
18 $ hg init repo1
18 $ hg init repo1
19 $ cd repo1
19 $ cd repo1
20 $ echo "some text" > a
20 $ echo "some text" > a
21 $ hg add
21 $ hg add
22 adding a
22 adding a
23 $ hg ci -m first
23 $ hg ci -m first
24 $ cat .hg/store/fncache | sort
24 $ cat .hg/store/fncache | sort
25 data/a.i
25 data/a.i
26
26
27 Testing a.i/b:
27 Testing a.i/b:
28
28
29 $ mkdir a.i
29 $ mkdir a.i
30 $ echo "some other text" > a.i/b
30 $ echo "some other text" > a.i/b
31 $ hg add
31 $ hg add
32 adding a.i/b
32 adding a.i/b
33 $ hg ci -m second
33 $ hg ci -m second
34 $ cat .hg/store/fncache | sort
34 $ cat .hg/store/fncache | sort
35 data/a.i
35 data/a.i
36 data/a.i.hg/b.i
36 data/a.i.hg/b.i
37
37
38 Testing a.i.hg/c:
38 Testing a.i.hg/c:
39
39
40 $ mkdir a.i.hg
40 $ mkdir a.i.hg
41 $ echo "yet another text" > a.i.hg/c
41 $ echo "yet another text" > a.i.hg/c
42 $ hg add
42 $ hg add
43 adding a.i.hg/c
43 adding a.i.hg/c
44 $ hg ci -m third
44 $ hg ci -m third
45 $ cat .hg/store/fncache | sort
45 $ cat .hg/store/fncache | sort
46 data/a.i
46 data/a.i
47 data/a.i.hg.hg/c.i
47 data/a.i.hg.hg/c.i
48 data/a.i.hg/b.i
48 data/a.i.hg/b.i
49
49
50 Testing verify:
50 Testing verify:
51
51
52 $ hg verify -q
52 $ hg verify -q
53
53
54 $ rm .hg/store/fncache
54 $ rm .hg/store/fncache
55
55
56 $ hg verify
56 $ hg verify
57 checking changesets
57 checking changesets
58 checking manifests
58 checking manifests
59 crosschecking files in changesets and manifests
59 crosschecking files in changesets and manifests
60 checking files
60 checking files
61 warning: revlog 'data/a.i' not in fncache!
61 warning: revlog 'data/a.i' not in fncache!
62 warning: revlog 'data/a.i.hg/c.i' not in fncache!
62 warning: revlog 'data/a.i.hg/c.i' not in fncache!
63 warning: revlog 'data/a.i/b.i' not in fncache!
63 warning: revlog 'data/a.i/b.i' not in fncache!
64 checking dirstate
64 checked 3 changesets with 3 changes to 3 files
65 checked 3 changesets with 3 changes to 3 files
65 3 warnings encountered!
66 3 warnings encountered!
66 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
67 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
67
68
68 Follow the hint to make sure it works
69 Follow the hint to make sure it works
69
70
70 $ hg debugrebuildfncache
71 $ hg debugrebuildfncache
71 adding data/a.i
72 adding data/a.i
72 adding data/a.i.hg/c.i
73 adding data/a.i.hg/c.i
73 adding data/a.i/b.i
74 adding data/a.i/b.i
74 3 items added, 0 removed from fncache
75 3 items added, 0 removed from fncache
75
76
76 $ hg verify -q
77 $ hg verify -q
77
78
78 $ cd ..
79 $ cd ..
79
80
80 Non store repo:
81 Non store repo:
81
82
82 $ hg --config format.usestore=False init foo
83 $ hg --config format.usestore=False init foo
83 $ cd foo
84 $ cd foo
84 $ mkdir tst.d
85 $ mkdir tst.d
85 $ echo foo > tst.d/foo
86 $ echo foo > tst.d/foo
86 $ hg ci -Amfoo
87 $ hg ci -Amfoo
87 adding tst.d/foo
88 adding tst.d/foo
88 $ find .hg | sort
89 $ find .hg | sort
89 .hg
90 .hg
90 .hg/00changelog.i
91 .hg/00changelog.i
91 .hg/00manifest.i
92 .hg/00manifest.i
92 .hg/cache
93 .hg/cache
93 .hg/cache/branch2-served
94 .hg/cache/branch2-served
94 .hg/cache/rbc-names-v1
95 .hg/cache/rbc-names-v1
95 .hg/cache/rbc-revs-v1
96 .hg/cache/rbc-revs-v1
96 .hg/data
97 .hg/data
97 .hg/data/tst.d.hg
98 .hg/data/tst.d.hg
98 .hg/data/tst.d.hg/foo.i
99 .hg/data/tst.d.hg/foo.i
99 .hg/dirstate
100 .hg/dirstate
100 .hg/fsmonitor.state (fsmonitor !)
101 .hg/fsmonitor.state (fsmonitor !)
101 .hg/last-message.txt
102 .hg/last-message.txt
102 .hg/phaseroots
103 .hg/phaseroots
103 .hg/requires
104 .hg/requires
104 .hg/undo
105 .hg/undo
105 .hg/undo.backup.dirstate
106 .hg/undo.backup.dirstate
106 .hg/undo.backupfiles
107 .hg/undo.backupfiles
107 .hg/undo.bookmarks
108 .hg/undo.bookmarks
108 .hg/undo.branch
109 .hg/undo.branch
109 .hg/undo.desc
110 .hg/undo.desc
110 .hg/undo.dirstate
111 .hg/undo.dirstate
111 .hg/undo.phaseroots
112 .hg/undo.phaseroots
112 .hg/wcache
113 .hg/wcache
113 .hg/wcache/checkisexec (execbit !)
114 .hg/wcache/checkisexec (execbit !)
114 .hg/wcache/checklink (symlink !)
115 .hg/wcache/checklink (symlink !)
115 .hg/wcache/checklink-target (symlink !)
116 .hg/wcache/checklink-target (symlink !)
116 .hg/wcache/manifestfulltextcache (reporevlogstore !)
117 .hg/wcache/manifestfulltextcache (reporevlogstore !)
117 $ cd ..
118 $ cd ..
118
119
119 Non fncache repo:
120 Non fncache repo:
120
121
121 $ hg --config format.usefncache=False init bar
122 $ hg --config format.usefncache=False init bar
122 $ cd bar
123 $ cd bar
123 $ mkdir tst.d
124 $ mkdir tst.d
124 $ echo foo > tst.d/Foo
125 $ echo foo > tst.d/Foo
125 $ hg ci -Amfoo
126 $ hg ci -Amfoo
126 adding tst.d/Foo
127 adding tst.d/Foo
127 $ find .hg | sort
128 $ find .hg | sort
128 .hg
129 .hg
129 .hg/00changelog.i
130 .hg/00changelog.i
130 .hg/cache
131 .hg/cache
131 .hg/cache/branch2-served
132 .hg/cache/branch2-served
132 .hg/cache/rbc-names-v1
133 .hg/cache/rbc-names-v1
133 .hg/cache/rbc-revs-v1
134 .hg/cache/rbc-revs-v1
134 .hg/dirstate
135 .hg/dirstate
135 .hg/fsmonitor.state (fsmonitor !)
136 .hg/fsmonitor.state (fsmonitor !)
136 .hg/last-message.txt
137 .hg/last-message.txt
137 .hg/requires
138 .hg/requires
138 .hg/store
139 .hg/store
139 .hg/store/00changelog.i
140 .hg/store/00changelog.i
140 .hg/store/00manifest.i
141 .hg/store/00manifest.i
141 .hg/store/data
142 .hg/store/data
142 .hg/store/data/tst.d.hg
143 .hg/store/data/tst.d.hg
143 .hg/store/data/tst.d.hg/_foo.i
144 .hg/store/data/tst.d.hg/_foo.i
144 .hg/store/phaseroots
145 .hg/store/phaseroots
145 .hg/store/requires
146 .hg/store/requires
146 .hg/store/undo
147 .hg/store/undo
147 .hg/store/undo.backupfiles
148 .hg/store/undo.backupfiles
148 .hg/store/undo.phaseroots
149 .hg/store/undo.phaseroots
149 .hg/undo.backup.dirstate
150 .hg/undo.backup.dirstate
150 .hg/undo.bookmarks
151 .hg/undo.bookmarks
151 .hg/undo.branch
152 .hg/undo.branch
152 .hg/undo.desc
153 .hg/undo.desc
153 .hg/undo.dirstate
154 .hg/undo.dirstate
154 .hg/wcache
155 .hg/wcache
155 .hg/wcache/checkisexec (execbit !)
156 .hg/wcache/checkisexec (execbit !)
156 .hg/wcache/checklink (symlink !)
157 .hg/wcache/checklink (symlink !)
157 .hg/wcache/checklink-target (symlink !)
158 .hg/wcache/checklink-target (symlink !)
158 .hg/wcache/manifestfulltextcache (reporevlogstore !)
159 .hg/wcache/manifestfulltextcache (reporevlogstore !)
159 $ cd ..
160 $ cd ..
160
161
161 Encoding of reserved / long paths in the store
162 Encoding of reserved / long paths in the store
162
163
163 $ hg init r2
164 $ hg init r2
164 $ cd r2
165 $ cd r2
165 $ cat <<EOF > .hg/hgrc
166 $ cat <<EOF > .hg/hgrc
166 > [ui]
167 > [ui]
167 > portablefilenames = ignore
168 > portablefilenames = ignore
168 > EOF
169 > EOF
169
170
170 $ hg import -q --bypass - <<EOF
171 $ hg import -q --bypass - <<EOF
171 > # HG changeset patch
172 > # HG changeset patch
172 > # User test
173 > # User test
173 > # Date 0 0
174 > # Date 0 0
174 > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7
175 > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7
175 > # Parent 0000000000000000000000000000000000000000
176 > # Parent 0000000000000000000000000000000000000000
176 > 1
177 > 1
177 >
178 >
178 > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
179 > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
179 > new file mode 100644
180 > new file mode 100644
180 > --- /dev/null
181 > --- /dev/null
181 > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
182 > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
182 > @@ -0,0 +1,1 @@
183 > @@ -0,0 +1,1 @@
183 > +foo
184 > +foo
184 > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
185 > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
185 > new file mode 100644
186 > new file mode 100644
186 > --- /dev/null
187 > --- /dev/null
187 > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
188 > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
188 > @@ -0,0 +1,1 @@
189 > @@ -0,0 +1,1 @@
189 > +foo
190 > +foo
190 > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
191 > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
191 > new file mode 100644
192 > new file mode 100644
192 > --- /dev/null
193 > --- /dev/null
193 > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
194 > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
194 > @@ -0,0 +1,1 @@
195 > @@ -0,0 +1,1 @@
195 > +foo
196 > +foo
196 > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
197 > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
197 > new file mode 100644
198 > new file mode 100644
198 > --- /dev/null
199 > --- /dev/null
199 > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
200 > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
200 > @@ -0,0 +1,1 @@
201 > @@ -0,0 +1,1 @@
201 > +foo
202 > +foo
202 > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
203 > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
203 > new file mode 100644
204 > new file mode 100644
204 > --- /dev/null
205 > --- /dev/null
205 > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
206 > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
206 > @@ -0,0 +1,1 @@
207 > @@ -0,0 +1,1 @@
207 > +foo
208 > +foo
208 > EOF
209 > EOF
209
210
210 $ find .hg/store -name *.i | sort
211 $ find .hg/store -name *.i | sort
211 .hg/store/00changelog.i
212 .hg/store/00changelog.i
212 .hg/store/00manifest.i
213 .hg/store/00manifest.i
213 .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i
214 .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i
214 .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i
215 .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i
215 .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i
216 .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i
216 .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i
217 .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i
217 .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i
218 .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i
218
219
219 $ cd ..
220 $ cd ..
220
221
221 Aborting lock does not prevent fncache writes
222 Aborting lock does not prevent fncache writes
222
223
223 $ cat > exceptionext.py <<EOF
224 $ cat > exceptionext.py <<EOF
224 > import os
225 > import os
225 > from mercurial import commands, error, extensions
226 > from mercurial import commands, error, extensions
226 >
227 >
227 > def lockexception(orig, vfs, lockname, wait, releasefn, *args, **kwargs):
228 > def lockexception(orig, vfs, lockname, wait, releasefn, *args, **kwargs):
228 > def releasewrap():
229 > def releasewrap():
229 > l.held = False # ensure __del__ is a noop
230 > l.held = False # ensure __del__ is a noop
230 > raise error.Abort(b"forced lock failure")
231 > raise error.Abort(b"forced lock failure")
231 > l = orig(vfs, lockname, wait, releasewrap, *args, **kwargs)
232 > l = orig(vfs, lockname, wait, releasewrap, *args, **kwargs)
232 > return l
233 > return l
233 >
234 >
234 > def reposetup(ui, repo):
235 > def reposetup(ui, repo):
235 > extensions.wrapfunction(repo, '_lock', lockexception)
236 > extensions.wrapfunction(repo, '_lock', lockexception)
236 >
237 >
237 > cmdtable = {}
238 > cmdtable = {}
238 >
239 >
239 > # wrap "commit" command to prevent wlock from being '__del__()'-ed
240 > # wrap "commit" command to prevent wlock from being '__del__()'-ed
240 > # at the end of dispatching (for intentional "forced lcok failure")
241 > # at the end of dispatching (for intentional "forced lcok failure")
241 > def commitwrap(orig, ui, repo, *pats, **opts):
242 > def commitwrap(orig, ui, repo, *pats, **opts):
242 > repo = repo.unfiltered() # to use replaced repo._lock certainly
243 > repo = repo.unfiltered() # to use replaced repo._lock certainly
243 > wlock = repo.wlock()
244 > wlock = repo.wlock()
244 > try:
245 > try:
245 > return orig(ui, repo, *pats, **opts)
246 > return orig(ui, repo, *pats, **opts)
246 > finally:
247 > finally:
247 > # multiple 'relase()' is needed for complete releasing wlock,
248 > # multiple 'relase()' is needed for complete releasing wlock,
248 > # because "forced" abort at last releasing store lock
249 > # because "forced" abort at last releasing store lock
249 > # prevents wlock from being released at same 'lockmod.release()'
250 > # prevents wlock from being released at same 'lockmod.release()'
250 > for i in range(wlock.held):
251 > for i in range(wlock.held):
251 > wlock.release()
252 > wlock.release()
252 >
253 >
253 > def extsetup(ui):
254 > def extsetup(ui):
254 > extensions.wrapcommand(commands.table, b"commit", commitwrap)
255 > extensions.wrapcommand(commands.table, b"commit", commitwrap)
255 > EOF
256 > EOF
256 $ extpath=`pwd`/exceptionext.py
257 $ extpath=`pwd`/exceptionext.py
257 $ hg init fncachetxn
258 $ hg init fncachetxn
258 $ cd fncachetxn
259 $ cd fncachetxn
259 $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc
260 $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc
260 $ touch y
261 $ touch y
261 $ hg ci -qAm y
262 $ hg ci -qAm y
262 abort: forced lock failure
263 abort: forced lock failure
263 [255]
264 [255]
264 $ cat .hg/store/fncache
265 $ cat .hg/store/fncache
265 data/y.i
266 data/y.i
266
267
267 Aborting transaction prevents fncache change
268 Aborting transaction prevents fncache change
268
269
269 $ cat > ../exceptionext.py <<EOF
270 $ cat > ../exceptionext.py <<EOF
270 > import os
271 > import os
271 > from mercurial import commands, error, extensions, localrepo
272 > from mercurial import commands, error, extensions, localrepo
272 >
273 >
273 > def wrapper(orig, self, *args, **kwargs):
274 > def wrapper(orig, self, *args, **kwargs):
274 > tr = orig(self, *args, **kwargs)
275 > tr = orig(self, *args, **kwargs)
275 > def fail(tr):
276 > def fail(tr):
276 > raise error.Abort(b"forced transaction failure")
277 > raise error.Abort(b"forced transaction failure")
277 > # zzz prefix to ensure it sorted after store.write
278 > # zzz prefix to ensure it sorted after store.write
278 > tr.addfinalize(b'zzz-forcefails', fail)
279 > tr.addfinalize(b'zzz-forcefails', fail)
279 > return tr
280 > return tr
280 >
281 >
281 > def uisetup(ui):
282 > def uisetup(ui):
282 > extensions.wrapfunction(
283 > extensions.wrapfunction(
283 > localrepo.localrepository, b'transaction', wrapper)
284 > localrepo.localrepository, b'transaction', wrapper)
284 >
285 >
285 > cmdtable = {}
286 > cmdtable = {}
286 >
287 >
287 > EOF
288 > EOF
288
289
289 Clean cached version
290 Clean cached version
290 $ rm -f "${extpath}c"
291 $ rm -f "${extpath}c"
291 $ rm -Rf "`dirname $extpath`/__pycache__"
292 $ rm -Rf "`dirname $extpath`/__pycache__"
292
293
293 $ touch z
294 $ touch z
294 $ hg ci -qAm z
295 $ hg ci -qAm z
295 transaction abort!
296 transaction abort!
296 rollback completed
297 rollback completed
297 abort: forced transaction failure
298 abort: forced transaction failure
298 [255]
299 [255]
299 $ cat .hg/store/fncache
300 $ cat .hg/store/fncache
300 data/y.i
301 data/y.i
301
302
302 Aborted transactions can be recovered later
303 Aborted transactions can be recovered later
303
304
304 $ cat > ../exceptionext.py <<EOF
305 $ cat > ../exceptionext.py <<EOF
305 > import os
306 > import os
306 > from mercurial import (
307 > from mercurial import (
307 > commands,
308 > commands,
308 > error,
309 > error,
309 > extensions,
310 > extensions,
310 > localrepo,
311 > localrepo,
311 > transaction,
312 > transaction,
312 > )
313 > )
313 >
314 >
314 > def trwrapper(orig, self, *args, **kwargs):
315 > def trwrapper(orig, self, *args, **kwargs):
315 > tr = orig(self, *args, **kwargs)
316 > tr = orig(self, *args, **kwargs)
316 > def fail(tr):
317 > def fail(tr):
317 > raise error.Abort(b"forced transaction failure")
318 > raise error.Abort(b"forced transaction failure")
318 > # zzz prefix to ensure it sorted after store.write
319 > # zzz prefix to ensure it sorted after store.write
319 > tr.addfinalize(b'zzz-forcefails', fail)
320 > tr.addfinalize(b'zzz-forcefails', fail)
320 > return tr
321 > return tr
321 >
322 >
322 > def abortwrapper(orig, self, *args, **kwargs):
323 > def abortwrapper(orig, self, *args, **kwargs):
323 > raise error.Abort(b"forced transaction failure")
324 > raise error.Abort(b"forced transaction failure")
324 >
325 >
325 > def uisetup(ui):
326 > def uisetup(ui):
326 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
327 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
327 > trwrapper)
328 > trwrapper)
328 > extensions.wrapfunction(transaction.transaction, '_abort',
329 > extensions.wrapfunction(transaction.transaction, '_abort',
329 > abortwrapper)
330 > abortwrapper)
330 >
331 >
331 > cmdtable = {}
332 > cmdtable = {}
332 >
333 >
333 > EOF
334 > EOF
334
335
335 Clean cached versions
336 Clean cached versions
336 $ rm -f "${extpath}c"
337 $ rm -f "${extpath}c"
337 $ rm -Rf "`dirname $extpath`/__pycache__"
338 $ rm -Rf "`dirname $extpath`/__pycache__"
338
339
339 $ hg up -q 1
340 $ hg up -q 1
340 $ touch z
341 $ touch z
341 $ hg ci -qAm z 2>/dev/null
342 $ hg ci -qAm z 2>/dev/null
342 [255]
343 [255]
343 $ cat .hg/store/fncache | sort
344 $ cat .hg/store/fncache | sort
344 data/y.i
345 data/y.i
345 data/z.i
346 data/z.i
346 $ hg recover --verify
347 $ hg recover --verify
347 rolling back interrupted transaction
348 rolling back interrupted transaction
348 checking changesets
349 checking changesets
349 checking manifests
350 checking manifests
350 crosschecking files in changesets and manifests
351 crosschecking files in changesets and manifests
351 checking files
352 checking files
353 checking dirstate
352 checked 1 changesets with 1 changes to 1 files
354 checked 1 changesets with 1 changes to 1 files
353 $ cat .hg/store/fncache
355 $ cat .hg/store/fncache
354 data/y.i
356 data/y.i
355
357
356 $ cd ..
358 $ cd ..
357
359
358 debugrebuildfncache does nothing unless repo has fncache requirement
360 debugrebuildfncache does nothing unless repo has fncache requirement
359
361
360 $ hg --config format.usefncache=false init nofncache
362 $ hg --config format.usefncache=false init nofncache
361 $ cd nofncache
363 $ cd nofncache
362 $ hg debugrebuildfncache
364 $ hg debugrebuildfncache
363 (not rebuilding fncache because repository does not support fncache)
365 (not rebuilding fncache because repository does not support fncache)
364
366
365 $ cd ..
367 $ cd ..
366
368
367 debugrebuildfncache works on empty repository
369 debugrebuildfncache works on empty repository
368
370
369 $ hg init empty
371 $ hg init empty
370 $ cd empty
372 $ cd empty
371 $ hg debugrebuildfncache
373 $ hg debugrebuildfncache
372 fncache already up to date
374 fncache already up to date
373 $ cd ..
375 $ cd ..
374
376
375 debugrebuildfncache on an up to date repository no-ops
377 debugrebuildfncache on an up to date repository no-ops
376
378
377 $ hg init repo
379 $ hg init repo
378 $ cd repo
380 $ cd repo
379 $ echo initial > foo
381 $ echo initial > foo
380 $ echo initial > .bar
382 $ echo initial > .bar
381 $ hg commit -A -m initial
383 $ hg commit -A -m initial
382 adding .bar
384 adding .bar
383 adding foo
385 adding foo
384
386
385 $ cat .hg/store/fncache | sort
387 $ cat .hg/store/fncache | sort
386 data/.bar.i
388 data/.bar.i
387 data/foo.i
389 data/foo.i
388
390
389 $ hg debugrebuildfncache
391 $ hg debugrebuildfncache
390 fncache already up to date
392 fncache already up to date
391
393
392 debugrebuildfncache restores deleted fncache file
394 debugrebuildfncache restores deleted fncache file
393
395
394 $ rm -f .hg/store/fncache
396 $ rm -f .hg/store/fncache
395 $ hg debugrebuildfncache
397 $ hg debugrebuildfncache
396 adding data/.bar.i
398 adding data/.bar.i
397 adding data/foo.i
399 adding data/foo.i
398 2 items added, 0 removed from fncache
400 2 items added, 0 removed from fncache
399
401
400 $ cat .hg/store/fncache | sort
402 $ cat .hg/store/fncache | sort
401 data/.bar.i
403 data/.bar.i
402 data/foo.i
404 data/foo.i
403
405
404 Rebuild after rebuild should no-op
406 Rebuild after rebuild should no-op
405
407
406 $ hg debugrebuildfncache
408 $ hg debugrebuildfncache
407 fncache already up to date
409 fncache already up to date
408
410
409 A single missing file should get restored, an extra file should be removed
411 A single missing file should get restored, an extra file should be removed
410
412
411 $ cat > .hg/store/fncache << EOF
413 $ cat > .hg/store/fncache << EOF
412 > data/foo.i
414 > data/foo.i
413 > data/bad-entry.i
415 > data/bad-entry.i
414 > EOF
416 > EOF
415
417
416 $ hg debugrebuildfncache
418 $ hg debugrebuildfncache
417 removing data/bad-entry.i
419 removing data/bad-entry.i
418 adding data/.bar.i
420 adding data/.bar.i
419 1 items added, 1 removed from fncache
421 1 items added, 1 removed from fncache
420
422
421 $ cat .hg/store/fncache | sort
423 $ cat .hg/store/fncache | sort
422 data/.bar.i
424 data/.bar.i
423 data/foo.i
425 data/foo.i
424
426
425 debugrebuildfncache recovers from truncated line in fncache
427 debugrebuildfncache recovers from truncated line in fncache
426
428
427 $ printf a > .hg/store/fncache
429 $ printf a > .hg/store/fncache
428 $ hg debugrebuildfncache
430 $ hg debugrebuildfncache
429 fncache does not ends with a newline
431 fncache does not ends with a newline
430 adding data/.bar.i
432 adding data/.bar.i
431 adding data/foo.i
433 adding data/foo.i
432 2 items added, 0 removed from fncache
434 2 items added, 0 removed from fncache
433
435
434 $ cat .hg/store/fncache | sort
436 $ cat .hg/store/fncache | sort
435 data/.bar.i
437 data/.bar.i
436 data/foo.i
438 data/foo.i
437
439
438 $ cd ..
440 $ cd ..
439
441
440 Try a simple variation without dotencode to ensure fncache is ignorant of encoding
442 Try a simple variation without dotencode to ensure fncache is ignorant of encoding
441
443
442 $ hg --config format.dotencode=false init nodotencode
444 $ hg --config format.dotencode=false init nodotencode
443 $ cd nodotencode
445 $ cd nodotencode
444 $ echo initial > foo
446 $ echo initial > foo
445 $ echo initial > .bar
447 $ echo initial > .bar
446 $ hg commit -A -m initial
448 $ hg commit -A -m initial
447 adding .bar
449 adding .bar
448 adding foo
450 adding foo
449
451
450 $ cat .hg/store/fncache | sort
452 $ cat .hg/store/fncache | sort
451 data/.bar.i
453 data/.bar.i
452 data/foo.i
454 data/foo.i
453
455
454 $ rm .hg/store/fncache
456 $ rm .hg/store/fncache
455 $ hg debugrebuildfncache
457 $ hg debugrebuildfncache
456 adding data/.bar.i
458 adding data/.bar.i
457 adding data/foo.i
459 adding data/foo.i
458 2 items added, 0 removed from fncache
460 2 items added, 0 removed from fncache
459
461
460 $ cat .hg/store/fncache | sort
462 $ cat .hg/store/fncache | sort
461 data/.bar.i
463 data/.bar.i
462 data/foo.i
464 data/foo.i
463
465
464 $ cd ..
466 $ cd ..
465
467
466 In repositories that have accumulated a large number of files over time, the
468 In repositories that have accumulated a large number of files over time, the
467 fncache file is going to be large. If we possibly can avoid loading it, so much the better.
469 fncache file is going to be large. If we possibly can avoid loading it, so much the better.
468 The cache should not loaded when committing changes to existing files, or when unbundling
470 The cache should not loaded when committing changes to existing files, or when unbundling
469 changesets that only contain changes to existing files:
471 changesets that only contain changes to existing files:
470
472
471 $ cat > fncacheloadwarn.py << EOF
473 $ cat > fncacheloadwarn.py << EOF
472 > from mercurial import extensions, localrepo
474 > from mercurial import extensions, localrepo
473 >
475 >
474 > def extsetup(ui):
476 > def extsetup(ui):
475 > def wrapstore(orig, requirements, *args):
477 > def wrapstore(orig, requirements, *args):
476 > store = orig(requirements, *args)
478 > store = orig(requirements, *args)
477 > if b'store' in requirements and b'fncache' in requirements:
479 > if b'store' in requirements and b'fncache' in requirements:
478 > instrumentfncachestore(store, ui)
480 > instrumentfncachestore(store, ui)
479 > return store
481 > return store
480 > extensions.wrapfunction(localrepo, 'makestore', wrapstore)
482 > extensions.wrapfunction(localrepo, 'makestore', wrapstore)
481 >
483 >
482 > def instrumentfncachestore(fncachestore, ui):
484 > def instrumentfncachestore(fncachestore, ui):
483 > class instrumentedfncache(type(fncachestore.fncache)):
485 > class instrumentedfncache(type(fncachestore.fncache)):
484 > def _load(self):
486 > def _load(self):
485 > ui.warn(b'fncache load triggered!\n')
487 > ui.warn(b'fncache load triggered!\n')
486 > super(instrumentedfncache, self)._load()
488 > super(instrumentedfncache, self)._load()
487 > fncachestore.fncache.__class__ = instrumentedfncache
489 > fncachestore.fncache.__class__ = instrumentedfncache
488 > EOF
490 > EOF
489
491
490 $ fncachextpath=`pwd`/fncacheloadwarn.py
492 $ fncachextpath=`pwd`/fncacheloadwarn.py
491 $ hg init nofncacheload
493 $ hg init nofncacheload
492 $ cd nofncacheload
494 $ cd nofncacheload
493 $ printf "[extensions]\nfncacheloadwarn=$fncachextpath\n" >> .hg/hgrc
495 $ printf "[extensions]\nfncacheloadwarn=$fncachextpath\n" >> .hg/hgrc
494
496
495 A new file should trigger a load, as we'd want to update the fncache set in that case:
497 A new file should trigger a load, as we'd want to update the fncache set in that case:
496
498
497 $ touch foo
499 $ touch foo
498 $ hg ci -qAm foo
500 $ hg ci -qAm foo
499 fncache load triggered!
501 fncache load triggered!
500
502
501 But modifying that file should not:
503 But modifying that file should not:
502
504
503 $ echo bar >> foo
505 $ echo bar >> foo
504 $ hg ci -qm foo
506 $ hg ci -qm foo
505
507
506 If a transaction has been aborted, the zero-size truncated index file will
508 If a transaction has been aborted, the zero-size truncated index file will
507 not prevent the fncache from being loaded; rather than actually abort
509 not prevent the fncache from being loaded; rather than actually abort
508 a transaction, we simulate the situation by creating a zero-size index file:
510 a transaction, we simulate the situation by creating a zero-size index file:
509
511
510 $ touch .hg/store/data/bar.i
512 $ touch .hg/store/data/bar.i
511 $ touch bar
513 $ touch bar
512 $ hg ci -qAm bar
514 $ hg ci -qAm bar
513 fncache load triggered!
515 fncache load triggered!
514
516
515 Unbundling should follow the same rules; existing files should not cause a load:
517 Unbundling should follow the same rules; existing files should not cause a load:
516
518
517 (loading during the clone is expected)
519 (loading during the clone is expected)
518 $ hg clone -q . tobundle
520 $ hg clone -q . tobundle
519 fncache load triggered!
521 fncache load triggered!
520 fncache load triggered!
522 fncache load triggered!
521
523
522 $ echo 'new line' > tobundle/bar
524 $ echo 'new line' > tobundle/bar
523 $ hg -R tobundle ci -qm bar
525 $ hg -R tobundle ci -qm bar
524 $ hg -R tobundle bundle -q barupdated.hg
526 $ hg -R tobundle bundle -q barupdated.hg
525 $ hg unbundle -q barupdated.hg
527 $ hg unbundle -q barupdated.hg
526
528
527 but adding new files should:
529 but adding new files should:
528
530
529 $ touch tobundle/newfile
531 $ touch tobundle/newfile
530 $ hg -R tobundle ci -qAm newfile
532 $ hg -R tobundle ci -qAm newfile
531 $ hg -R tobundle bundle -q newfile.hg
533 $ hg -R tobundle bundle -q newfile.hg
532 $ hg unbundle -q newfile.hg
534 $ hg unbundle -q newfile.hg
533 fncache load triggered!
535 fncache load triggered!
534
536
535 $ cd ..
537 $ cd ..
@@ -1,414 +1,415 b''
1 This file contains testcases that tend to be related to the wire protocol part
1 This file contains testcases that tend to be related to the wire protocol part
2 of largefiles.
2 of largefiles.
3
3
4 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
4 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
5 $ mkdir "${USERCACHE}"
5 $ mkdir "${USERCACHE}"
6 $ cat >> $HGRCPATH <<EOF
6 $ cat >> $HGRCPATH <<EOF
7 > [extensions]
7 > [extensions]
8 > largefiles=
8 > largefiles=
9 > purge=
9 > purge=
10 > rebase=
10 > rebase=
11 > transplant=
11 > transplant=
12 > [phases]
12 > [phases]
13 > publish=False
13 > publish=False
14 > [largefiles]
14 > [largefiles]
15 > minsize=2
15 > minsize=2
16 > patterns=glob:**.dat
16 > patterns=glob:**.dat
17 > usercache=${USERCACHE}
17 > usercache=${USERCACHE}
18 > [web]
18 > [web]
19 > allow-archive = zip
19 > allow-archive = zip
20 > [hooks]
20 > [hooks]
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
22 > EOF
22 > EOF
23
23
24
24
25 #if serve
25 #if serve
26 vanilla clients not locked out from largefiles servers on vanilla repos
26 vanilla clients not locked out from largefiles servers on vanilla repos
27 $ mkdir r1
27 $ mkdir r1
28 $ cd r1
28 $ cd r1
29 $ hg init
29 $ hg init
30 $ echo c1 > f1
30 $ echo c1 > f1
31 $ hg add f1
31 $ hg add f1
32 $ hg commit -m "m1"
32 $ hg commit -m "m1"
33 Invoking status precommit hook
33 Invoking status precommit hook
34 A f1
34 A f1
35 $ cd ..
35 $ cd ..
36 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
36 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
37 $ cat hg.pid >> $DAEMON_PIDS
37 $ cat hg.pid >> $DAEMON_PIDS
38 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
38 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
39 requesting all changes
39 requesting all changes
40 adding changesets
40 adding changesets
41 adding manifests
41 adding manifests
42 adding file changes
42 adding file changes
43 added 1 changesets with 1 changes to 1 files
43 added 1 changesets with 1 changes to 1 files
44 new changesets b6eb3a2e2efe (1 drafts)
44 new changesets b6eb3a2e2efe (1 drafts)
45 updating to branch default
45 updating to branch default
46 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47
47
48 largefiles clients still work with vanilla servers
48 largefiles clients still work with vanilla servers
49 $ hg serve --config extensions.largefiles=! -R r1 -d -p $HGPORT1 --pid-file hg.pid
49 $ hg serve --config extensions.largefiles=! -R r1 -d -p $HGPORT1 --pid-file hg.pid
50 $ cat hg.pid >> $DAEMON_PIDS
50 $ cat hg.pid >> $DAEMON_PIDS
51 $ hg clone http://localhost:$HGPORT1 r3
51 $ hg clone http://localhost:$HGPORT1 r3
52 requesting all changes
52 requesting all changes
53 adding changesets
53 adding changesets
54 adding manifests
54 adding manifests
55 adding file changes
55 adding file changes
56 added 1 changesets with 1 changes to 1 files
56 added 1 changesets with 1 changes to 1 files
57 new changesets b6eb3a2e2efe (1 drafts)
57 new changesets b6eb3a2e2efe (1 drafts)
58 updating to branch default
58 updating to branch default
59 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 #endif
60 #endif
61
61
62 vanilla clients locked out from largefiles http repos
62 vanilla clients locked out from largefiles http repos
63 $ mkdir r4
63 $ mkdir r4
64 $ cd r4
64 $ cd r4
65 $ hg init
65 $ hg init
66 $ echo c1 > f1
66 $ echo c1 > f1
67 $ hg add --large f1
67 $ hg add --large f1
68 $ hg commit -m "m1"
68 $ hg commit -m "m1"
69 Invoking status precommit hook
69 Invoking status precommit hook
70 A f1
70 A f1
71 $ cd ..
71 $ cd ..
72
72
73 largefiles can be pushed locally (issue3583)
73 largefiles can be pushed locally (issue3583)
74 $ hg init dest
74 $ hg init dest
75 $ cd r4
75 $ cd r4
76 $ hg outgoing ../dest
76 $ hg outgoing ../dest
77 comparing with ../dest
77 comparing with ../dest
78 searching for changes
78 searching for changes
79 changeset: 0:639881c12b4c
79 changeset: 0:639881c12b4c
80 tag: tip
80 tag: tip
81 user: test
81 user: test
82 date: Thu Jan 01 00:00:00 1970 +0000
82 date: Thu Jan 01 00:00:00 1970 +0000
83 summary: m1
83 summary: m1
84
84
85 $ hg push ../dest
85 $ hg push ../dest
86 pushing to ../dest
86 pushing to ../dest
87 searching for changes
87 searching for changes
88 adding changesets
88 adding changesets
89 adding manifests
89 adding manifests
90 adding file changes
90 adding file changes
91 added 1 changesets with 1 changes to 1 files
91 added 1 changesets with 1 changes to 1 files
92
92
93 exit code with nothing outgoing (issue3611)
93 exit code with nothing outgoing (issue3611)
94 $ hg outgoing ../dest
94 $ hg outgoing ../dest
95 comparing with ../dest
95 comparing with ../dest
96 searching for changes
96 searching for changes
97 no changes found
97 no changes found
98 [1]
98 [1]
99 $ cd ..
99 $ cd ..
100
100
101 #if serve
101 #if serve
102 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
102 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
103 $ cat hg.pid >> $DAEMON_PIDS
103 $ cat hg.pid >> $DAEMON_PIDS
104 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
104 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
105 abort: remote error:
105 abort: remote error:
106
106
107 This repository uses the largefiles extension.
107 This repository uses the largefiles extension.
108
108
109 Please enable it in your Mercurial config file.
109 Please enable it in your Mercurial config file.
110 [100]
110 [100]
111
111
112 used all HGPORTs, kill all daemons
112 used all HGPORTs, kill all daemons
113 $ killdaemons.py
113 $ killdaemons.py
114 #endif
114 #endif
115
115
116 vanilla clients locked out from largefiles ssh repos
116 vanilla clients locked out from largefiles ssh repos
117 $ hg --config extensions.largefiles=! clone ssh://user@dummy/r4 r5
117 $ hg --config extensions.largefiles=! clone ssh://user@dummy/r4 r5
118 remote:
118 remote:
119 remote: This repository uses the largefiles extension.
119 remote: This repository uses the largefiles extension.
120 remote:
120 remote:
121 remote: Please enable it in your Mercurial config file.
121 remote: Please enable it in your Mercurial config file.
122 remote:
122 remote:
123 remote: -
123 remote: -
124 abort: remote error
124 abort: remote error
125 (check previous remote output)
125 (check previous remote output)
126 [100]
126 [100]
127
127
128 #if serve
128 #if serve
129
129
130 largefiles clients refuse to push largefiles repos to vanilla servers
130 largefiles clients refuse to push largefiles repos to vanilla servers
131 $ mkdir r6
131 $ mkdir r6
132 $ cd r6
132 $ cd r6
133 $ hg init
133 $ hg init
134 $ echo c1 > f1
134 $ echo c1 > f1
135 $ hg add f1
135 $ hg add f1
136 $ hg commit -m "m1"
136 $ hg commit -m "m1"
137 Invoking status precommit hook
137 Invoking status precommit hook
138 A f1
138 A f1
139 $ cat >> .hg/hgrc <<!
139 $ cat >> .hg/hgrc <<!
140 > [web]
140 > [web]
141 > push_ssl = false
141 > push_ssl = false
142 > allow_push = *
142 > allow_push = *
143 > !
143 > !
144 $ cd ..
144 $ cd ..
145 $ hg clone r6 r7
145 $ hg clone r6 r7
146 updating to branch default
146 updating to branch default
147 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
148 $ cd r7
148 $ cd r7
149 $ echo c2 > f2
149 $ echo c2 > f2
150 $ hg add --large f2
150 $ hg add --large f2
151 $ hg commit -m "m2"
151 $ hg commit -m "m2"
152 Invoking status precommit hook
152 Invoking status precommit hook
153 A f2
153 A f2
154 $ hg verify --large -q
154 $ hg verify --large -q
155 $ hg serve --config extensions.largefiles=! -R ../r6 -d -p $HGPORT --pid-file ../hg.pid
155 $ hg serve --config extensions.largefiles=! -R ../r6 -d -p $HGPORT --pid-file ../hg.pid
156 $ cat ../hg.pid >> $DAEMON_PIDS
156 $ cat ../hg.pid >> $DAEMON_PIDS
157 $ hg push http://localhost:$HGPORT
157 $ hg push http://localhost:$HGPORT
158 pushing to http://localhost:$HGPORT/
158 pushing to http://localhost:$HGPORT/
159 searching for changes
159 searching for changes
160 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
160 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
161 [255]
161 [255]
162 $ cd ..
162 $ cd ..
163
163
164 putlfile errors are shown (issue3123)
164 putlfile errors are shown (issue3123)
165 Corrupt the cached largefile in r7 and move it out of the servers usercache
165 Corrupt the cached largefile in r7 and move it out of the servers usercache
166 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
166 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
167 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
167 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
168 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
168 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
169 $ hg init empty
169 $ hg init empty
170 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
170 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
171 > --config 'web.allow_push=*' --config web.push_ssl=False
171 > --config 'web.allow_push=*' --config web.push_ssl=False
172 $ cat hg.pid >> $DAEMON_PIDS
172 $ cat hg.pid >> $DAEMON_PIDS
173 $ hg push -R r7 http://localhost:$HGPORT1
173 $ hg push -R r7 http://localhost:$HGPORT1
174 pushing to http://localhost:$HGPORT1/
174 pushing to http://localhost:$HGPORT1/
175 searching for changes
175 searching for changes
176 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
176 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
177 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
177 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
178 [255]
178 [255]
179 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
179 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
180 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
180 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
181 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
181 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
182 $ hg push -R r7 http://localhost:$HGPORT1
182 $ hg push -R r7 http://localhost:$HGPORT1
183 pushing to http://localhost:$HGPORT1/
183 pushing to http://localhost:$HGPORT1/
184 searching for changes
184 searching for changes
185 remote: adding changesets
185 remote: adding changesets
186 remote: adding manifests
186 remote: adding manifests
187 remote: adding file changes
187 remote: adding file changes
188 remote: added 2 changesets with 2 changes to 2 files
188 remote: added 2 changesets with 2 changes to 2 files
189 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
189 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
190 server side corruption
190 server side corruption
191 $ rm -rf empty
191 $ rm -rf empty
192
192
193 Push a largefiles repository to a served empty repository
193 Push a largefiles repository to a served empty repository
194 $ hg init r8
194 $ hg init r8
195 $ echo c3 > r8/f1
195 $ echo c3 > r8/f1
196 $ hg add --large r8/f1 -R r8
196 $ hg add --large r8/f1 -R r8
197 $ hg commit -m "m1" -R r8
197 $ hg commit -m "m1" -R r8
198 Invoking status precommit hook
198 Invoking status precommit hook
199 A f1
199 A f1
200 $ hg init empty
200 $ hg init empty
201 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
201 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
202 > --config 'web.allow_push=*' --config web.push_ssl=False
202 > --config 'web.allow_push=*' --config web.push_ssl=False
203 $ cat hg.pid >> $DAEMON_PIDS
203 $ cat hg.pid >> $DAEMON_PIDS
204 $ rm "${USERCACHE}"/*
204 $ rm "${USERCACHE}"/*
205 $ hg push -R r8 http://localhost:$HGPORT2/#default
205 $ hg push -R r8 http://localhost:$HGPORT2/#default
206 pushing to http://localhost:$HGPORT2/
206 pushing to http://localhost:$HGPORT2/
207 searching for changes
207 searching for changes
208 remote: adding changesets
208 remote: adding changesets
209 remote: adding manifests
209 remote: adding manifests
210 remote: adding file changes
210 remote: adding file changes
211 remote: added 1 changesets with 1 changes to 1 files
211 remote: added 1 changesets with 1 changes to 1 files
212 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
212 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
213 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
213 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
214
214
215 Clone over http, no largefiles pulled on clone.
215 Clone over http, no largefiles pulled on clone.
216
216
217 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
217 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
218 adding changesets
218 adding changesets
219 adding manifests
219 adding manifests
220 adding file changes
220 adding file changes
221 added 1 changesets with 1 changes to 1 files
221 added 1 changesets with 1 changes to 1 files
222 new changesets cf03e5bb9936 (1 drafts)
222 new changesets cf03e5bb9936 (1 drafts)
223
223
224 Archive contains largefiles
224 Archive contains largefiles
225 >>> import os
225 >>> import os
226 >>> from mercurial import urllibcompat
226 >>> from mercurial import urllibcompat
227 >>> u = 'http://localhost:%s/archive/default.zip' % os.environ['HGPORT2']
227 >>> u = 'http://localhost:%s/archive/default.zip' % os.environ['HGPORT2']
228 >>> with open('archive.zip', 'wb') as f:
228 >>> with open('archive.zip', 'wb') as f:
229 ... f.write(urllibcompat.urlreq.urlopen(u).read()) and None
229 ... f.write(urllibcompat.urlreq.urlopen(u).read()) and None
230 $ unzip -t archive.zip
230 $ unzip -t archive.zip
231 Archive: archive.zip
231 Archive: archive.zip
232 testing: empty-default/.hg_archival.txt*OK (glob)
232 testing: empty-default/.hg_archival.txt*OK (glob)
233 testing: empty-default/f1*OK (glob)
233 testing: empty-default/f1*OK (glob)
234 No errors detected in compressed data of archive.zip.
234 No errors detected in compressed data of archive.zip.
235
235
236 test 'verify' with remotestore:
236 test 'verify' with remotestore:
237
237
238 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
238 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
239 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
239 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
240 $ hg -R http-clone verify --large --lfa
240 $ hg -R http-clone verify --large --lfa
241 checking changesets
241 checking changesets
242 checking manifests
242 checking manifests
243 crosschecking files in changesets and manifests
243 crosschecking files in changesets and manifests
244 checking files
244 checking files
245 checking dirstate
245 checked 1 changesets with 1 changes to 1 files
246 checked 1 changesets with 1 changes to 1 files
246 searching 1 changesets for largefiles
247 searching 1 changesets for largefiles
247 changeset 0:cf03e5bb9936: f1 missing
248 changeset 0:cf03e5bb9936: f1 missing
248 verified existence of 1 revisions of 1 largefiles
249 verified existence of 1 revisions of 1 largefiles
249 [1]
250 [1]
250 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
251 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
251 $ hg -R http-clone -q verify --large --lfa
252 $ hg -R http-clone -q verify --large --lfa
252
253
253 largefiles pulled on update - a largefile missing on the server:
254 largefiles pulled on update - a largefile missing on the server:
254 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
255 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
255 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
256 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
256 getting changed largefiles
257 getting changed largefiles
257 f1: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 not available from http://localhost:$HGPORT2/
258 f1: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 not available from http://localhost:$HGPORT2/
258 0 largefiles updated, 0 removed
259 0 largefiles updated, 0 removed
259 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
260 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
260 $ hg -R http-clone st
261 $ hg -R http-clone st
261 ! f1
262 ! f1
262 $ hg -R http-clone up -Cqr null
263 $ hg -R http-clone up -Cqr null
263
264
264 largefiles pulled on update - a largefile corrupted on the server:
265 largefiles pulled on update - a largefile corrupted on the server:
265 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
266 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
266 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
267 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
267 getting changed largefiles
268 getting changed largefiles
268 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
269 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
269 0 largefiles updated, 0 removed
270 0 largefiles updated, 0 removed
270 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
271 $ hg -R http-clone st
272 $ hg -R http-clone st
272 ! f1
273 ! f1
273 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
274 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
274 $ [ ! -f http-clone/f1 ]
275 $ [ ! -f http-clone/f1 ]
275 $ [ ! -f http-clone-usercache ]
276 $ [ ! -f http-clone-usercache ]
276 $ hg -R http-clone verify --large --lfc -q
277 $ hg -R http-clone verify --large --lfc -q
277 $ hg -R http-clone up -Cqr null
278 $ hg -R http-clone up -Cqr null
278
279
279 largefiles pulled on update - no server side problems:
280 largefiles pulled on update - no server side problems:
280 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
281 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
281 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache --config progress.debug=true
282 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache --config progress.debug=true
282 resolving manifests
283 resolving manifests
283 branchmerge: False, force: False, partial: False
284 branchmerge: False, force: False, partial: False
284 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
285 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
285 .hglf/f1: remote created -> g
286 .hglf/f1: remote created -> g
286 getting .hglf/f1
287 getting .hglf/f1
287 updating: .hglf/f1 1/1 files (100.00%)
288 updating: .hglf/f1 1/1 files (100.00%)
288 getting changed largefiles
289 getting changed largefiles
289 using http://localhost:$HGPORT2/
290 using http://localhost:$HGPORT2/
290 sending capabilities command
291 sending capabilities command
291 sending statlfile command
292 sending statlfile command
292 getting largefiles: 0/1 files (0.00%)
293 getting largefiles: 0/1 files (0.00%)
293 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
294 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
294 sending getlfile command
295 sending getlfile command
295 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
296 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
296 1 largefiles updated, 0 removed
297 1 largefiles updated, 0 removed
297 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
298
299
299 $ ls http-clone-usercache/*
300 $ ls http-clone-usercache/*
300 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
301 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
301
302
302 $ rm -rf empty http-clone*
303 $ rm -rf empty http-clone*
303
304
304 used all HGPORTs, kill all daemons
305 used all HGPORTs, kill all daemons
305 $ killdaemons.py
306 $ killdaemons.py
306
307
307 largefiles should batch verify remote calls
308 largefiles should batch verify remote calls
308
309
309 $ hg init batchverifymain
310 $ hg init batchverifymain
310 $ cd batchverifymain
311 $ cd batchverifymain
311 $ echo "aaa" >> a
312 $ echo "aaa" >> a
312 $ hg add --large a
313 $ hg add --large a
313 $ hg commit -m "a"
314 $ hg commit -m "a"
314 Invoking status precommit hook
315 Invoking status precommit hook
315 A a
316 A a
316 $ echo "bbb" >> b
317 $ echo "bbb" >> b
317 $ hg add --large b
318 $ hg add --large b
318 $ hg commit -m "b"
319 $ hg commit -m "b"
319 Invoking status precommit hook
320 Invoking status precommit hook
320 A b
321 A b
321 $ cd ..
322 $ cd ..
322 $ hg serve -R batchverifymain -d -p $HGPORT --pid-file hg.pid \
323 $ hg serve -R batchverifymain -d -p $HGPORT --pid-file hg.pid \
323 > -A access.log
324 > -A access.log
324 $ cat hg.pid >> $DAEMON_PIDS
325 $ cat hg.pid >> $DAEMON_PIDS
325 $ hg clone --noupdate http://localhost:$HGPORT batchverifyclone
326 $ hg clone --noupdate http://localhost:$HGPORT batchverifyclone
326 requesting all changes
327 requesting all changes
327 adding changesets
328 adding changesets
328 adding manifests
329 adding manifests
329 adding file changes
330 adding file changes
330 added 2 changesets with 2 changes to 2 files
331 added 2 changesets with 2 changes to 2 files
331 new changesets 567253b0f523:04d19c27a332 (2 drafts)
332 new changesets 567253b0f523:04d19c27a332 (2 drafts)
332 $ hg -R batchverifyclone verify --large --lfa -q
333 $ hg -R batchverifyclone verify --large --lfa -q
333 $ tail -1 access.log
334 $ tail -1 access.log
334 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=statlfile+sha%3D972a1a11f19934401291cc99117ec614933374ce%3Bstatlfile+sha%3Dc801c9cfe94400963fcb683246217d5db77f9a9a x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
335 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=statlfile+sha%3D972a1a11f19934401291cc99117ec614933374ce%3Bstatlfile+sha%3Dc801c9cfe94400963fcb683246217d5db77f9a9a x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
335 $ hg -R batchverifyclone update
336 $ hg -R batchverifyclone update
336 getting changed largefiles
337 getting changed largefiles
337 2 largefiles updated, 0 removed
338 2 largefiles updated, 0 removed
338 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
339 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
339
340
340 Clear log file before next test
341 Clear log file before next test
341
342
342 $ printf "" > access.log
343 $ printf "" > access.log
343
344
344 Verify should check file on remote server only when file is not
345 Verify should check file on remote server only when file is not
345 available locally.
346 available locally.
346
347
347 $ echo "ccc" >> batchverifymain/c
348 $ echo "ccc" >> batchverifymain/c
348 $ hg -R batchverifymain status
349 $ hg -R batchverifymain status
349 ? c
350 ? c
350 $ hg -R batchverifymain add --large batchverifymain/c
351 $ hg -R batchverifymain add --large batchverifymain/c
351 $ hg -R batchverifymain commit -m "c"
352 $ hg -R batchverifymain commit -m "c"
352 Invoking status precommit hook
353 Invoking status precommit hook
353 A c
354 A c
354 $ hg -R batchverifyclone pull
355 $ hg -R batchverifyclone pull
355 pulling from http://localhost:$HGPORT/
356 pulling from http://localhost:$HGPORT/
356 searching for changes
357 searching for changes
357 adding changesets
358 adding changesets
358 adding manifests
359 adding manifests
359 adding file changes
360 adding file changes
360 added 1 changesets with 1 changes to 1 files
361 added 1 changesets with 1 changes to 1 files
361 new changesets 6bba8cb6935d (1 drafts)
362 new changesets 6bba8cb6935d (1 drafts)
362 (run 'hg update' to get a working copy)
363 (run 'hg update' to get a working copy)
363 $ hg -R batchverifyclone verify --lfa -q
364 $ hg -R batchverifyclone verify --lfa -q
364 $ tail -1 access.log
365 $ tail -1 access.log
365 $LOCALIP - - [$LOGDATE$] "GET /?cmd=statlfile HTTP/1.1" 200 - x-hgarg-1:sha=c8559c3c9cfb42131794b7d8009230403b9b454c x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
366 $LOCALIP - - [$LOGDATE$] "GET /?cmd=statlfile HTTP/1.1" 200 - x-hgarg-1:sha=c8559c3c9cfb42131794b7d8009230403b9b454c x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
366
367
367 $ killdaemons.py
368 $ killdaemons.py
368
369
369 largefiles should not ask for password again after successful authorization
370 largefiles should not ask for password again after successful authorization
370
371
371 $ hg init credentialmain
372 $ hg init credentialmain
372 $ cd credentialmain
373 $ cd credentialmain
373 $ echo "aaa" >> a
374 $ echo "aaa" >> a
374 $ hg add --large a
375 $ hg add --large a
375 $ hg commit -m "a"
376 $ hg commit -m "a"
376 Invoking status precommit hook
377 Invoking status precommit hook
377 A a
378 A a
378
379
379 Before running server clear the user cache to force clone to download
380 Before running server clear the user cache to force clone to download
380 a large file from the server rather than to get it from the cache
381 a large file from the server rather than to get it from the cache
381
382
382 $ rm "${USERCACHE}"/*
383 $ rm "${USERCACHE}"/*
383
384
384 $ cd ..
385 $ cd ..
385
386
386 $ hg serve --config extensions.x=$TESTDIR/httpserverauth.py -R credentialmain \
387 $ hg serve --config extensions.x=$TESTDIR/httpserverauth.py -R credentialmain \
387 > -d -p $HGPORT --pid-file hg.pid -A access.log
388 > -d -p $HGPORT --pid-file hg.pid -A access.log
388 $ cat hg.pid >> $DAEMON_PIDS
389 $ cat hg.pid >> $DAEMON_PIDS
389 $ cat << EOF > get_pass.py
390 $ cat << EOF > get_pass.py
390 > from mercurial import util
391 > from mercurial import util
391 > def newgetpass():
392 > def newgetpass():
392 > return "pass"
393 > return "pass"
393 > util.get_password = newgetpass
394 > util.get_password = newgetpass
394 > EOF
395 > EOF
395 $ hg clone --config ui.interactive=true --config extensions.getpass=get_pass.py \
396 $ hg clone --config ui.interactive=true --config extensions.getpass=get_pass.py \
396 > http://user@localhost:$HGPORT credentialclone
397 > http://user@localhost:$HGPORT credentialclone
397 http authorization required for http://localhost:$HGPORT/
398 http authorization required for http://localhost:$HGPORT/
398 realm: mercurial
399 realm: mercurial
399 user: user
400 user: user
400 password: requesting all changes
401 password: requesting all changes
401 adding changesets
402 adding changesets
402 adding manifests
403 adding manifests
403 adding file changes
404 adding file changes
404 added 1 changesets with 1 changes to 1 files
405 added 1 changesets with 1 changes to 1 files
405 new changesets 567253b0f523 (1 drafts)
406 new changesets 567253b0f523 (1 drafts)
406 updating to branch default
407 updating to branch default
407 getting changed largefiles
408 getting changed largefiles
408 1 largefiles updated, 0 removed
409 1 largefiles updated, 0 removed
409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410
411
411 $ killdaemons.py
412 $ killdaemons.py
412 $ rm hg.pid access.log
413 $ rm hg.pid access.log
413
414
414 #endif
415 #endif
@@ -1,1878 +1,1879 b''
1 This file used to contains all largefile tests.
1 This file used to contains all largefile tests.
2 Do not add any new tests in this file as it his already far too long to run.
2 Do not add any new tests in this file as it his already far too long to run.
3
3
4 It contains all the testing of the basic concepts of large file in a single block.
4 It contains all the testing of the basic concepts of large file in a single block.
5
5
6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
7 $ mkdir "${USERCACHE}"
7 $ mkdir "${USERCACHE}"
8 $ cat >> $HGRCPATH <<EOF
8 $ cat >> $HGRCPATH <<EOF
9 > [extensions]
9 > [extensions]
10 > largefiles=
10 > largefiles=
11 > purge=
11 > purge=
12 > rebase=
12 > rebase=
13 > transplant=
13 > transplant=
14 > [phases]
14 > [phases]
15 > publish=False
15 > publish=False
16 > [largefiles]
16 > [largefiles]
17 > minsize=2
17 > minsize=2
18 > patterns=glob:**.dat
18 > patterns=glob:**.dat
19 > usercache=${USERCACHE}
19 > usercache=${USERCACHE}
20 > [hooks]
20 > [hooks]
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
22 > EOF
22 > EOF
23
23
24 Create the repo with a couple of revisions of both large and normal
24 Create the repo with a couple of revisions of both large and normal
25 files.
25 files.
26 Test status and dirstate of largefiles and that summary output is correct.
26 Test status and dirstate of largefiles and that summary output is correct.
27
27
28 $ hg init a
28 $ hg init a
29 $ cd a
29 $ cd a
30 $ mkdir sub
30 $ mkdir sub
31 $ echo normal1 > normal1
31 $ echo normal1 > normal1
32 $ echo normal2 > sub/normal2
32 $ echo normal2 > sub/normal2
33 $ echo large1 > large1
33 $ echo large1 > large1
34 $ echo large2 > sub/large2
34 $ echo large2 > sub/large2
35 $ hg add normal1 sub/normal2
35 $ hg add normal1 sub/normal2
36 $ hg add --large large1 sub/large2
36 $ hg add --large large1 sub/large2
37 $ hg commit -m "add files"
37 $ hg commit -m "add files"
38 Invoking status precommit hook
38 Invoking status precommit hook
39 A large1
39 A large1
40 A normal1
40 A normal1
41 A sub/large2
41 A sub/large2
42 A sub/normal2
42 A sub/normal2
43 $ touch large1 sub/large2
43 $ touch large1 sub/large2
44 $ sleep 1
44 $ sleep 1
45 $ hg st
45 $ hg st
46 $ hg debugstate --no-dates
46 $ hg debugstate --no-dates
47 n 644 41 set .hglf/large1
47 n 644 41 set .hglf/large1
48 n 644 41 set .hglf/sub/large2
48 n 644 41 set .hglf/sub/large2
49 n 644 8 set normal1
49 n 644 8 set normal1
50 n 644 8 set sub/normal2
50 n 644 8 set sub/normal2
51 $ hg debugstate --large --no-dates
51 $ hg debugstate --large --no-dates
52 n 644 7 set large1
52 n 644 7 set large1
53 n 644 7 set sub/large2
53 n 644 7 set sub/large2
54 $ echo normal11 > normal1
54 $ echo normal11 > normal1
55 $ echo normal22 > sub/normal2
55 $ echo normal22 > sub/normal2
56 $ echo large11 > large1
56 $ echo large11 > large1
57 $ echo large22 > sub/large2
57 $ echo large22 > sub/large2
58 $ hg commit -m "edit files"
58 $ hg commit -m "edit files"
59 Invoking status precommit hook
59 Invoking status precommit hook
60 M large1
60 M large1
61 M normal1
61 M normal1
62 M sub/large2
62 M sub/large2
63 M sub/normal2
63 M sub/normal2
64 $ hg sum --large
64 $ hg sum --large
65 parent: 1:ce8896473775 tip
65 parent: 1:ce8896473775 tip
66 edit files
66 edit files
67 branch: default
67 branch: default
68 commit: (clean)
68 commit: (clean)
69 update: (current)
69 update: (current)
70 phases: 2 draft
70 phases: 2 draft
71 largefiles: (no remote repo)
71 largefiles: (no remote repo)
72
72
73 Commit preserved largefile contents.
73 Commit preserved largefile contents.
74
74
75 $ cat normal1
75 $ cat normal1
76 normal11
76 normal11
77 $ cat large1
77 $ cat large1
78 large11
78 large11
79 $ cat sub/normal2
79 $ cat sub/normal2
80 normal22
80 normal22
81 $ cat sub/large2
81 $ cat sub/large2
82 large22
82 large22
83
83
84 Test status, subdir and unknown files
84 Test status, subdir and unknown files
85
85
86 $ echo unknown > sub/unknown
86 $ echo unknown > sub/unknown
87 $ hg st --all
87 $ hg st --all
88 ? sub/unknown
88 ? sub/unknown
89 C large1
89 C large1
90 C normal1
90 C normal1
91 C sub/large2
91 C sub/large2
92 C sub/normal2
92 C sub/normal2
93 $ hg st --all sub
93 $ hg st --all sub
94 ? sub/unknown
94 ? sub/unknown
95 C sub/large2
95 C sub/large2
96 C sub/normal2
96 C sub/normal2
97 $ rm sub/unknown
97 $ rm sub/unknown
98
98
99 Test messages and exit codes for remove warning cases
99 Test messages and exit codes for remove warning cases
100
100
101 $ hg remove -A large1
101 $ hg remove -A large1
102 not removing large1: file still exists
102 not removing large1: file still exists
103 [1]
103 [1]
104 $ echo 'modified' > large1
104 $ echo 'modified' > large1
105 $ hg remove large1
105 $ hg remove large1
106 not removing large1: file is modified (use -f to force removal)
106 not removing large1: file is modified (use -f to force removal)
107 [1]
107 [1]
108 $ echo 'new' > normalnew
108 $ echo 'new' > normalnew
109 $ hg add normalnew
109 $ hg add normalnew
110 $ echo 'new' > largenew
110 $ echo 'new' > largenew
111 $ hg add --large normalnew
111 $ hg add --large normalnew
112 normalnew already tracked!
112 normalnew already tracked!
113 $ hg remove normalnew largenew
113 $ hg remove normalnew largenew
114 not removing largenew: file is untracked
114 not removing largenew: file is untracked
115 not removing normalnew: file has been marked for add (use 'hg forget' to undo add)
115 not removing normalnew: file has been marked for add (use 'hg forget' to undo add)
116 [1]
116 [1]
117 $ rm normalnew largenew
117 $ rm normalnew largenew
118 $ hg up -Cq
118 $ hg up -Cq
119
119
120 Remove both largefiles and normal files.
120 Remove both largefiles and normal files.
121
121
122 $ hg remove normal1 large1
122 $ hg remove normal1 large1
123 $ hg status large1
123 $ hg status large1
124 R large1
124 R large1
125 $ hg commit -m "remove files"
125 $ hg commit -m "remove files"
126 Invoking status precommit hook
126 Invoking status precommit hook
127 R large1
127 R large1
128 R normal1
128 R normal1
129 $ ls -A
129 $ ls -A
130 .hg
130 .hg
131 .hglf
131 .hglf
132 sub
132 sub
133 $ echo "testlargefile" > large1-test
133 $ echo "testlargefile" > large1-test
134 $ hg add --large large1-test
134 $ hg add --large large1-test
135 $ hg st
135 $ hg st
136 A large1-test
136 A large1-test
137 $ hg rm large1-test
137 $ hg rm large1-test
138 not removing large1-test: file has been marked for add (use forget to undo)
138 not removing large1-test: file has been marked for add (use forget to undo)
139 [1]
139 [1]
140 $ hg st
140 $ hg st
141 A large1-test
141 A large1-test
142 $ hg forget large1-test
142 $ hg forget large1-test
143 $ hg st
143 $ hg st
144 ? large1-test
144 ? large1-test
145 $ hg remove large1-test
145 $ hg remove large1-test
146 not removing large1-test: file is untracked
146 not removing large1-test: file is untracked
147 [1]
147 [1]
148 $ hg forget large1-test
148 $ hg forget large1-test
149 not removing large1-test: file is already untracked
149 not removing large1-test: file is already untracked
150 [1]
150 [1]
151 $ rm large1-test
151 $ rm large1-test
152
152
153 Copy both largefiles and normal files (testing that status output is correct).
153 Copy both largefiles and normal files (testing that status output is correct).
154
154
155 $ hg cp sub/normal2 normal1
155 $ hg cp sub/normal2 normal1
156 $ hg cp sub/large2 large1
156 $ hg cp sub/large2 large1
157 $ hg commit -m "copy files"
157 $ hg commit -m "copy files"
158 Invoking status precommit hook
158 Invoking status precommit hook
159 A large1
159 A large1
160 A normal1
160 A normal1
161 $ cat normal1
161 $ cat normal1
162 normal22
162 normal22
163 $ cat large1
163 $ cat large1
164 large22
164 large22
165
165
166 Test moving largefiles and verify that normal files are also unaffected.
166 Test moving largefiles and verify that normal files are also unaffected.
167
167
168 $ hg mv normal1 normal3
168 $ hg mv normal1 normal3
169 $ hg mv large1 large3
169 $ hg mv large1 large3
170 $ hg mv sub/normal2 sub/normal4
170 $ hg mv sub/normal2 sub/normal4
171 $ hg mv sub/large2 sub/large4
171 $ hg mv sub/large2 sub/large4
172 $ hg commit -m "move files"
172 $ hg commit -m "move files"
173 Invoking status precommit hook
173 Invoking status precommit hook
174 A large3
174 A large3
175 A normal3
175 A normal3
176 A sub/large4
176 A sub/large4
177 A sub/normal4
177 A sub/normal4
178 R large1
178 R large1
179 R normal1
179 R normal1
180 R sub/large2
180 R sub/large2
181 R sub/normal2
181 R sub/normal2
182 $ cat normal3
182 $ cat normal3
183 normal22
183 normal22
184 $ cat large3
184 $ cat large3
185 large22
185 large22
186 $ cat sub/normal4
186 $ cat sub/normal4
187 normal22
187 normal22
188 $ cat sub/large4
188 $ cat sub/large4
189 large22
189 large22
190
190
191
191
192 #if serve
192 #if serve
193 Test display of largefiles in hgweb
193 Test display of largefiles in hgweb
194
194
195 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
195 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
196 $ cat ../hg.pid >> $DAEMON_PIDS
196 $ cat ../hg.pid >> $DAEMON_PIDS
197 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/?style=raw'
197 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/?style=raw'
198 200 Script output follows
198 200 Script output follows
199
199
200
200
201 drwxr-xr-x sub
201 drwxr-xr-x sub
202 -rw-r--r-- 41 large3
202 -rw-r--r-- 41 large3
203 -rw-r--r-- 9 normal3
203 -rw-r--r-- 9 normal3
204
204
205
205
206 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/sub/?style=raw'
206 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/sub/?style=raw'
207 200 Script output follows
207 200 Script output follows
208
208
209
209
210 -rw-r--r-- 41 large4
210 -rw-r--r-- 41 large4
211 -rw-r--r-- 9 normal4
211 -rw-r--r-- 9 normal4
212
212
213
213
214 $ killdaemons.py
214 $ killdaemons.py
215 #endif
215 #endif
216
216
217 Test largefiles can be loaded in hgweb (wrapcommand() shouldn't fail)
217 Test largefiles can be loaded in hgweb (wrapcommand() shouldn't fail)
218
218
219 $ cat <<EOF > "$TESTTMP/hgweb.cgi"
219 $ cat <<EOF > "$TESTTMP/hgweb.cgi"
220 > #!$PYTHON
220 > #!$PYTHON
221 > from mercurial import demandimport; demandimport.enable()
221 > from mercurial import demandimport; demandimport.enable()
222 > from mercurial.hgweb import hgweb
222 > from mercurial.hgweb import hgweb
223 > from mercurial.hgweb import wsgicgi
223 > from mercurial.hgweb import wsgicgi
224 > application = hgweb(b'.', b'test repo')
224 > application = hgweb(b'.', b'test repo')
225 > wsgicgi.launch(application)
225 > wsgicgi.launch(application)
226 > EOF
226 > EOF
227 $ . "$TESTDIR/cgienv"
227 $ . "$TESTDIR/cgienv"
228
228
229 $ SCRIPT_NAME='' \
229 $ SCRIPT_NAME='' \
230 > "$PYTHON" "$TESTTMP/hgweb.cgi" > /dev/null
230 > "$PYTHON" "$TESTTMP/hgweb.cgi" > /dev/null
231
231
232 Test archiving the various revisions. These hit corner cases known with
232 Test archiving the various revisions. These hit corner cases known with
233 archiving.
233 archiving.
234
234
235 $ hg archive -r 0 ../archive0
235 $ hg archive -r 0 ../archive0
236 $ hg archive -r 1 ../archive1
236 $ hg archive -r 1 ../archive1
237 $ hg archive -r 2 ../archive2
237 $ hg archive -r 2 ../archive2
238 $ hg archive -r 3 ../archive3
238 $ hg archive -r 3 ../archive3
239 $ hg archive -r 4 ../archive4
239 $ hg archive -r 4 ../archive4
240 $ cd ../archive0
240 $ cd ../archive0
241 $ cat normal1
241 $ cat normal1
242 normal1
242 normal1
243 $ cat large1
243 $ cat large1
244 large1
244 large1
245 $ cat sub/normal2
245 $ cat sub/normal2
246 normal2
246 normal2
247 $ cat sub/large2
247 $ cat sub/large2
248 large2
248 large2
249 $ cd ../archive1
249 $ cd ../archive1
250 $ cat normal1
250 $ cat normal1
251 normal11
251 normal11
252 $ cat large1
252 $ cat large1
253 large11
253 large11
254 $ cat sub/normal2
254 $ cat sub/normal2
255 normal22
255 normal22
256 $ cat sub/large2
256 $ cat sub/large2
257 large22
257 large22
258 $ cd ../archive2
258 $ cd ../archive2
259 $ ls -A
259 $ ls -A
260 .hg_archival.txt
260 .hg_archival.txt
261 sub
261 sub
262 $ cat sub/normal2
262 $ cat sub/normal2
263 normal22
263 normal22
264 $ cat sub/large2
264 $ cat sub/large2
265 large22
265 large22
266 $ cd ../archive3
266 $ cd ../archive3
267 $ cat normal1
267 $ cat normal1
268 normal22
268 normal22
269 $ cat large1
269 $ cat large1
270 large22
270 large22
271 $ cat sub/normal2
271 $ cat sub/normal2
272 normal22
272 normal22
273 $ cat sub/large2
273 $ cat sub/large2
274 large22
274 large22
275 $ cd ../archive4
275 $ cd ../archive4
276 $ cat normal3
276 $ cat normal3
277 normal22
277 normal22
278 $ cat large3
278 $ cat large3
279 large22
279 large22
280 $ cat sub/normal4
280 $ cat sub/normal4
281 normal22
281 normal22
282 $ cat sub/large4
282 $ cat sub/large4
283 large22
283 large22
284
284
285 Commit corner case: specify files to commit.
285 Commit corner case: specify files to commit.
286
286
287 $ cd ../a
287 $ cd ../a
288 $ echo normal3 > normal3
288 $ echo normal3 > normal3
289 $ echo large3 > large3
289 $ echo large3 > large3
290 $ echo normal4 > sub/normal4
290 $ echo normal4 > sub/normal4
291 $ echo large4 > sub/large4
291 $ echo large4 > sub/large4
292 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
292 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
293 Invoking status precommit hook
293 Invoking status precommit hook
294 M large3
294 M large3
295 M normal3
295 M normal3
296 M sub/large4
296 M sub/large4
297 M sub/normal4
297 M sub/normal4
298 $ cat normal3
298 $ cat normal3
299 normal3
299 normal3
300 $ cat large3
300 $ cat large3
301 large3
301 large3
302 $ cat sub/normal4
302 $ cat sub/normal4
303 normal4
303 normal4
304 $ cat sub/large4
304 $ cat sub/large4
305 large4
305 large4
306
306
307 One more commit corner case: commit from a subdirectory.
307 One more commit corner case: commit from a subdirectory.
308
308
309 $ cd ../a
309 $ cd ../a
310 $ echo normal33 > normal3
310 $ echo normal33 > normal3
311 $ echo large33 > large3
311 $ echo large33 > large3
312 $ echo normal44 > sub/normal4
312 $ echo normal44 > sub/normal4
313 $ echo large44 > sub/large4
313 $ echo large44 > sub/large4
314 $ cd sub
314 $ cd sub
315 $ hg commit -m "edit files yet again"
315 $ hg commit -m "edit files yet again"
316 Invoking status precommit hook
316 Invoking status precommit hook
317 M large3
317 M large3
318 M normal3
318 M normal3
319 M sub/large4
319 M sub/large4
320 M sub/normal4
320 M sub/normal4
321 $ cat ../normal3
321 $ cat ../normal3
322 normal33
322 normal33
323 $ cat ../large3
323 $ cat ../large3
324 large33
324 large33
325 $ cat normal4
325 $ cat normal4
326 normal44
326 normal44
327 $ cat large4
327 $ cat large4
328 large44
328 large44
329
329
330 Committing standins is not allowed.
330 Committing standins is not allowed.
331
331
332 $ cd ..
332 $ cd ..
333 $ echo large3 > large3
333 $ echo large3 > large3
334 $ hg commit .hglf/large3 -m "try to commit standin"
334 $ hg commit .hglf/large3 -m "try to commit standin"
335 abort: file ".hglf/large3" is a largefile standin
335 abort: file ".hglf/large3" is a largefile standin
336 (commit the largefile itself instead)
336 (commit the largefile itself instead)
337 [255]
337 [255]
338
338
339 Corner cases for adding largefiles.
339 Corner cases for adding largefiles.
340
340
341 $ echo large5 > large5
341 $ echo large5 > large5
342 $ hg add --large large5
342 $ hg add --large large5
343 $ hg add --large large5
343 $ hg add --large large5
344 large5 already a largefile
344 large5 already a largefile
345 $ mkdir sub2
345 $ mkdir sub2
346 $ echo large6 > sub2/large6
346 $ echo large6 > sub2/large6
347 $ echo large7 > sub2/large7
347 $ echo large7 > sub2/large7
348 $ hg add --large sub2
348 $ hg add --large sub2
349 adding sub2/large6 as a largefile
349 adding sub2/large6 as a largefile
350 adding sub2/large7 as a largefile
350 adding sub2/large7 as a largefile
351 $ hg st
351 $ hg st
352 M large3
352 M large3
353 A large5
353 A large5
354 A sub2/large6
354 A sub2/large6
355 A sub2/large7
355 A sub2/large7
356
356
357 Committing directories containing only largefiles.
357 Committing directories containing only largefiles.
358
358
359 $ mkdir -p z/y/x/m
359 $ mkdir -p z/y/x/m
360 $ touch z/y/x/m/large1
360 $ touch z/y/x/m/large1
361 $ touch z/y/x/large2
361 $ touch z/y/x/large2
362 $ hg add --large z/y/x/m/large1 z/y/x/large2
362 $ hg add --large z/y/x/m/large1 z/y/x/large2
363 $ hg commit -m "Subdir with directory only containing largefiles" z
363 $ hg commit -m "Subdir with directory only containing largefiles" z
364 Invoking status precommit hook
364 Invoking status precommit hook
365 M large3
365 M large3
366 A large5
366 A large5
367 A sub2/large6
367 A sub2/large6
368 A sub2/large7
368 A sub2/large7
369 A z/y/x/large2
369 A z/y/x/large2
370 A z/y/x/m/large1
370 A z/y/x/m/large1
371
371
372 (and a bit of log testing)
372 (and a bit of log testing)
373
373
374 $ hg log -T '{rev}\n' z/y/x/m/large1
374 $ hg log -T '{rev}\n' z/y/x/m/large1
375 7
375 7
376 $ hg log -T '{rev}\n' z/y/x/m # with only a largefile
376 $ hg log -T '{rev}\n' z/y/x/m # with only a largefile
377 7
377 7
378
378
379 $ hg rollback --quiet
379 $ hg rollback --quiet
380 $ touch z/y/x/m/normal
380 $ touch z/y/x/m/normal
381 $ hg add z/y/x/m/normal
381 $ hg add z/y/x/m/normal
382 $ hg commit -m "Subdir with mixed contents" z
382 $ hg commit -m "Subdir with mixed contents" z
383 Invoking status precommit hook
383 Invoking status precommit hook
384 M large3
384 M large3
385 A large5
385 A large5
386 A sub2/large6
386 A sub2/large6
387 A sub2/large7
387 A sub2/large7
388 A z/y/x/large2
388 A z/y/x/large2
389 A z/y/x/m/large1
389 A z/y/x/m/large1
390 A z/y/x/m/normal
390 A z/y/x/m/normal
391 $ hg st
391 $ hg st
392 M large3
392 M large3
393 A large5
393 A large5
394 A sub2/large6
394 A sub2/large6
395 A sub2/large7
395 A sub2/large7
396 $ hg rollback --quiet
396 $ hg rollback --quiet
397 $ hg revert z/y/x/large2 z/y/x/m/large1
397 $ hg revert z/y/x/large2 z/y/x/m/large1
398 $ rm z/y/x/large2 z/y/x/m/large1
398 $ rm z/y/x/large2 z/y/x/m/large1
399 $ hg commit -m "Subdir with normal contents" z
399 $ hg commit -m "Subdir with normal contents" z
400 Invoking status precommit hook
400 Invoking status precommit hook
401 M large3
401 M large3
402 A large5
402 A large5
403 A sub2/large6
403 A sub2/large6
404 A sub2/large7
404 A sub2/large7
405 A z/y/x/m/normal
405 A z/y/x/m/normal
406 $ hg st
406 $ hg st
407 M large3
407 M large3
408 A large5
408 A large5
409 A sub2/large6
409 A sub2/large6
410 A sub2/large7
410 A sub2/large7
411 $ hg rollback --quiet
411 $ hg rollback --quiet
412 $ hg revert --quiet z
412 $ hg revert --quiet z
413 $ hg commit -m "Empty subdir" z
413 $ hg commit -m "Empty subdir" z
414 abort: z: no match under directory!
414 abort: z: no match under directory!
415 [10]
415 [10]
416 $ rm -rf z
416 $ rm -rf z
417 $ hg ci -m "standin" .hglf
417 $ hg ci -m "standin" .hglf
418 abort: file ".hglf" is a largefile standin
418 abort: file ".hglf" is a largefile standin
419 (commit the largefile itself instead)
419 (commit the largefile itself instead)
420 [255]
420 [255]
421
421
422 Test "hg status" with combination of 'file pattern' and 'directory
422 Test "hg status" with combination of 'file pattern' and 'directory
423 pattern' for largefiles:
423 pattern' for largefiles:
424
424
425 $ hg status sub2/large6 sub2
425 $ hg status sub2/large6 sub2
426 A sub2/large6
426 A sub2/large6
427 A sub2/large7
427 A sub2/large7
428
428
429 Config settings (pattern **.dat, minsize 2 MB) are respected.
429 Config settings (pattern **.dat, minsize 2 MB) are respected.
430
430
431 $ echo testdata > test.dat
431 $ echo testdata > test.dat
432 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
432 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
433 $ hg add
433 $ hg add
434 adding reallylarge as a largefile
434 adding reallylarge as a largefile
435 adding test.dat as a largefile
435 adding test.dat as a largefile
436
436
437 Test that minsize and --lfsize handle float values;
437 Test that minsize and --lfsize handle float values;
438 also tests that --lfsize overrides largefiles.minsize.
438 also tests that --lfsize overrides largefiles.minsize.
439 (0.250 MB = 256 kB = 262144 B)
439 (0.250 MB = 256 kB = 262144 B)
440
440
441 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
441 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
442 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
442 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
443 $ hg --config largefiles.minsize=.25 add
443 $ hg --config largefiles.minsize=.25 add
444 adding ratherlarge as a largefile
444 adding ratherlarge as a largefile
445 adding medium
445 adding medium
446 $ hg forget medium
446 $ hg forget medium
447 $ hg --config largefiles.minsize=.25 add --lfsize=.125
447 $ hg --config largefiles.minsize=.25 add --lfsize=.125
448 adding medium as a largefile
448 adding medium as a largefile
449 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
449 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
450 $ hg --config largefiles.minsize=.25 add --lfsize=.125
450 $ hg --config largefiles.minsize=.25 add --lfsize=.125
451 adding notlarge
451 adding notlarge
452 $ hg forget notlarge
452 $ hg forget notlarge
453
453
454 Test forget on largefiles.
454 Test forget on largefiles.
455
455
456 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
456 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
457 $ hg commit -m "add/edit more largefiles"
457 $ hg commit -m "add/edit more largefiles"
458 Invoking status precommit hook
458 Invoking status precommit hook
459 A sub2/large6
459 A sub2/large6
460 A sub2/large7
460 A sub2/large7
461 R large3
461 R large3
462 ? large5
462 ? large5
463 ? medium
463 ? medium
464 ? notlarge
464 ? notlarge
465 ? ratherlarge
465 ? ratherlarge
466 ? reallylarge
466 ? reallylarge
467 ? test.dat
467 ? test.dat
468 $ hg st
468 $ hg st
469 ? large3
469 ? large3
470 ? large5
470 ? large5
471 ? medium
471 ? medium
472 ? notlarge
472 ? notlarge
473 ? ratherlarge
473 ? ratherlarge
474 ? reallylarge
474 ? reallylarge
475 ? test.dat
475 ? test.dat
476
476
477 Purge with largefiles: verify that largefiles are still in the working
477 Purge with largefiles: verify that largefiles are still in the working
478 dir after a purge.
478 dir after a purge.
479
479
480 $ hg purge --all
480 $ hg purge --all
481 $ cat sub/large4
481 $ cat sub/large4
482 large44
482 large44
483 $ cat sub2/large6
483 $ cat sub2/large6
484 large6
484 large6
485 $ cat sub2/large7
485 $ cat sub2/large7
486 large7
486 large7
487
487
488 Test addremove: verify that files that should be added as largefiles are added as
488 Test addremove: verify that files that should be added as largefiles are added as
489 such and that already-existing largefiles are not added as normal files by
489 such and that already-existing largefiles are not added as normal files by
490 accident.
490 accident.
491
491
492 $ rm normal3
492 $ rm normal3
493 $ rm sub/large4
493 $ rm sub/large4
494 $ echo "testing addremove with patterns" > testaddremove.dat
494 $ echo "testing addremove with patterns" > testaddremove.dat
495 $ echo "normaladdremove" > normaladdremove
495 $ echo "normaladdremove" > normaladdremove
496 $ hg addremove
496 $ hg addremove
497 removing sub/large4
497 removing sub/large4
498 adding testaddremove.dat as a largefile
498 adding testaddremove.dat as a largefile
499 removing normal3
499 removing normal3
500 adding normaladdremove
500 adding normaladdremove
501
501
502 Test addremove with -R
502 Test addremove with -R
503
503
504 $ hg up -C
504 $ hg up -C
505 getting changed largefiles
505 getting changed largefiles
506 1 largefiles updated, 0 removed
506 1 largefiles updated, 0 removed
507 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
507 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 $ rm normal3
508 $ rm normal3
509 $ rm sub/large4
509 $ rm sub/large4
510 $ echo "testing addremove with patterns" > testaddremove.dat
510 $ echo "testing addremove with patterns" > testaddremove.dat
511 $ echo "normaladdremove" > normaladdremove
511 $ echo "normaladdremove" > normaladdremove
512 $ cd ..
512 $ cd ..
513 $ hg -R a -v addremove
513 $ hg -R a -v addremove
514 removing sub/large4
514 removing sub/large4
515 adding testaddremove.dat as a largefile
515 adding testaddremove.dat as a largefile
516 removing normal3
516 removing normal3
517 adding normaladdremove
517 adding normaladdremove
518 $ cd a
518 $ cd a
519
519
520 Test 3364
520 Test 3364
521 $ hg clone . ../addrm
521 $ hg clone . ../addrm
522 updating to branch default
522 updating to branch default
523 getting changed largefiles
523 getting changed largefiles
524 3 largefiles updated, 0 removed
524 3 largefiles updated, 0 removed
525 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
525 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
526 $ cd ../addrm
526 $ cd ../addrm
527 $ cat >> .hg/hgrc <<EOF
527 $ cat >> .hg/hgrc <<EOF
528 > [hooks]
528 > [hooks]
529 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
529 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
530 > EOF
530 > EOF
531 $ touch foo
531 $ touch foo
532 $ hg add --large foo
532 $ hg add --large foo
533 $ hg ci -m "add foo"
533 $ hg ci -m "add foo"
534 Invoking status precommit hook
534 Invoking status precommit hook
535 A foo
535 A foo
536 Invoking status postcommit hook
536 Invoking status postcommit hook
537 C foo
537 C foo
538 C normal3
538 C normal3
539 C sub/large4
539 C sub/large4
540 C sub/normal4
540 C sub/normal4
541 C sub2/large6
541 C sub2/large6
542 C sub2/large7
542 C sub2/large7
543 $ rm foo
543 $ rm foo
544 $ hg st
544 $ hg st
545 ! foo
545 ! foo
546 hmm.. no precommit invoked, but there is a postcommit??
546 hmm.. no precommit invoked, but there is a postcommit??
547 $ hg ci -m "will not checkin"
547 $ hg ci -m "will not checkin"
548 nothing changed (1 missing files, see 'hg status')
548 nothing changed (1 missing files, see 'hg status')
549 Invoking status postcommit hook
549 Invoking status postcommit hook
550 ! foo
550 ! foo
551 C normal3
551 C normal3
552 C sub/large4
552 C sub/large4
553 C sub/normal4
553 C sub/normal4
554 C sub2/large6
554 C sub2/large6
555 C sub2/large7
555 C sub2/large7
556 [1]
556 [1]
557 $ hg addremove
557 $ hg addremove
558 removing foo
558 removing foo
559 $ hg st
559 $ hg st
560 R foo
560 R foo
561 $ hg ci -m "used to say nothing changed"
561 $ hg ci -m "used to say nothing changed"
562 Invoking status precommit hook
562 Invoking status precommit hook
563 R foo
563 R foo
564 Invoking status postcommit hook
564 Invoking status postcommit hook
565 C normal3
565 C normal3
566 C sub/large4
566 C sub/large4
567 C sub/normal4
567 C sub/normal4
568 C sub2/large6
568 C sub2/large6
569 C sub2/large7
569 C sub2/large7
570 $ hg st
570 $ hg st
571
571
572 Test 3507 (both normal files and largefiles were a problem)
572 Test 3507 (both normal files and largefiles were a problem)
573
573
574 $ touch normal
574 $ touch normal
575 $ touch large
575 $ touch large
576 $ hg add normal
576 $ hg add normal
577 $ hg add --large large
577 $ hg add --large large
578 $ hg ci -m "added"
578 $ hg ci -m "added"
579 Invoking status precommit hook
579 Invoking status precommit hook
580 A large
580 A large
581 A normal
581 A normal
582 Invoking status postcommit hook
582 Invoking status postcommit hook
583 C large
583 C large
584 C normal
584 C normal
585 C normal3
585 C normal3
586 C sub/large4
586 C sub/large4
587 C sub/normal4
587 C sub/normal4
588 C sub2/large6
588 C sub2/large6
589 C sub2/large7
589 C sub2/large7
590 $ hg remove normal
590 $ hg remove normal
591 $ hg addremove --traceback
591 $ hg addremove --traceback
592 $ hg ci -m "addremoved normal"
592 $ hg ci -m "addremoved normal"
593 Invoking status precommit hook
593 Invoking status precommit hook
594 R normal
594 R normal
595 Invoking status postcommit hook
595 Invoking status postcommit hook
596 C large
596 C large
597 C normal3
597 C normal3
598 C sub/large4
598 C sub/large4
599 C sub/normal4
599 C sub/normal4
600 C sub2/large6
600 C sub2/large6
601 C sub2/large7
601 C sub2/large7
602 $ hg up -C '.^'
602 $ hg up -C '.^'
603 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
603 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
604 $ hg remove large
604 $ hg remove large
605 $ hg addremove --traceback
605 $ hg addremove --traceback
606 $ hg ci -m "removed large"
606 $ hg ci -m "removed large"
607 Invoking status precommit hook
607 Invoking status precommit hook
608 R large
608 R large
609 created new head
609 created new head
610 Invoking status postcommit hook
610 Invoking status postcommit hook
611 C normal
611 C normal
612 C normal3
612 C normal3
613 C sub/large4
613 C sub/large4
614 C sub/normal4
614 C sub/normal4
615 C sub2/large6
615 C sub2/large6
616 C sub2/large7
616 C sub2/large7
617
617
618 Test commit -A (issue3542)
618 Test commit -A (issue3542)
619 $ echo large8 > large8
619 $ echo large8 > large8
620 $ hg add --large large8
620 $ hg add --large large8
621 $ hg ci -Am 'this used to add large8 as normal and commit both'
621 $ hg ci -Am 'this used to add large8 as normal and commit both'
622 Invoking status precommit hook
622 Invoking status precommit hook
623 A large8
623 A large8
624 Invoking status postcommit hook
624 Invoking status postcommit hook
625 C large8
625 C large8
626 C normal
626 C normal
627 C normal3
627 C normal3
628 C sub/large4
628 C sub/large4
629 C sub/normal4
629 C sub/normal4
630 C sub2/large6
630 C sub2/large6
631 C sub2/large7
631 C sub2/large7
632 $ rm large8
632 $ rm large8
633 $ hg ci -Am 'this used to not notice the rm'
633 $ hg ci -Am 'this used to not notice the rm'
634 removing large8
634 removing large8
635 Invoking status precommit hook
635 Invoking status precommit hook
636 R large8
636 R large8
637 Invoking status postcommit hook
637 Invoking status postcommit hook
638 C normal
638 C normal
639 C normal3
639 C normal3
640 C sub/large4
640 C sub/large4
641 C sub/normal4
641 C sub/normal4
642 C sub2/large6
642 C sub2/large6
643 C sub2/large7
643 C sub2/large7
644
644
645 Test that a standin can't be added as a large file
645 Test that a standin can't be added as a large file
646
646
647 $ touch large
647 $ touch large
648 $ hg add --large large
648 $ hg add --large large
649 $ hg ci -m "add"
649 $ hg ci -m "add"
650 Invoking status precommit hook
650 Invoking status precommit hook
651 A large
651 A large
652 Invoking status postcommit hook
652 Invoking status postcommit hook
653 C large
653 C large
654 C normal
654 C normal
655 C normal3
655 C normal3
656 C sub/large4
656 C sub/large4
657 C sub/normal4
657 C sub/normal4
658 C sub2/large6
658 C sub2/large6
659 C sub2/large7
659 C sub2/large7
660 $ hg remove large
660 $ hg remove large
661 $ touch large
661 $ touch large
662 $ hg addremove --config largefiles.patterns=**large --traceback
662 $ hg addremove --config largefiles.patterns=**large --traceback
663 adding large as a largefile
663 adding large as a largefile
664
664
665 Test that outgoing --large works (with revsets too)
665 Test that outgoing --large works (with revsets too)
666 $ hg outgoing --rev '.^' --large
666 $ hg outgoing --rev '.^' --large
667 comparing with $TESTTMP/a
667 comparing with $TESTTMP/a
668 searching for changes
668 searching for changes
669 changeset: 8:c02fd3b77ec4
669 changeset: 8:c02fd3b77ec4
670 user: test
670 user: test
671 date: Thu Jan 01 00:00:00 1970 +0000
671 date: Thu Jan 01 00:00:00 1970 +0000
672 summary: add foo
672 summary: add foo
673
673
674 changeset: 9:289dd08c9bbb
674 changeset: 9:289dd08c9bbb
675 user: test
675 user: test
676 date: Thu Jan 01 00:00:00 1970 +0000
676 date: Thu Jan 01 00:00:00 1970 +0000
677 summary: used to say nothing changed
677 summary: used to say nothing changed
678
678
679 changeset: 10:34f23ac6ac12
679 changeset: 10:34f23ac6ac12
680 user: test
680 user: test
681 date: Thu Jan 01 00:00:00 1970 +0000
681 date: Thu Jan 01 00:00:00 1970 +0000
682 summary: added
682 summary: added
683
683
684 changeset: 12:710c1b2f523c
684 changeset: 12:710c1b2f523c
685 parent: 10:34f23ac6ac12
685 parent: 10:34f23ac6ac12
686 user: test
686 user: test
687 date: Thu Jan 01 00:00:00 1970 +0000
687 date: Thu Jan 01 00:00:00 1970 +0000
688 summary: removed large
688 summary: removed large
689
689
690 changeset: 13:0a3e75774479
690 changeset: 13:0a3e75774479
691 user: test
691 user: test
692 date: Thu Jan 01 00:00:00 1970 +0000
692 date: Thu Jan 01 00:00:00 1970 +0000
693 summary: this used to add large8 as normal and commit both
693 summary: this used to add large8 as normal and commit both
694
694
695 changeset: 14:84f3d378175c
695 changeset: 14:84f3d378175c
696 user: test
696 user: test
697 date: Thu Jan 01 00:00:00 1970 +0000
697 date: Thu Jan 01 00:00:00 1970 +0000
698 summary: this used to not notice the rm
698 summary: this used to not notice the rm
699
699
700 largefiles to upload (1 entities):
700 largefiles to upload (1 entities):
701 large8
701 large8
702
702
703 $ cd ../a
703 $ cd ../a
704
704
705 Clone a largefiles repo.
705 Clone a largefiles repo.
706
706
707 $ hg clone . ../b
707 $ hg clone . ../b
708 updating to branch default
708 updating to branch default
709 getting changed largefiles
709 getting changed largefiles
710 3 largefiles updated, 0 removed
710 3 largefiles updated, 0 removed
711 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
711 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
712 $ cd ../b
712 $ cd ../b
713 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
713 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
714 7:daea875e9014 add/edit more largefiles
714 7:daea875e9014 add/edit more largefiles
715 6:4355d653f84f edit files yet again
715 6:4355d653f84f edit files yet again
716 5:9d5af5072dbd edit files again
716 5:9d5af5072dbd edit files again
717 4:74c02385b94c move files
717 4:74c02385b94c move files
718 3:9e8fbc4bce62 copy files
718 3:9e8fbc4bce62 copy files
719 2:51a0ae4d5864 remove files
719 2:51a0ae4d5864 remove files
720 1:ce8896473775 edit files
720 1:ce8896473775 edit files
721 0:30d30fe6a5be add files
721 0:30d30fe6a5be add files
722 $ cat normal3
722 $ cat normal3
723 normal33
723 normal33
724
724
725 Test graph log
725 Test graph log
726
726
727 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
727 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
728 @ 7:daea875e9014 add/edit more largefiles
728 @ 7:daea875e9014 add/edit more largefiles
729 |
729 |
730 o 6:4355d653f84f edit files yet again
730 o 6:4355d653f84f edit files yet again
731 |
731 |
732 o 5:9d5af5072dbd edit files again
732 o 5:9d5af5072dbd edit files again
733 |
733 |
734 o 4:74c02385b94c move files
734 o 4:74c02385b94c move files
735 |
735 |
736 o 3:9e8fbc4bce62 copy files
736 o 3:9e8fbc4bce62 copy files
737 |
737 |
738 o 2:51a0ae4d5864 remove files
738 o 2:51a0ae4d5864 remove files
739 |
739 |
740 o 1:ce8896473775 edit files
740 o 1:ce8896473775 edit files
741 |
741 |
742 o 0:30d30fe6a5be add files
742 o 0:30d30fe6a5be add files
743
743
744
744
745 Test log with --patch
745 Test log with --patch
746
746
747 $ hg log --patch -r 6::7
747 $ hg log --patch -r 6::7
748 changeset: 6:4355d653f84f
748 changeset: 6:4355d653f84f
749 user: test
749 user: test
750 date: Thu Jan 01 00:00:00 1970 +0000
750 date: Thu Jan 01 00:00:00 1970 +0000
751 summary: edit files yet again
751 summary: edit files yet again
752
752
753 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
753 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
754 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
754 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
755 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
755 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
756 @@ -1,1 +1,1 @@
756 @@ -1,1 +1,1 @@
757 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
757 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
758 +7838695e10da2bb75ac1156565f40a2595fa2fa0
758 +7838695e10da2bb75ac1156565f40a2595fa2fa0
759 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
759 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
760 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
760 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
761 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
761 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
762 @@ -1,1 +1,1 @@
762 @@ -1,1 +1,1 @@
763 -aeb2210d19f02886dde00dac279729a48471e2f9
763 -aeb2210d19f02886dde00dac279729a48471e2f9
764 +971fb41e78fea4f8e0ba5244784239371cb00591
764 +971fb41e78fea4f8e0ba5244784239371cb00591
765 diff -r 9d5af5072dbd -r 4355d653f84f normal3
765 diff -r 9d5af5072dbd -r 4355d653f84f normal3
766 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
766 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
767 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
767 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
768 @@ -1,1 +1,1 @@
768 @@ -1,1 +1,1 @@
769 -normal3
769 -normal3
770 +normal33
770 +normal33
771 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
771 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
772 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
772 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
773 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
773 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
774 @@ -1,1 +1,1 @@
774 @@ -1,1 +1,1 @@
775 -normal4
775 -normal4
776 +normal44
776 +normal44
777
777
778 changeset: 7:daea875e9014
778 changeset: 7:daea875e9014
779 tag: tip
779 tag: tip
780 user: test
780 user: test
781 date: Thu Jan 01 00:00:00 1970 +0000
781 date: Thu Jan 01 00:00:00 1970 +0000
782 summary: add/edit more largefiles
782 summary: add/edit more largefiles
783
783
784 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
784 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
785 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
785 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
786 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
786 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
787 @@ -1,1 +0,0 @@
787 @@ -1,1 +0,0 @@
788 -7838695e10da2bb75ac1156565f40a2595fa2fa0
788 -7838695e10da2bb75ac1156565f40a2595fa2fa0
789 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
789 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
790 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
790 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
791 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
791 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
792 @@ -0,0 +1,1 @@
792 @@ -0,0 +1,1 @@
793 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
793 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
794 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
794 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
795 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
795 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
796 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
796 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
797 @@ -0,0 +1,1 @@
797 @@ -0,0 +1,1 @@
798 +bb3151689acb10f0c3125c560d5e63df914bc1af
798 +bb3151689acb10f0c3125c560d5e63df914bc1af
799
799
800
800
801 $ hg log --patch -r 6::7 sub/
801 $ hg log --patch -r 6::7 sub/
802 changeset: 6:4355d653f84f
802 changeset: 6:4355d653f84f
803 user: test
803 user: test
804 date: Thu Jan 01 00:00:00 1970 +0000
804 date: Thu Jan 01 00:00:00 1970 +0000
805 summary: edit files yet again
805 summary: edit files yet again
806
806
807 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
807 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
808 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
808 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
809 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
809 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
810 @@ -1,1 +1,1 @@
810 @@ -1,1 +1,1 @@
811 -aeb2210d19f02886dde00dac279729a48471e2f9
811 -aeb2210d19f02886dde00dac279729a48471e2f9
812 +971fb41e78fea4f8e0ba5244784239371cb00591
812 +971fb41e78fea4f8e0ba5244784239371cb00591
813 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
813 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
814 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
814 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
815 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
815 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
816 @@ -1,1 +1,1 @@
816 @@ -1,1 +1,1 @@
817 -normal4
817 -normal4
818 +normal44
818 +normal44
819
819
820
820
821 log with both --follow and --patch
821 log with both --follow and --patch
822
822
823 $ hg log --follow --patch --limit 2
823 $ hg log --follow --patch --limit 2
824 changeset: 7:daea875e9014
824 changeset: 7:daea875e9014
825 tag: tip
825 tag: tip
826 user: test
826 user: test
827 date: Thu Jan 01 00:00:00 1970 +0000
827 date: Thu Jan 01 00:00:00 1970 +0000
828 summary: add/edit more largefiles
828 summary: add/edit more largefiles
829
829
830 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
830 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
831 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
831 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
832 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
832 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
833 @@ -1,1 +0,0 @@
833 @@ -1,1 +0,0 @@
834 -7838695e10da2bb75ac1156565f40a2595fa2fa0
834 -7838695e10da2bb75ac1156565f40a2595fa2fa0
835 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
835 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
836 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
836 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
837 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
837 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
838 @@ -0,0 +1,1 @@
838 @@ -0,0 +1,1 @@
839 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
839 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
840 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
840 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
841 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
841 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
842 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
842 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
843 @@ -0,0 +1,1 @@
843 @@ -0,0 +1,1 @@
844 +bb3151689acb10f0c3125c560d5e63df914bc1af
844 +bb3151689acb10f0c3125c560d5e63df914bc1af
845
845
846 changeset: 6:4355d653f84f
846 changeset: 6:4355d653f84f
847 user: test
847 user: test
848 date: Thu Jan 01 00:00:00 1970 +0000
848 date: Thu Jan 01 00:00:00 1970 +0000
849 summary: edit files yet again
849 summary: edit files yet again
850
850
851 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
851 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
852 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
852 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
853 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
853 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
854 @@ -1,1 +1,1 @@
854 @@ -1,1 +1,1 @@
855 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
855 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
856 +7838695e10da2bb75ac1156565f40a2595fa2fa0
856 +7838695e10da2bb75ac1156565f40a2595fa2fa0
857 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
857 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
858 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
858 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
859 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
859 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
860 @@ -1,1 +1,1 @@
860 @@ -1,1 +1,1 @@
861 -aeb2210d19f02886dde00dac279729a48471e2f9
861 -aeb2210d19f02886dde00dac279729a48471e2f9
862 +971fb41e78fea4f8e0ba5244784239371cb00591
862 +971fb41e78fea4f8e0ba5244784239371cb00591
863 diff -r 9d5af5072dbd -r 4355d653f84f normal3
863 diff -r 9d5af5072dbd -r 4355d653f84f normal3
864 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
864 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
865 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
865 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
866 @@ -1,1 +1,1 @@
866 @@ -1,1 +1,1 @@
867 -normal3
867 -normal3
868 +normal33
868 +normal33
869 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
869 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
870 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
870 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
871 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
871 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
872 @@ -1,1 +1,1 @@
872 @@ -1,1 +1,1 @@
873 -normal4
873 -normal4
874 +normal44
874 +normal44
875
875
876 $ hg log --follow --patch sub/large4
876 $ hg log --follow --patch sub/large4
877 changeset: 6:4355d653f84f
877 changeset: 6:4355d653f84f
878 user: test
878 user: test
879 date: Thu Jan 01 00:00:00 1970 +0000
879 date: Thu Jan 01 00:00:00 1970 +0000
880 summary: edit files yet again
880 summary: edit files yet again
881
881
882 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
882 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
883 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
883 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
884 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
884 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
885 @@ -1,1 +1,1 @@
885 @@ -1,1 +1,1 @@
886 -aeb2210d19f02886dde00dac279729a48471e2f9
886 -aeb2210d19f02886dde00dac279729a48471e2f9
887 +971fb41e78fea4f8e0ba5244784239371cb00591
887 +971fb41e78fea4f8e0ba5244784239371cb00591
888
888
889 changeset: 5:9d5af5072dbd
889 changeset: 5:9d5af5072dbd
890 user: test
890 user: test
891 date: Thu Jan 01 00:00:00 1970 +0000
891 date: Thu Jan 01 00:00:00 1970 +0000
892 summary: edit files again
892 summary: edit files again
893
893
894 diff -r 74c02385b94c -r 9d5af5072dbd .hglf/sub/large4
894 diff -r 74c02385b94c -r 9d5af5072dbd .hglf/sub/large4
895 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
895 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
896 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
896 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
897 @@ -1,1 +1,1 @@
897 @@ -1,1 +1,1 @@
898 -eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
898 -eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
899 +aeb2210d19f02886dde00dac279729a48471e2f9
899 +aeb2210d19f02886dde00dac279729a48471e2f9
900
900
901 changeset: 4:74c02385b94c
901 changeset: 4:74c02385b94c
902 user: test
902 user: test
903 date: Thu Jan 01 00:00:00 1970 +0000
903 date: Thu Jan 01 00:00:00 1970 +0000
904 summary: move files
904 summary: move files
905
905
906 diff -r 9e8fbc4bce62 -r 74c02385b94c .hglf/sub/large4
906 diff -r 9e8fbc4bce62 -r 74c02385b94c .hglf/sub/large4
907 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
907 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
908 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
908 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
909 @@ -0,0 +1,1 @@
909 @@ -0,0 +1,1 @@
910 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
910 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
911
911
912 changeset: 1:ce8896473775
912 changeset: 1:ce8896473775
913 user: test
913 user: test
914 date: Thu Jan 01 00:00:00 1970 +0000
914 date: Thu Jan 01 00:00:00 1970 +0000
915 summary: edit files
915 summary: edit files
916
916
917 diff -r 30d30fe6a5be -r ce8896473775 .hglf/sub/large2
917 diff -r 30d30fe6a5be -r ce8896473775 .hglf/sub/large2
918 --- a/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
918 --- a/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
919 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
919 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
920 @@ -1,1 +1,1 @@
920 @@ -1,1 +1,1 @@
921 -1deebade43c8c498a3c8daddac0244dc55d1331d
921 -1deebade43c8c498a3c8daddac0244dc55d1331d
922 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
922 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
923
923
924 changeset: 0:30d30fe6a5be
924 changeset: 0:30d30fe6a5be
925 user: test
925 user: test
926 date: Thu Jan 01 00:00:00 1970 +0000
926 date: Thu Jan 01 00:00:00 1970 +0000
927 summary: add files
927 summary: add files
928
928
929 diff -r 000000000000 -r 30d30fe6a5be .hglf/sub/large2
929 diff -r 000000000000 -r 30d30fe6a5be .hglf/sub/large2
930 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
930 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
931 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
931 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
932 @@ -0,0 +1,1 @@
932 @@ -0,0 +1,1 @@
933 +1deebade43c8c498a3c8daddac0244dc55d1331d
933 +1deebade43c8c498a3c8daddac0244dc55d1331d
934
934
935 $ cat sub/normal4
935 $ cat sub/normal4
936 normal44
936 normal44
937 $ cat sub/large4
937 $ cat sub/large4
938 large44
938 large44
939 $ cat sub2/large6
939 $ cat sub2/large6
940 large6
940 large6
941 $ cat sub2/large7
941 $ cat sub2/large7
942 large7
942 large7
943 $ hg log -qf sub2/large7
943 $ hg log -qf sub2/large7
944 7:daea875e9014
944 7:daea875e9014
945 $ hg log -Gqf sub2/large7
945 $ hg log -Gqf sub2/large7
946 @ 7:daea875e9014
946 @ 7:daea875e9014
947 |
947 |
948 ~
948 ~
949 $ cd ..
949 $ cd ..
950
950
951 Test log from outside repo
951 Test log from outside repo
952
952
953 $ hg log b/sub -T '{rev}:{node|short} {desc|firstline}\n'
953 $ hg log b/sub -T '{rev}:{node|short} {desc|firstline}\n'
954 6:4355d653f84f edit files yet again
954 6:4355d653f84f edit files yet again
955 5:9d5af5072dbd edit files again
955 5:9d5af5072dbd edit files again
956 4:74c02385b94c move files
956 4:74c02385b94c move files
957 1:ce8896473775 edit files
957 1:ce8896473775 edit files
958 0:30d30fe6a5be add files
958 0:30d30fe6a5be add files
959
959
960 Test clone at revision
960 Test clone at revision
961
961
962 $ hg clone a -r 3 c
962 $ hg clone a -r 3 c
963 adding changesets
963 adding changesets
964 adding manifests
964 adding manifests
965 adding file changes
965 adding file changes
966 added 4 changesets with 10 changes to 4 files
966 added 4 changesets with 10 changes to 4 files
967 new changesets 30d30fe6a5be:9e8fbc4bce62 (4 drafts)
967 new changesets 30d30fe6a5be:9e8fbc4bce62 (4 drafts)
968 updating to branch default
968 updating to branch default
969 getting changed largefiles
969 getting changed largefiles
970 2 largefiles updated, 0 removed
970 2 largefiles updated, 0 removed
971 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
971 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
972 $ cd c
972 $ cd c
973 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
973 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
974 3:9e8fbc4bce62 copy files
974 3:9e8fbc4bce62 copy files
975 2:51a0ae4d5864 remove files
975 2:51a0ae4d5864 remove files
976 1:ce8896473775 edit files
976 1:ce8896473775 edit files
977 0:30d30fe6a5be add files
977 0:30d30fe6a5be add files
978 $ cat normal1
978 $ cat normal1
979 normal22
979 normal22
980 $ cat large1
980 $ cat large1
981 large22
981 large22
982 $ cat sub/normal2
982 $ cat sub/normal2
983 normal22
983 normal22
984 $ cat sub/large2
984 $ cat sub/large2
985 large22
985 large22
986
986
987 Old revisions of a clone have correct largefiles content (this also
987 Old revisions of a clone have correct largefiles content (this also
988 tests update).
988 tests update).
989
989
990 $ hg update -r 1
990 $ hg update -r 1
991 getting changed largefiles
991 getting changed largefiles
992 1 largefiles updated, 0 removed
992 1 largefiles updated, 0 removed
993 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
993 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
994 $ cat large1
994 $ cat large1
995 large11
995 large11
996 $ cat sub/large2
996 $ cat sub/large2
997 large22
997 large22
998 $ cd ..
998 $ cd ..
999
999
1000 Test cloning with --all-largefiles flag
1000 Test cloning with --all-largefiles flag
1001
1001
1002 $ rm "${USERCACHE}"/*
1002 $ rm "${USERCACHE}"/*
1003 $ hg clone --all-largefiles a a-backup
1003 $ hg clone --all-largefiles a a-backup
1004 updating to branch default
1004 updating to branch default
1005 getting changed largefiles
1005 getting changed largefiles
1006 3 largefiles updated, 0 removed
1006 3 largefiles updated, 0 removed
1007 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1007 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1008 7 additional largefiles cached
1008 7 additional largefiles cached
1009
1009
1010 $ rm "${USERCACHE}"/*
1010 $ rm "${USERCACHE}"/*
1011 $ hg clone --all-largefiles -u 0 a a-clone0
1011 $ hg clone --all-largefiles -u 0 a a-clone0
1012 updating to branch default
1012 updating to branch default
1013 getting changed largefiles
1013 getting changed largefiles
1014 2 largefiles updated, 0 removed
1014 2 largefiles updated, 0 removed
1015 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1015 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1016 8 additional largefiles cached
1016 8 additional largefiles cached
1017 $ hg -R a-clone0 sum
1017 $ hg -R a-clone0 sum
1018 parent: 0:30d30fe6a5be
1018 parent: 0:30d30fe6a5be
1019 add files
1019 add files
1020 branch: default
1020 branch: default
1021 commit: (clean)
1021 commit: (clean)
1022 update: 7 new changesets (update)
1022 update: 7 new changesets (update)
1023 phases: 8 draft
1023 phases: 8 draft
1024
1024
1025 $ rm "${USERCACHE}"/*
1025 $ rm "${USERCACHE}"/*
1026 $ hg clone --all-largefiles -u 1 a a-clone1
1026 $ hg clone --all-largefiles -u 1 a a-clone1
1027 updating to branch default
1027 updating to branch default
1028 getting changed largefiles
1028 getting changed largefiles
1029 2 largefiles updated, 0 removed
1029 2 largefiles updated, 0 removed
1030 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1030 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1031 8 additional largefiles cached
1031 8 additional largefiles cached
1032 $ hg -R a-clone1 verify --large --lfa --lfc -q
1032 $ hg -R a-clone1 verify --large --lfa --lfc -q
1033 $ hg -R a-clone1 sum
1033 $ hg -R a-clone1 sum
1034 parent: 1:ce8896473775
1034 parent: 1:ce8896473775
1035 edit files
1035 edit files
1036 branch: default
1036 branch: default
1037 commit: (clean)
1037 commit: (clean)
1038 update: 6 new changesets (update)
1038 update: 6 new changesets (update)
1039 phases: 8 draft
1039 phases: 8 draft
1040
1040
1041 $ rm "${USERCACHE}"/*
1041 $ rm "${USERCACHE}"/*
1042 $ hg clone --all-largefiles -U a a-clone-u
1042 $ hg clone --all-largefiles -U a a-clone-u
1043 10 additional largefiles cached
1043 10 additional largefiles cached
1044 $ hg -R a-clone-u sum
1044 $ hg -R a-clone-u sum
1045 parent: -1:000000000000 (no revision checked out)
1045 parent: -1:000000000000 (no revision checked out)
1046 branch: default
1046 branch: default
1047 commit: (clean)
1047 commit: (clean)
1048 update: 8 new changesets (update)
1048 update: 8 new changesets (update)
1049 phases: 8 draft
1049 phases: 8 draft
1050
1050
1051 Show computed destination directory:
1051 Show computed destination directory:
1052
1052
1053 $ mkdir xyz
1053 $ mkdir xyz
1054 $ cd xyz
1054 $ cd xyz
1055 $ hg clone ../a
1055 $ hg clone ../a
1056 destination directory: a
1056 destination directory: a
1057 updating to branch default
1057 updating to branch default
1058 getting changed largefiles
1058 getting changed largefiles
1059 3 largefiles updated, 0 removed
1059 3 largefiles updated, 0 removed
1060 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1060 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1061 $ cd ..
1061 $ cd ..
1062
1062
1063 Clone URL without path:
1063 Clone URL without path:
1064
1064
1065 $ hg clone file://
1065 $ hg clone file://
1066 abort: repository / not found
1066 abort: repository / not found
1067 [255]
1067 [255]
1068
1068
1069 Ensure base clone command argument validation
1069 Ensure base clone command argument validation
1070
1070
1071 $ hg clone -U -u 0 a a-clone-failure
1071 $ hg clone -U -u 0 a a-clone-failure
1072 abort: cannot specify both --noupdate and --updaterev
1072 abort: cannot specify both --noupdate and --updaterev
1073 [10]
1073 [10]
1074
1074
1075 $ hg clone --all-largefiles a ssh://localhost/a
1075 $ hg clone --all-largefiles a ssh://localhost/a
1076 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
1076 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
1077 [255]
1077 [255]
1078
1078
1079 Test pulling with --all-largefiles flag. Also test that the largefiles are
1079 Test pulling with --all-largefiles flag. Also test that the largefiles are
1080 downloaded from 'default' instead of 'default-push' when no source is specified
1080 downloaded from 'default' instead of 'default-push' when no source is specified
1081 (issue3584)
1081 (issue3584)
1082
1082
1083 $ rm -Rf a-backup
1083 $ rm -Rf a-backup
1084 $ hg clone -r 1 a a-backup
1084 $ hg clone -r 1 a a-backup
1085 adding changesets
1085 adding changesets
1086 adding manifests
1086 adding manifests
1087 adding file changes
1087 adding file changes
1088 added 2 changesets with 8 changes to 4 files
1088 added 2 changesets with 8 changes to 4 files
1089 new changesets 30d30fe6a5be:ce8896473775 (2 drafts)
1089 new changesets 30d30fe6a5be:ce8896473775 (2 drafts)
1090 updating to branch default
1090 updating to branch default
1091 getting changed largefiles
1091 getting changed largefiles
1092 2 largefiles updated, 0 removed
1092 2 largefiles updated, 0 removed
1093 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1093 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1094 $ rm "${USERCACHE}"/*
1094 $ rm "${USERCACHE}"/*
1095 $ cd a-backup
1095 $ cd a-backup
1096 $ hg pull --all-largefiles --config paths.default-push=bogus/path
1096 $ hg pull --all-largefiles --config paths.default-push=bogus/path
1097 pulling from $TESTTMP/a
1097 pulling from $TESTTMP/a
1098 searching for changes
1098 searching for changes
1099 adding changesets
1099 adding changesets
1100 adding manifests
1100 adding manifests
1101 adding file changes
1101 adding file changes
1102 added 6 changesets with 16 changes to 8 files
1102 added 6 changesets with 16 changes to 8 files
1103 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1103 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1104 (run 'hg update' to get a working copy)
1104 (run 'hg update' to get a working copy)
1105 6 largefiles cached
1105 6 largefiles cached
1106
1106
1107 redo pull with --lfrev and check it pulls largefiles for the right revs
1107 redo pull with --lfrev and check it pulls largefiles for the right revs
1108
1108
1109 $ hg rollback
1109 $ hg rollback
1110 repository tip rolled back to revision 1 (undo pull)
1110 repository tip rolled back to revision 1 (undo pull)
1111 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
1111 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
1112 pulling from $TESTTMP/a
1112 pulling from $TESTTMP/a
1113 searching for changes
1113 searching for changes
1114 all local changesets known remotely
1114 all local changesets known remotely
1115 6 changesets found
1115 6 changesets found
1116 uncompressed size of bundle content:
1116 uncompressed size of bundle content:
1117 1389 (changelog)
1117 1389 (changelog)
1118 1698 (manifests)
1118 1698 (manifests)
1119 254 .hglf/large1
1119 254 .hglf/large1
1120 564 .hglf/large3
1120 564 .hglf/large3
1121 572 .hglf/sub/large4
1121 572 .hglf/sub/large4
1122 182 .hglf/sub2/large6
1122 182 .hglf/sub2/large6
1123 182 .hglf/sub2/large7
1123 182 .hglf/sub2/large7
1124 212 normal1
1124 212 normal1
1125 457 normal3
1125 457 normal3
1126 465 sub/normal4
1126 465 sub/normal4
1127 adding changesets
1127 adding changesets
1128 adding manifests
1128 adding manifests
1129 adding file changes
1129 adding file changes
1130 added 6 changesets with 16 changes to 8 files
1130 added 6 changesets with 16 changes to 8 files
1131 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1131 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1132 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
1132 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
1133 (run 'hg update' to get a working copy)
1133 (run 'hg update' to get a working copy)
1134 pulling largefiles for revision 7
1134 pulling largefiles for revision 7
1135 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
1135 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
1136 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
1136 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
1137 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
1137 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
1138 pulling largefiles for revision 2
1138 pulling largefiles for revision 2
1139 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1139 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1140 0 largefiles cached
1140 0 largefiles cached
1141
1141
1142 lfpull
1142 lfpull
1143
1143
1144 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
1144 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
1145 2 largefiles cached
1145 2 largefiles cached
1146 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
1146 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
1147 pulling largefiles for revision 4
1147 pulling largefiles for revision 4
1148 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1148 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1149 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1149 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1150 pulling largefiles for revision 2
1150 pulling largefiles for revision 2
1151 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1151 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1152 0 largefiles cached
1152 0 largefiles cached
1153
1153
1154 $ ls usercache-lfpull/* | sort
1154 $ ls usercache-lfpull/* | sort
1155 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
1155 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
1156 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
1156 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
1157
1157
1158 $ cd ..
1158 $ cd ..
1159
1159
1160 Rebasing between two repositories does not revert largefiles to old
1160 Rebasing between two repositories does not revert largefiles to old
1161 revisions (this was a very bad bug that took a lot of work to fix).
1161 revisions (this was a very bad bug that took a lot of work to fix).
1162
1162
1163 $ hg clone a d
1163 $ hg clone a d
1164 updating to branch default
1164 updating to branch default
1165 getting changed largefiles
1165 getting changed largefiles
1166 3 largefiles updated, 0 removed
1166 3 largefiles updated, 0 removed
1167 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1167 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1168 $ cd b
1168 $ cd b
1169 $ echo large4-modified > sub/large4
1169 $ echo large4-modified > sub/large4
1170 $ echo normal3-modified > normal3
1170 $ echo normal3-modified > normal3
1171 $ hg commit -m "modify normal file and largefile in repo b"
1171 $ hg commit -m "modify normal file and largefile in repo b"
1172 Invoking status precommit hook
1172 Invoking status precommit hook
1173 M normal3
1173 M normal3
1174 M sub/large4
1174 M sub/large4
1175 $ cd ../d
1175 $ cd ../d
1176 $ echo large6-modified > sub2/large6
1176 $ echo large6-modified > sub2/large6
1177 $ echo normal4-modified > sub/normal4
1177 $ echo normal4-modified > sub/normal4
1178 $ hg commit -m "modify normal file largefile in repo d"
1178 $ hg commit -m "modify normal file largefile in repo d"
1179 Invoking status precommit hook
1179 Invoking status precommit hook
1180 M sub/normal4
1180 M sub/normal4
1181 M sub2/large6
1181 M sub2/large6
1182 $ cd ..
1182 $ cd ..
1183 $ hg clone d e
1183 $ hg clone d e
1184 updating to branch default
1184 updating to branch default
1185 getting changed largefiles
1185 getting changed largefiles
1186 3 largefiles updated, 0 removed
1186 3 largefiles updated, 0 removed
1187 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1187 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1188 $ cd d
1188 $ cd d
1189
1189
1190 More rebase testing, but also test that the largefiles are downloaded from
1190 More rebase testing, but also test that the largefiles are downloaded from
1191 'default-push' when no source is specified (issue3584). (The largefile from the
1191 'default-push' when no source is specified (issue3584). (The largefile from the
1192 pulled revision is however not downloaded but found in the local cache.)
1192 pulled revision is however not downloaded but found in the local cache.)
1193 Largefiles are fetched for the new pulled revision, not for existing revisions,
1193 Largefiles are fetched for the new pulled revision, not for existing revisions,
1194 rebased or not.
1194 rebased or not.
1195
1195
1196 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1196 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1197 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
1197 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
1198 pulling from $TESTTMP/b
1198 pulling from $TESTTMP/b
1199 searching for changes
1199 searching for changes
1200 adding changesets
1200 adding changesets
1201 adding manifests
1201 adding manifests
1202 adding file changes
1202 adding file changes
1203 added 1 changesets with 2 changes to 2 files (+1 heads)
1203 added 1 changesets with 2 changes to 2 files (+1 heads)
1204 new changesets a381d2c8c80e (1 drafts)
1204 new changesets a381d2c8c80e (1 drafts)
1205 0 largefiles cached
1205 0 largefiles cached
1206 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1206 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1207 Invoking status precommit hook
1207 Invoking status precommit hook
1208 M sub/normal4
1208 M sub/normal4
1209 M sub2/large6
1209 M sub2/large6
1210 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1210 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1211 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1211 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1212 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1212 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1213 9:598410d3eb9a modify normal file largefile in repo d
1213 9:598410d3eb9a modify normal file largefile in repo d
1214 8:a381d2c8c80e modify normal file and largefile in repo b
1214 8:a381d2c8c80e modify normal file and largefile in repo b
1215 7:daea875e9014 add/edit more largefiles
1215 7:daea875e9014 add/edit more largefiles
1216 6:4355d653f84f edit files yet again
1216 6:4355d653f84f edit files yet again
1217 5:9d5af5072dbd edit files again
1217 5:9d5af5072dbd edit files again
1218 4:74c02385b94c move files
1218 4:74c02385b94c move files
1219 3:9e8fbc4bce62 copy files
1219 3:9e8fbc4bce62 copy files
1220 2:51a0ae4d5864 remove files
1220 2:51a0ae4d5864 remove files
1221 1:ce8896473775 edit files
1221 1:ce8896473775 edit files
1222 0:30d30fe6a5be add files
1222 0:30d30fe6a5be add files
1223 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
1223 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
1224 @ 9:598410d3eb9a modify normal file largefile in repo d
1224 @ 9:598410d3eb9a modify normal file largefile in repo d
1225 |
1225 |
1226 o 8:a381d2c8c80e modify normal file and largefile in repo b
1226 o 8:a381d2c8c80e modify normal file and largefile in repo b
1227 |
1227 |
1228 o 7:daea875e9014 add/edit more largefiles
1228 o 7:daea875e9014 add/edit more largefiles
1229 |
1229 |
1230 o 6:4355d653f84f edit files yet again
1230 o 6:4355d653f84f edit files yet again
1231 |
1231 |
1232 o 5:9d5af5072dbd edit files again
1232 o 5:9d5af5072dbd edit files again
1233 |
1233 |
1234 o 4:74c02385b94c move files
1234 o 4:74c02385b94c move files
1235 |
1235 |
1236 o 3:9e8fbc4bce62 copy files
1236 o 3:9e8fbc4bce62 copy files
1237 |
1237 |
1238 o 2:51a0ae4d5864 remove files
1238 o 2:51a0ae4d5864 remove files
1239 |
1239 |
1240 o 1:ce8896473775 edit files
1240 o 1:ce8896473775 edit files
1241 |
1241 |
1242 o 0:30d30fe6a5be add files
1242 o 0:30d30fe6a5be add files
1243
1243
1244 $ cat normal3
1244 $ cat normal3
1245 normal3-modified
1245 normal3-modified
1246 $ cat sub/normal4
1246 $ cat sub/normal4
1247 normal4-modified
1247 normal4-modified
1248 $ cat sub/large4
1248 $ cat sub/large4
1249 large4-modified
1249 large4-modified
1250 $ cat sub2/large6
1250 $ cat sub2/large6
1251 large6-modified
1251 large6-modified
1252 $ cat sub2/large7
1252 $ cat sub2/large7
1253 large7
1253 large7
1254 $ cd ../e
1254 $ cd ../e
1255 $ hg pull ../b
1255 $ hg pull ../b
1256 pulling from ../b
1256 pulling from ../b
1257 searching for changes
1257 searching for changes
1258 adding changesets
1258 adding changesets
1259 adding manifests
1259 adding manifests
1260 adding file changes
1260 adding file changes
1261 added 1 changesets with 2 changes to 2 files (+1 heads)
1261 added 1 changesets with 2 changes to 2 files (+1 heads)
1262 new changesets a381d2c8c80e (1 drafts)
1262 new changesets a381d2c8c80e (1 drafts)
1263 (run 'hg heads' to see heads, 'hg merge' to merge)
1263 (run 'hg heads' to see heads, 'hg merge' to merge)
1264 $ hg rebase
1264 $ hg rebase
1265 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1265 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1266 Invoking status precommit hook
1266 Invoking status precommit hook
1267 M sub/normal4
1267 M sub/normal4
1268 M sub2/large6
1268 M sub2/large6
1269 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1269 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1270 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1270 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1271 9:598410d3eb9a modify normal file largefile in repo d
1271 9:598410d3eb9a modify normal file largefile in repo d
1272 8:a381d2c8c80e modify normal file and largefile in repo b
1272 8:a381d2c8c80e modify normal file and largefile in repo b
1273 7:daea875e9014 add/edit more largefiles
1273 7:daea875e9014 add/edit more largefiles
1274 6:4355d653f84f edit files yet again
1274 6:4355d653f84f edit files yet again
1275 5:9d5af5072dbd edit files again
1275 5:9d5af5072dbd edit files again
1276 4:74c02385b94c move files
1276 4:74c02385b94c move files
1277 3:9e8fbc4bce62 copy files
1277 3:9e8fbc4bce62 copy files
1278 2:51a0ae4d5864 remove files
1278 2:51a0ae4d5864 remove files
1279 1:ce8896473775 edit files
1279 1:ce8896473775 edit files
1280 0:30d30fe6a5be add files
1280 0:30d30fe6a5be add files
1281 $ cat normal3
1281 $ cat normal3
1282 normal3-modified
1282 normal3-modified
1283 $ cat sub/normal4
1283 $ cat sub/normal4
1284 normal4-modified
1284 normal4-modified
1285 $ cat sub/large4
1285 $ cat sub/large4
1286 large4-modified
1286 large4-modified
1287 $ cat sub2/large6
1287 $ cat sub2/large6
1288 large6-modified
1288 large6-modified
1289 $ cat sub2/large7
1289 $ cat sub2/large7
1290 large7
1290 large7
1291
1291
1292 Log on largefiles
1292 Log on largefiles
1293
1293
1294 - same output
1294 - same output
1295 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1295 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1296 8:a381d2c8c80e modify normal file and largefile in repo b
1296 8:a381d2c8c80e modify normal file and largefile in repo b
1297 6:4355d653f84f edit files yet again
1297 6:4355d653f84f edit files yet again
1298 5:9d5af5072dbd edit files again
1298 5:9d5af5072dbd edit files again
1299 4:74c02385b94c move files
1299 4:74c02385b94c move files
1300 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1300 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1301 o 8:a381d2c8c80e modify normal file and largefile in repo b
1301 o 8:a381d2c8c80e modify normal file and largefile in repo b
1302 :
1302 :
1303 o 6:4355d653f84f edit files yet again
1303 o 6:4355d653f84f edit files yet again
1304 |
1304 |
1305 o 5:9d5af5072dbd edit files again
1305 o 5:9d5af5072dbd edit files again
1306 |
1306 |
1307 o 4:74c02385b94c move files
1307 o 4:74c02385b94c move files
1308 |
1308 |
1309 ~
1309 ~
1310 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1310 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1311 8:a381d2c8c80e modify normal file and largefile in repo b
1311 8:a381d2c8c80e modify normal file and largefile in repo b
1312 6:4355d653f84f edit files yet again
1312 6:4355d653f84f edit files yet again
1313 5:9d5af5072dbd edit files again
1313 5:9d5af5072dbd edit files again
1314 4:74c02385b94c move files
1314 4:74c02385b94c move files
1315 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1315 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1316 o 8:a381d2c8c80e modify normal file and largefile in repo b
1316 o 8:a381d2c8c80e modify normal file and largefile in repo b
1317 :
1317 :
1318 o 6:4355d653f84f edit files yet again
1318 o 6:4355d653f84f edit files yet again
1319 |
1319 |
1320 o 5:9d5af5072dbd edit files again
1320 o 5:9d5af5072dbd edit files again
1321 |
1321 |
1322 o 4:74c02385b94c move files
1322 o 4:74c02385b94c move files
1323 |
1323 |
1324 ~
1324 ~
1325
1325
1326 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1326 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1327 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1327 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1328 8:a381d2c8c80e modify normal file and largefile in repo b
1328 8:a381d2c8c80e modify normal file and largefile in repo b
1329 6:4355d653f84f edit files yet again
1329 6:4355d653f84f edit files yet again
1330 5:9d5af5072dbd edit files again
1330 5:9d5af5072dbd edit files again
1331 4:74c02385b94c move files
1331 4:74c02385b94c move files
1332 1:ce8896473775 edit files
1332 1:ce8896473775 edit files
1333 0:30d30fe6a5be add files
1333 0:30d30fe6a5be add files
1334 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1334 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1335 o 8:a381d2c8c80e modify normal file and largefile in repo b
1335 o 8:a381d2c8c80e modify normal file and largefile in repo b
1336 :
1336 :
1337 o 6:4355d653f84f edit files yet again
1337 o 6:4355d653f84f edit files yet again
1338 |
1338 |
1339 o 5:9d5af5072dbd edit files again
1339 o 5:9d5af5072dbd edit files again
1340 |
1340 |
1341 o 4:74c02385b94c move files
1341 o 4:74c02385b94c move files
1342 :
1342 :
1343 o 1:ce8896473775 edit files
1343 o 1:ce8896473775 edit files
1344 |
1344 |
1345 o 0:30d30fe6a5be add files
1345 o 0:30d30fe6a5be add files
1346
1346
1347 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1347 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1348 9:598410d3eb9a modify normal file largefile in repo d
1348 9:598410d3eb9a modify normal file largefile in repo d
1349 8:a381d2c8c80e modify normal file and largefile in repo b
1349 8:a381d2c8c80e modify normal file and largefile in repo b
1350 6:4355d653f84f edit files yet again
1350 6:4355d653f84f edit files yet again
1351 5:9d5af5072dbd edit files again
1351 5:9d5af5072dbd edit files again
1352 4:74c02385b94c move files
1352 4:74c02385b94c move files
1353 1:ce8896473775 edit files
1353 1:ce8896473775 edit files
1354 0:30d30fe6a5be add files
1354 0:30d30fe6a5be add files
1355 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' sub
1355 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' sub
1356 @ 9:598410d3eb9a modify normal file largefile in repo d
1356 @ 9:598410d3eb9a modify normal file largefile in repo d
1357 |
1357 |
1358 o 8:a381d2c8c80e modify normal file and largefile in repo b
1358 o 8:a381d2c8c80e modify normal file and largefile in repo b
1359 :
1359 :
1360 o 6:4355d653f84f edit files yet again
1360 o 6:4355d653f84f edit files yet again
1361 |
1361 |
1362 o 5:9d5af5072dbd edit files again
1362 o 5:9d5af5072dbd edit files again
1363 |
1363 |
1364 o 4:74c02385b94c move files
1364 o 4:74c02385b94c move files
1365 :
1365 :
1366 o 1:ce8896473775 edit files
1366 o 1:ce8896473775 edit files
1367 |
1367 |
1368 o 0:30d30fe6a5be add files
1368 o 0:30d30fe6a5be add files
1369
1369
1370 - globbing gives same result
1370 - globbing gives same result
1371 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1371 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1372 9:598410d3eb9a modify normal file largefile in repo d
1372 9:598410d3eb9a modify normal file largefile in repo d
1373 8:a381d2c8c80e modify normal file and largefile in repo b
1373 8:a381d2c8c80e modify normal file and largefile in repo b
1374 6:4355d653f84f edit files yet again
1374 6:4355d653f84f edit files yet again
1375 5:9d5af5072dbd edit files again
1375 5:9d5af5072dbd edit files again
1376 4:74c02385b94c move files
1376 4:74c02385b94c move files
1377 1:ce8896473775 edit files
1377 1:ce8896473775 edit files
1378 0:30d30fe6a5be add files
1378 0:30d30fe6a5be add files
1379 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1379 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1380 @ 9:598410d3eb9a modify normal file largefile in repo d
1380 @ 9:598410d3eb9a modify normal file largefile in repo d
1381 |
1381 |
1382 o 8:a381d2c8c80e modify normal file and largefile in repo b
1382 o 8:a381d2c8c80e modify normal file and largefile in repo b
1383 :
1383 :
1384 o 6:4355d653f84f edit files yet again
1384 o 6:4355d653f84f edit files yet again
1385 |
1385 |
1386 o 5:9d5af5072dbd edit files again
1386 o 5:9d5af5072dbd edit files again
1387 |
1387 |
1388 o 4:74c02385b94c move files
1388 o 4:74c02385b94c move files
1389 :
1389 :
1390 o 1:ce8896473775 edit files
1390 o 1:ce8896473775 edit files
1391 |
1391 |
1392 o 0:30d30fe6a5be add files
1392 o 0:30d30fe6a5be add files
1393
1393
1394 Rollback on largefiles.
1394 Rollback on largefiles.
1395
1395
1396 $ echo large4-modified-again > sub/large4
1396 $ echo large4-modified-again > sub/large4
1397 $ hg commit -m "Modify large4 again"
1397 $ hg commit -m "Modify large4 again"
1398 Invoking status precommit hook
1398 Invoking status precommit hook
1399 M sub/large4
1399 M sub/large4
1400 $ hg rollback
1400 $ hg rollback
1401 repository tip rolled back to revision 9 (undo commit)
1401 repository tip rolled back to revision 9 (undo commit)
1402 working directory now based on revision 9
1402 working directory now based on revision 9
1403 $ hg st
1403 $ hg st
1404 M sub/large4
1404 M sub/large4
1405 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1405 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1406 9:598410d3eb9a modify normal file largefile in repo d
1406 9:598410d3eb9a modify normal file largefile in repo d
1407 8:a381d2c8c80e modify normal file and largefile in repo b
1407 8:a381d2c8c80e modify normal file and largefile in repo b
1408 7:daea875e9014 add/edit more largefiles
1408 7:daea875e9014 add/edit more largefiles
1409 6:4355d653f84f edit files yet again
1409 6:4355d653f84f edit files yet again
1410 5:9d5af5072dbd edit files again
1410 5:9d5af5072dbd edit files again
1411 4:74c02385b94c move files
1411 4:74c02385b94c move files
1412 3:9e8fbc4bce62 copy files
1412 3:9e8fbc4bce62 copy files
1413 2:51a0ae4d5864 remove files
1413 2:51a0ae4d5864 remove files
1414 1:ce8896473775 edit files
1414 1:ce8896473775 edit files
1415 0:30d30fe6a5be add files
1415 0:30d30fe6a5be add files
1416 $ cat sub/large4
1416 $ cat sub/large4
1417 large4-modified-again
1417 large4-modified-again
1418
1418
1419 "update --check" refuses to update with uncommitted changes.
1419 "update --check" refuses to update with uncommitted changes.
1420 $ hg update --check 8
1420 $ hg update --check 8
1421 abort: uncommitted changes
1421 abort: uncommitted changes
1422 [255]
1422 [255]
1423
1423
1424 "update --clean" leaves correct largefiles in working copy, even when there is
1424 "update --clean" leaves correct largefiles in working copy, even when there is
1425 .orig files from revert in .hglf.
1425 .orig files from revert in .hglf.
1426
1426
1427 $ echo mistake > sub2/large7
1427 $ echo mistake > sub2/large7
1428 $ hg revert sub2/large7
1428 $ hg revert sub2/large7
1429 $ cat sub2/large7
1429 $ cat sub2/large7
1430 large7
1430 large7
1431 $ cat sub2/large7.orig
1431 $ cat sub2/large7.orig
1432 mistake
1432 mistake
1433 $ test ! -f .hglf/sub2/large7.orig
1433 $ test ! -f .hglf/sub2/large7.orig
1434
1434
1435 $ hg -q update --clean -r null
1435 $ hg -q update --clean -r null
1436 $ hg update --clean
1436 $ hg update --clean
1437 getting changed largefiles
1437 getting changed largefiles
1438 3 largefiles updated, 0 removed
1438 3 largefiles updated, 0 removed
1439 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1439 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1440 $ cat normal3
1440 $ cat normal3
1441 normal3-modified
1441 normal3-modified
1442 $ cat sub/normal4
1442 $ cat sub/normal4
1443 normal4-modified
1443 normal4-modified
1444 $ cat sub/large4
1444 $ cat sub/large4
1445 large4-modified
1445 large4-modified
1446 $ cat sub2/large6
1446 $ cat sub2/large6
1447 large6-modified
1447 large6-modified
1448 $ cat sub2/large7
1448 $ cat sub2/large7
1449 large7
1449 large7
1450 $ cat sub2/large7.orig
1450 $ cat sub2/large7.orig
1451 mistake
1451 mistake
1452 $ test ! -f .hglf/sub2/large7.orig
1452 $ test ! -f .hglf/sub2/large7.orig
1453
1453
1454 verify that largefile .orig file no longer is overwritten on every update -C:
1454 verify that largefile .orig file no longer is overwritten on every update -C:
1455 $ hg update --clean
1455 $ hg update --clean
1456 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1456 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1457 $ cat sub2/large7.orig
1457 $ cat sub2/large7.orig
1458 mistake
1458 mistake
1459 $ rm sub2/large7.orig
1459 $ rm sub2/large7.orig
1460
1460
1461 Now "update check" is happy.
1461 Now "update check" is happy.
1462 $ hg update --check 8
1462 $ hg update --check 8
1463 getting changed largefiles
1463 getting changed largefiles
1464 1 largefiles updated, 0 removed
1464 1 largefiles updated, 0 removed
1465 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1465 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1466 $ hg update --check
1466 $ hg update --check
1467 getting changed largefiles
1467 getting changed largefiles
1468 1 largefiles updated, 0 removed
1468 1 largefiles updated, 0 removed
1469 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1469 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1470
1470
1471 Test removing empty largefiles directories on update
1471 Test removing empty largefiles directories on update
1472 $ test -d sub2 && echo "sub2 exists"
1472 $ test -d sub2 && echo "sub2 exists"
1473 sub2 exists
1473 sub2 exists
1474 $ hg update -q null
1474 $ hg update -q null
1475 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1475 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1476 [1]
1476 [1]
1477 $ hg update -q
1477 $ hg update -q
1478
1478
1479 Test hg remove removes empty largefiles directories
1479 Test hg remove removes empty largefiles directories
1480 $ test -d sub2 && echo "sub2 exists"
1480 $ test -d sub2 && echo "sub2 exists"
1481 sub2 exists
1481 sub2 exists
1482 $ hg remove sub2/*
1482 $ hg remove sub2/*
1483 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1483 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1484 [1]
1484 [1]
1485 $ hg revert sub2/large6 sub2/large7
1485 $ hg revert sub2/large6 sub2/large7
1486
1486
1487 "revert" works on largefiles (and normal files too).
1487 "revert" works on largefiles (and normal files too).
1488 $ echo hack3 >> normal3
1488 $ echo hack3 >> normal3
1489 $ echo hack4 >> sub/normal4
1489 $ echo hack4 >> sub/normal4
1490 $ echo hack4 >> sub/large4
1490 $ echo hack4 >> sub/large4
1491 $ rm sub2/large6
1491 $ rm sub2/large6
1492 $ hg revert sub2/large6
1492 $ hg revert sub2/large6
1493 $ hg rm sub2/large6
1493 $ hg rm sub2/large6
1494 $ echo new >> sub2/large8
1494 $ echo new >> sub2/large8
1495 $ hg add --large sub2/large8
1495 $ hg add --large sub2/large8
1496 # XXX we don't really want to report that we're reverting the standin;
1496 # XXX we don't really want to report that we're reverting the standin;
1497 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1497 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1498 $ hg revert sub
1498 $ hg revert sub
1499 reverting .hglf/sub/large4
1499 reverting .hglf/sub/large4
1500 reverting sub/normal4
1500 reverting sub/normal4
1501 $ hg status
1501 $ hg status
1502 M normal3
1502 M normal3
1503 A sub2/large8
1503 A sub2/large8
1504 R sub2/large6
1504 R sub2/large6
1505 ? sub/large4.orig
1505 ? sub/large4.orig
1506 ? sub/normal4.orig
1506 ? sub/normal4.orig
1507 $ cat sub/normal4
1507 $ cat sub/normal4
1508 normal4-modified
1508 normal4-modified
1509 $ cat sub/large4
1509 $ cat sub/large4
1510 large4-modified
1510 large4-modified
1511 $ hg revert -a --no-backup
1511 $ hg revert -a --no-backup
1512 forgetting .hglf/sub2/large8
1512 forgetting .hglf/sub2/large8
1513 reverting normal3
1513 reverting normal3
1514 undeleting .hglf/sub2/large6
1514 undeleting .hglf/sub2/large6
1515 $ hg status
1515 $ hg status
1516 ? sub/large4.orig
1516 ? sub/large4.orig
1517 ? sub/normal4.orig
1517 ? sub/normal4.orig
1518 ? sub2/large8
1518 ? sub2/large8
1519 $ cat normal3
1519 $ cat normal3
1520 normal3-modified
1520 normal3-modified
1521 $ cat sub2/large6
1521 $ cat sub2/large6
1522 large6-modified
1522 large6-modified
1523 $ rm sub/*.orig sub2/large8
1523 $ rm sub/*.orig sub2/large8
1524
1524
1525 revert some files to an older revision
1525 revert some files to an older revision
1526 $ hg revert --no-backup -r 8 sub2
1526 $ hg revert --no-backup -r 8 sub2
1527 reverting .hglf/sub2/large6
1527 reverting .hglf/sub2/large6
1528 $ cat sub2/large6
1528 $ cat sub2/large6
1529 large6
1529 large6
1530 $ hg revert --no-backup -C -r '.^' sub2
1530 $ hg revert --no-backup -C -r '.^' sub2
1531 $ hg revert --no-backup sub2
1531 $ hg revert --no-backup sub2
1532 reverting .hglf/sub2/large6
1532 reverting .hglf/sub2/large6
1533 $ hg status
1533 $ hg status
1534
1534
1535 "verify --large" actually verifies largefiles
1535 "verify --large" actually verifies largefiles
1536
1536
1537 - Where Do We Come From? What Are We? Where Are We Going?
1537 - Where Do We Come From? What Are We? Where Are We Going?
1538 $ pwd
1538 $ pwd
1539 $TESTTMP/e
1539 $TESTTMP/e
1540 $ hg paths
1540 $ hg paths
1541 default = $TESTTMP/d
1541 default = $TESTTMP/d
1542
1542
1543 $ hg verify --large
1543 $ hg verify --large
1544 checking changesets
1544 checking changesets
1545 checking manifests
1545 checking manifests
1546 crosschecking files in changesets and manifests
1546 crosschecking files in changesets and manifests
1547 checking files
1547 checking files
1548 checking dirstate
1548 checked 10 changesets with 28 changes to 10 files
1549 checked 10 changesets with 28 changes to 10 files
1549 searching 1 changesets for largefiles
1550 searching 1 changesets for largefiles
1550 verified existence of 3 revisions of 3 largefiles
1551 verified existence of 3 revisions of 3 largefiles
1551
1552
1552 - introduce missing blob in local store repo and remote store
1553 - introduce missing blob in local store repo and remote store
1553 and make sure that this is caught:
1554 and make sure that this is caught:
1554
1555
1555 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1556 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1556 $ rm .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1557 $ rm .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1557 $ hg verify --large -q
1558 $ hg verify --large -q
1558 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1559 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1559 [1]
1560 [1]
1560
1561
1561 - introduce corruption and make sure that it is caught when checking content:
1562 - introduce corruption and make sure that it is caught when checking content:
1562 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1563 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1563 $ hg verify -q --large --lfc
1564 $ hg verify -q --large --lfc
1564 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1565 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1565 [1]
1566 [1]
1566
1567
1567 - cleanup
1568 - cleanup
1568 $ cp e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1569 $ cp e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1569 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 .hg/largefiles/
1570 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 .hg/largefiles/
1570
1571
1571 - verifying all revisions will fail because we didn't clone all largefiles to d:
1572 - verifying all revisions will fail because we didn't clone all largefiles to d:
1572 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1573 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1573 $ hg verify -q --lfa --lfc
1574 $ hg verify -q --lfa --lfc
1574 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64
1575 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64
1575 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d
1576 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d
1576 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f
1577 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f
1577 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1578 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1578 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1579 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1579 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1580 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1580 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1581 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1581 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c
1582 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c
1582 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9
1583 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9
1583 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0
1584 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0
1584 [1]
1585 [1]
1585
1586
1586 - cleanup
1587 - cleanup
1587 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1588 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1588 $ rm -f .hglf/sub/*.orig
1589 $ rm -f .hglf/sub/*.orig
1589
1590
1590 Update to revision with missing largefile - and make sure it really is missing
1591 Update to revision with missing largefile - and make sure it really is missing
1591
1592
1592 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1593 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1593 $ hg up -r 6
1594 $ hg up -r 6
1594 getting changed largefiles
1595 getting changed largefiles
1595 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1596 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1596 1 largefiles updated, 2 removed
1597 1 largefiles updated, 2 removed
1597 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1598 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1598 $ rm normal3
1599 $ rm normal3
1599 $ echo >> sub/normal4
1600 $ echo >> sub/normal4
1600 $ hg ci -m 'commit with missing files'
1601 $ hg ci -m 'commit with missing files'
1601 Invoking status precommit hook
1602 Invoking status precommit hook
1602 M sub/normal4
1603 M sub/normal4
1603 ! large3
1604 ! large3
1604 ! normal3
1605 ! normal3
1605 created new head
1606 created new head
1606 $ hg st
1607 $ hg st
1607 ! large3
1608 ! large3
1608 ! normal3
1609 ! normal3
1609 $ hg up -r.
1610 $ hg up -r.
1610 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1611 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1611 $ hg st
1612 $ hg st
1612 ! large3
1613 ! large3
1613 ! normal3
1614 ! normal3
1614 $ hg up -Cr.
1615 $ hg up -Cr.
1615 getting changed largefiles
1616 getting changed largefiles
1616 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1617 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1617 0 largefiles updated, 0 removed
1618 0 largefiles updated, 0 removed
1618 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1619 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1619 $ hg st
1620 $ hg st
1620 ! large3
1621 ! large3
1621 $ hg rollback
1622 $ hg rollback
1622 repository tip rolled back to revision 9 (undo commit)
1623 repository tip rolled back to revision 9 (undo commit)
1623 working directory now based on revision 6
1624 working directory now based on revision 6
1624
1625
1625 Merge with revision with missing largefile - and make sure it tries to fetch it.
1626 Merge with revision with missing largefile - and make sure it tries to fetch it.
1626
1627
1627 $ hg up -Cqr null
1628 $ hg up -Cqr null
1628 $ echo f > f
1629 $ echo f > f
1629 $ hg ci -Am branch
1630 $ hg ci -Am branch
1630 adding f
1631 adding f
1631 Invoking status precommit hook
1632 Invoking status precommit hook
1632 A f
1633 A f
1633 created new head
1634 created new head
1634 $ hg merge -r 6
1635 $ hg merge -r 6
1635 getting changed largefiles
1636 getting changed largefiles
1636 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1637 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1637 1 largefiles updated, 0 removed
1638 1 largefiles updated, 0 removed
1638 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1639 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1639 (branch merge, don't forget to commit)
1640 (branch merge, don't forget to commit)
1640
1641
1641 $ hg rollback -q
1642 $ hg rollback -q
1642 $ hg up -Cq
1643 $ hg up -Cq
1643
1644
1644 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1645 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1645
1646
1646 $ hg pull --all-largefiles
1647 $ hg pull --all-largefiles
1647 pulling from $TESTTMP/d
1648 pulling from $TESTTMP/d
1648 searching for changes
1649 searching for changes
1649 no changes found
1650 no changes found
1650
1651
1651 Merging does not revert to old versions of largefiles and also check
1652 Merging does not revert to old versions of largefiles and also check
1652 that merging after having pulled from a non-default remote works
1653 that merging after having pulled from a non-default remote works
1653 correctly.
1654 correctly.
1654
1655
1655 $ cd ..
1656 $ cd ..
1656 $ hg clone -r 7 e temp
1657 $ hg clone -r 7 e temp
1657 adding changesets
1658 adding changesets
1658 adding manifests
1659 adding manifests
1659 adding file changes
1660 adding file changes
1660 added 8 changesets with 24 changes to 10 files
1661 added 8 changesets with 24 changes to 10 files
1661 new changesets 30d30fe6a5be:daea875e9014 (8 drafts)
1662 new changesets 30d30fe6a5be:daea875e9014 (8 drafts)
1662 updating to branch default
1663 updating to branch default
1663 getting changed largefiles
1664 getting changed largefiles
1664 3 largefiles updated, 0 removed
1665 3 largefiles updated, 0 removed
1665 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1666 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1666 $ hg clone temp f
1667 $ hg clone temp f
1667 updating to branch default
1668 updating to branch default
1668 getting changed largefiles
1669 getting changed largefiles
1669 3 largefiles updated, 0 removed
1670 3 largefiles updated, 0 removed
1670 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1671 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1671 # Delete the largefiles in the largefiles system cache so that we have an
1672 # Delete the largefiles in the largefiles system cache so that we have an
1672 # opportunity to test that caching after a pull works.
1673 # opportunity to test that caching after a pull works.
1673 $ rm "${USERCACHE}"/*
1674 $ rm "${USERCACHE}"/*
1674 $ cd f
1675 $ cd f
1675 $ echo "large4-merge-test" > sub/large4
1676 $ echo "large4-merge-test" > sub/large4
1676 $ hg commit -m "Modify large4 to test merge"
1677 $ hg commit -m "Modify large4 to test merge"
1677 Invoking status precommit hook
1678 Invoking status precommit hook
1678 M sub/large4
1679 M sub/large4
1679 # Test --cache-largefiles flag
1680 # Test --cache-largefiles flag
1680 $ hg pull --lfrev 'heads(pulled())' ../e
1681 $ hg pull --lfrev 'heads(pulled())' ../e
1681 pulling from ../e
1682 pulling from ../e
1682 searching for changes
1683 searching for changes
1683 adding changesets
1684 adding changesets
1684 adding manifests
1685 adding manifests
1685 adding file changes
1686 adding file changes
1686 added 2 changesets with 4 changes to 4 files (+1 heads)
1687 added 2 changesets with 4 changes to 4 files (+1 heads)
1687 new changesets a381d2c8c80e:598410d3eb9a (2 drafts)
1688 new changesets a381d2c8c80e:598410d3eb9a (2 drafts)
1688 (run 'hg heads' to see heads, 'hg merge' to merge)
1689 (run 'hg heads' to see heads, 'hg merge' to merge)
1689 2 largefiles cached
1690 2 largefiles cached
1690 $ hg merge
1691 $ hg merge
1691 largefile sub/large4 has a merge conflict
1692 largefile sub/large4 has a merge conflict
1692 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1693 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1693 you can keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928.
1694 you can keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928.
1694 what do you want to do? l
1695 what do you want to do? l
1695 getting changed largefiles
1696 getting changed largefiles
1696 1 largefiles updated, 0 removed
1697 1 largefiles updated, 0 removed
1697 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1698 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1698 (branch merge, don't forget to commit)
1699 (branch merge, don't forget to commit)
1699 $ hg commit -m "Merge repos e and f"
1700 $ hg commit -m "Merge repos e and f"
1700 Invoking status precommit hook
1701 Invoking status precommit hook
1701 M normal3
1702 M normal3
1702 M sub/normal4
1703 M sub/normal4
1703 M sub2/large6
1704 M sub2/large6
1704 $ cat normal3
1705 $ cat normal3
1705 normal3-modified
1706 normal3-modified
1706 $ cat sub/normal4
1707 $ cat sub/normal4
1707 normal4-modified
1708 normal4-modified
1708 $ cat sub/large4
1709 $ cat sub/large4
1709 large4-merge-test
1710 large4-merge-test
1710 $ cat sub2/large6
1711 $ cat sub2/large6
1711 large6-modified
1712 large6-modified
1712 $ cat sub2/large7
1713 $ cat sub2/large7
1713 large7
1714 large7
1714
1715
1715 Test status after merging with a branch that introduces a new largefile:
1716 Test status after merging with a branch that introduces a new largefile:
1716
1717
1717 $ echo large > large
1718 $ echo large > large
1718 $ hg add --large large
1719 $ hg add --large large
1719 $ hg commit -m 'add largefile'
1720 $ hg commit -m 'add largefile'
1720 Invoking status precommit hook
1721 Invoking status precommit hook
1721 A large
1722 A large
1722 $ hg update -q ".^"
1723 $ hg update -q ".^"
1723 $ echo change >> normal3
1724 $ echo change >> normal3
1724 $ hg commit -m 'some change'
1725 $ hg commit -m 'some change'
1725 Invoking status precommit hook
1726 Invoking status precommit hook
1726 M normal3
1727 M normal3
1727 created new head
1728 created new head
1728 $ hg merge
1729 $ hg merge
1729 getting changed largefiles
1730 getting changed largefiles
1730 1 largefiles updated, 0 removed
1731 1 largefiles updated, 0 removed
1731 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1732 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1732 (branch merge, don't forget to commit)
1733 (branch merge, don't forget to commit)
1733 $ hg status
1734 $ hg status
1734 M large
1735 M large
1735
1736
1736 - make sure update of merge with removed largefiles fails as expected
1737 - make sure update of merge with removed largefiles fails as expected
1737 $ hg rm sub2/large6
1738 $ hg rm sub2/large6
1738 $ hg up -r.
1739 $ hg up -r.
1739 abort: outstanding uncommitted merge
1740 abort: outstanding uncommitted merge
1740 [20]
1741 [20]
1741
1742
1742 - revert should be able to revert files introduced in a pending merge
1743 - revert should be able to revert files introduced in a pending merge
1743 $ hg revert --all -r .
1744 $ hg revert --all -r .
1744 removing .hglf/large
1745 removing .hglf/large
1745 undeleting .hglf/sub2/large6
1746 undeleting .hglf/sub2/large6
1746
1747
1747 Test that a normal file and a largefile with the same name and path cannot
1748 Test that a normal file and a largefile with the same name and path cannot
1748 coexist.
1749 coexist.
1749
1750
1750 $ rm sub2/large7
1751 $ rm sub2/large7
1751 $ echo "largeasnormal" > sub2/large7
1752 $ echo "largeasnormal" > sub2/large7
1752 $ hg add sub2/large7
1753 $ hg add sub2/large7
1753 sub2/large7 already a largefile
1754 sub2/large7 already a largefile
1754
1755
1755 Test that transplanting a largefile change works correctly.
1756 Test that transplanting a largefile change works correctly.
1756
1757
1757 $ cd ..
1758 $ cd ..
1758 $ hg clone -r 8 d g
1759 $ hg clone -r 8 d g
1759 adding changesets
1760 adding changesets
1760 adding manifests
1761 adding manifests
1761 adding file changes
1762 adding file changes
1762 added 9 changesets with 26 changes to 10 files
1763 added 9 changesets with 26 changes to 10 files
1763 new changesets 30d30fe6a5be:a381d2c8c80e (9 drafts)
1764 new changesets 30d30fe6a5be:a381d2c8c80e (9 drafts)
1764 updating to branch default
1765 updating to branch default
1765 getting changed largefiles
1766 getting changed largefiles
1766 3 largefiles updated, 0 removed
1767 3 largefiles updated, 0 removed
1767 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1768 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1768 $ cd g
1769 $ cd g
1769 $ hg transplant -s ../d 598410d3eb9a
1770 $ hg transplant -s ../d 598410d3eb9a
1770 searching for changes
1771 searching for changes
1771 searching for changes
1772 searching for changes
1772 adding changesets
1773 adding changesets
1773 adding manifests
1774 adding manifests
1774 adding file changes
1775 adding file changes
1775 added 1 changesets with 2 changes to 2 files
1776 added 1 changesets with 2 changes to 2 files
1776 new changesets 598410d3eb9a (1 drafts)
1777 new changesets 598410d3eb9a (1 drafts)
1777 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1778 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1778 9:598410d3eb9a modify normal file largefile in repo d
1779 9:598410d3eb9a modify normal file largefile in repo d
1779 8:a381d2c8c80e modify normal file and largefile in repo b
1780 8:a381d2c8c80e modify normal file and largefile in repo b
1780 7:daea875e9014 add/edit more largefiles
1781 7:daea875e9014 add/edit more largefiles
1781 6:4355d653f84f edit files yet again
1782 6:4355d653f84f edit files yet again
1782 5:9d5af5072dbd edit files again
1783 5:9d5af5072dbd edit files again
1783 4:74c02385b94c move files
1784 4:74c02385b94c move files
1784 3:9e8fbc4bce62 copy files
1785 3:9e8fbc4bce62 copy files
1785 2:51a0ae4d5864 remove files
1786 2:51a0ae4d5864 remove files
1786 1:ce8896473775 edit files
1787 1:ce8896473775 edit files
1787 0:30d30fe6a5be add files
1788 0:30d30fe6a5be add files
1788 $ cat normal3
1789 $ cat normal3
1789 normal3-modified
1790 normal3-modified
1790 $ cat sub/normal4
1791 $ cat sub/normal4
1791 normal4-modified
1792 normal4-modified
1792 $ cat sub/large4
1793 $ cat sub/large4
1793 large4-modified
1794 large4-modified
1794 $ cat sub2/large6
1795 $ cat sub2/large6
1795 large6-modified
1796 large6-modified
1796 $ cat sub2/large7
1797 $ cat sub2/large7
1797 large7
1798 large7
1798
1799
1799 Cat a largefile
1800 Cat a largefile
1800 $ hg cat normal3
1801 $ hg cat normal3
1801 normal3-modified
1802 normal3-modified
1802 $ hg cat sub/large4
1803 $ hg cat sub/large4
1803 large4-modified
1804 large4-modified
1804 $ rm "${USERCACHE}"/*
1805 $ rm "${USERCACHE}"/*
1805 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1806 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1806 $ cat cat.out
1807 $ cat cat.out
1807 large4-modified
1808 large4-modified
1808 $ rm cat.out
1809 $ rm cat.out
1809 $ hg cat -r a381d2c8c80e normal3
1810 $ hg cat -r a381d2c8c80e normal3
1810 normal3-modified
1811 normal3-modified
1811 $ hg cat -r '.^' normal3
1812 $ hg cat -r '.^' normal3
1812 normal3-modified
1813 normal3-modified
1813 $ hg cat -r '.^' sub/large4 doesntexist
1814 $ hg cat -r '.^' sub/large4 doesntexist
1814 large4-modified
1815 large4-modified
1815 doesntexist: no such file in rev a381d2c8c80e
1816 doesntexist: no such file in rev a381d2c8c80e
1816 $ hg --cwd sub cat -r '.^' large4
1817 $ hg --cwd sub cat -r '.^' large4
1817 large4-modified
1818 large4-modified
1818 $ hg --cwd sub cat -r '.^' ../normal3
1819 $ hg --cwd sub cat -r '.^' ../normal3
1819 normal3-modified
1820 normal3-modified
1820 Cat a standin
1821 Cat a standin
1821 $ hg cat .hglf/sub/large4
1822 $ hg cat .hglf/sub/large4
1822 e166e74c7303192238d60af5a9c4ce9bef0b7928
1823 e166e74c7303192238d60af5a9c4ce9bef0b7928
1823 $ hg cat .hglf/normal3
1824 $ hg cat .hglf/normal3
1824 .hglf/normal3: no such file in rev 598410d3eb9a
1825 .hglf/normal3: no such file in rev 598410d3eb9a
1825 [1]
1826 [1]
1826
1827
1827 Test that renaming a largefile results in correct output for status
1828 Test that renaming a largefile results in correct output for status
1828
1829
1829 $ hg rename sub/large4 large4-renamed
1830 $ hg rename sub/large4 large4-renamed
1830 $ hg commit -m "test rename output"
1831 $ hg commit -m "test rename output"
1831 Invoking status precommit hook
1832 Invoking status precommit hook
1832 A large4-renamed
1833 A large4-renamed
1833 R sub/large4
1834 R sub/large4
1834 $ cat large4-renamed
1835 $ cat large4-renamed
1835 large4-modified
1836 large4-modified
1836 $ cd sub2
1837 $ cd sub2
1837 $ hg rename large6 large6-renamed
1838 $ hg rename large6 large6-renamed
1838 $ hg st
1839 $ hg st
1839 A sub2/large6-renamed
1840 A sub2/large6-renamed
1840 R sub2/large6
1841 R sub2/large6
1841 $ cd ..
1842 $ cd ..
1842
1843
1843 Test --normal flag
1844 Test --normal flag
1844
1845
1845 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1846 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1846 $ hg add --normal --large new-largefile
1847 $ hg add --normal --large new-largefile
1847 abort: --normal cannot be used with --large
1848 abort: --normal cannot be used with --large
1848 [255]
1849 [255]
1849 $ hg add --normal new-largefile
1850 $ hg add --normal new-largefile
1850 new-largefile: up to 69 MB of RAM may be required to manage this file
1851 new-largefile: up to 69 MB of RAM may be required to manage this file
1851 (use 'hg revert new-largefile' to cancel the pending addition)
1852 (use 'hg revert new-largefile' to cancel the pending addition)
1852 $ hg revert new-largefile
1853 $ hg revert new-largefile
1853 $ hg --config ui.large-file-limit=22M add --normal new-largefile
1854 $ hg --config ui.large-file-limit=22M add --normal new-largefile
1854
1855
1855 Test explicit commit of switch between normal and largefile - make sure both
1856 Test explicit commit of switch between normal and largefile - make sure both
1856 the add and the remove is committed.
1857 the add and the remove is committed.
1857
1858
1858 $ hg up -qC
1859 $ hg up -qC
1859 $ hg forget normal3 large4-renamed
1860 $ hg forget normal3 large4-renamed
1860 $ hg add --large normal3
1861 $ hg add --large normal3
1861 $ hg add large4-renamed
1862 $ hg add large4-renamed
1862 $ hg commit -m 'swap' normal3 large4-renamed
1863 $ hg commit -m 'swap' normal3 large4-renamed
1863 Invoking status precommit hook
1864 Invoking status precommit hook
1864 A large4-renamed
1865 A large4-renamed
1865 A normal3
1866 A normal3
1866 ? new-largefile
1867 ? new-largefile
1867 ? sub2/large6-renamed
1868 ? sub2/large6-renamed
1868 $ hg mani
1869 $ hg mani
1869 .hglf/normal3
1870 .hglf/normal3
1870 .hglf/sub2/large6
1871 .hglf/sub2/large6
1871 .hglf/sub2/large7
1872 .hglf/sub2/large7
1872 large4-renamed
1873 large4-renamed
1873 sub/normal4
1874 sub/normal4
1874
1875
1875 $ cd ..
1876 $ cd ..
1876
1877
1877
1878
1878
1879
@@ -1,412 +1,413 b''
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 $ mkdir "${USERCACHE}"
2 $ mkdir "${USERCACHE}"
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > largefiles =
5 > largefiles =
6 > share =
6 > share =
7 > strip =
7 > strip =
8 > convert =
8 > convert =
9 > [largefiles]
9 > [largefiles]
10 > minsize = 0.5
10 > minsize = 0.5
11 > patterns = **.other
11 > patterns = **.other
12 > **.dat
12 > **.dat
13 > usercache=${USERCACHE}
13 > usercache=${USERCACHE}
14 > EOF
14 > EOF
15
15
16 "lfconvert" works
16 "lfconvert" works
17 $ hg init bigfile-repo
17 $ hg init bigfile-repo
18 $ cd bigfile-repo
18 $ cd bigfile-repo
19 $ cat >> .hg/hgrc <<EOF
19 $ cat >> .hg/hgrc <<EOF
20 > [extensions]
20 > [extensions]
21 > largefiles = !
21 > largefiles = !
22 > EOF
22 > EOF
23 $ mkdir sub
23 $ mkdir sub
24 $ dd if=/dev/zero bs=1k count=256 > large 2> /dev/null
24 $ dd if=/dev/zero bs=1k count=256 > large 2> /dev/null
25 $ dd if=/dev/zero bs=1k count=256 > large2 2> /dev/null
25 $ dd if=/dev/zero bs=1k count=256 > large2 2> /dev/null
26 $ echo normal > normal1
26 $ echo normal > normal1
27 $ echo alsonormal > sub/normal2
27 $ echo alsonormal > sub/normal2
28 $ dd if=/dev/zero bs=1k count=10 > sub/maybelarge.dat 2> /dev/null
28 $ dd if=/dev/zero bs=1k count=10 > sub/maybelarge.dat 2> /dev/null
29 $ hg addremove
29 $ hg addremove
30 adding large
30 adding large
31 adding large2
31 adding large2
32 adding normal1
32 adding normal1
33 adding sub/maybelarge.dat
33 adding sub/maybelarge.dat
34 adding sub/normal2
34 adding sub/normal2
35 $ hg commit -m"add large, normal1" large normal1
35 $ hg commit -m"add large, normal1" large normal1
36 $ hg commit -m"add sub/*" sub
36 $ hg commit -m"add sub/*" sub
37
37
38 Test tag parsing
38 Test tag parsing
39 $ cat >> .hgtags <<EOF
39 $ cat >> .hgtags <<EOF
40 > IncorrectlyFormattedTag!
40 > IncorrectlyFormattedTag!
41 > invalidhash sometag
41 > invalidhash sometag
42 > 0123456789abcdef anothertag
42 > 0123456789abcdef anothertag
43 > EOF
43 > EOF
44 $ hg add .hgtags
44 $ hg add .hgtags
45 $ hg commit -m"add large2" large2 .hgtags
45 $ hg commit -m"add large2" large2 .hgtags
46
46
47 Test link+rename largefile codepath
47 Test link+rename largefile codepath
48 $ [ -d .hg/largefiles ] && echo fail || echo pass
48 $ [ -d .hg/largefiles ] && echo fail || echo pass
49 pass
49 pass
50 $ cd ..
50 $ cd ..
51 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
51 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
52 initializing destination largefiles-repo
52 initializing destination largefiles-repo
53 skipping incorrectly formatted tag IncorrectlyFormattedTag!
53 skipping incorrectly formatted tag IncorrectlyFormattedTag!
54 skipping incorrectly formatted id invalidhash
54 skipping incorrectly formatted id invalidhash
55 no mapping for id 0123456789abcdef
55 no mapping for id 0123456789abcdef
56 #if symlink
56 #if symlink
57 $ hg --cwd bigfile-repo rename large2 large3
57 $ hg --cwd bigfile-repo rename large2 large3
58 $ ln -sf large bigfile-repo/large3
58 $ ln -sf large bigfile-repo/large3
59 $ hg --cwd bigfile-repo commit -m"make large2 a symlink" large2 large3
59 $ hg --cwd bigfile-repo commit -m"make large2 a symlink" large2 large3
60 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo-symlink
60 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo-symlink
61 initializing destination largefiles-repo-symlink
61 initializing destination largefiles-repo-symlink
62 skipping incorrectly formatted tag IncorrectlyFormattedTag!
62 skipping incorrectly formatted tag IncorrectlyFormattedTag!
63 skipping incorrectly formatted id invalidhash
63 skipping incorrectly formatted id invalidhash
64 no mapping for id 0123456789abcdef
64 no mapping for id 0123456789abcdef
65 abort: renamed/copied largefile large3 becomes symlink
65 abort: renamed/copied largefile large3 becomes symlink
66 [255]
66 [255]
67 #endif
67 #endif
68 $ cd bigfile-repo
68 $ cd bigfile-repo
69 $ hg strip --no-backup 2
69 $ hg strip --no-backup 2
70 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
70 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
71 $ cd ..
71 $ cd ..
72 $ rm -rf largefiles-repo largefiles-repo-symlink
72 $ rm -rf largefiles-repo largefiles-repo-symlink
73
73
74 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
74 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
75 initializing destination largefiles-repo
75 initializing destination largefiles-repo
76
76
77 "lfconvert" converts content correctly
77 "lfconvert" converts content correctly
78 $ cd largefiles-repo
78 $ cd largefiles-repo
79 $ hg up
79 $ hg up
80 getting changed largefiles
80 getting changed largefiles
81 2 largefiles updated, 0 removed
81 2 largefiles updated, 0 removed
82 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 $ hg locate
83 $ hg locate
84 .hglf/large
84 .hglf/large
85 .hglf/sub/maybelarge.dat
85 .hglf/sub/maybelarge.dat
86 normal1
86 normal1
87 sub/normal2
87 sub/normal2
88 $ cat normal1
88 $ cat normal1
89 normal
89 normal
90 $ cat sub/normal2
90 $ cat sub/normal2
91 alsonormal
91 alsonormal
92 $ md5sum.py large sub/maybelarge.dat
92 $ md5sum.py large sub/maybelarge.dat
93 ec87a838931d4d5d2e94a04644788a55 large
93 ec87a838931d4d5d2e94a04644788a55 large
94 1276481102f218c981e0324180bafd9f sub/maybelarge.dat
94 1276481102f218c981e0324180bafd9f sub/maybelarge.dat
95
95
96 "lfconvert" adds 'largefiles' to .hg/requires.
96 "lfconvert" adds 'largefiles' to .hg/requires.
97 $ hg debugrequires
97 $ hg debugrequires
98 dotencode
98 dotencode
99 dirstate-v2 (dirstate-v2 !)
99 dirstate-v2 (dirstate-v2 !)
100 fncache
100 fncache
101 generaldelta
101 generaldelta
102 largefiles
102 largefiles
103 persistent-nodemap (rust !)
103 persistent-nodemap (rust !)
104 revlog-compression-zstd (zstd !)
104 revlog-compression-zstd (zstd !)
105 revlogv1
105 revlogv1
106 share-safe
106 share-safe
107 sparserevlog
107 sparserevlog
108 store
108 store
109 testonly-simplestore (reposimplestore !)
109 testonly-simplestore (reposimplestore !)
110
110
111 "lfconvert" includes a newline at the end of the standin files.
111 "lfconvert" includes a newline at the end of the standin files.
112 $ cat .hglf/large .hglf/sub/maybelarge.dat
112 $ cat .hglf/large .hglf/sub/maybelarge.dat
113 2e000fa7e85759c7f4c254d4d9c33ef481e459a7
113 2e000fa7e85759c7f4c254d4d9c33ef481e459a7
114 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
114 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
115 $ cd ..
115 $ cd ..
116
116
117 add some changesets to rename/remove/merge
117 add some changesets to rename/remove/merge
118 $ cd bigfile-repo
118 $ cd bigfile-repo
119 $ hg mv -q sub stuff
119 $ hg mv -q sub stuff
120 $ hg commit -m"rename sub/ to stuff/"
120 $ hg commit -m"rename sub/ to stuff/"
121 $ hg update -q 1
121 $ hg update -q 1
122 $ echo blah >> normal3
122 $ echo blah >> normal3
123 $ echo blah >> sub/normal2
123 $ echo blah >> sub/normal2
124 $ echo blah >> sub/maybelarge.dat
124 $ echo blah >> sub/maybelarge.dat
125 $ md5sum.py sub/maybelarge.dat
125 $ md5sum.py sub/maybelarge.dat
126 1dd0b99ff80e19cff409702a1d3f5e15 sub/maybelarge.dat
126 1dd0b99ff80e19cff409702a1d3f5e15 sub/maybelarge.dat
127 $ hg commit -A -m"add normal3, modify sub/*"
127 $ hg commit -A -m"add normal3, modify sub/*"
128 adding normal3
128 adding normal3
129 created new head
129 created new head
130 $ hg rm large normal3
130 $ hg rm large normal3
131 $ hg commit -q -m"remove large, normal3"
131 $ hg commit -q -m"remove large, normal3"
132 $ hg merge
132 $ hg merge
133 tool internal:merge (for pattern stuff/maybelarge.dat) can't handle binary
133 tool internal:merge (for pattern stuff/maybelarge.dat) can't handle binary
134 no tool found to merge stuff/maybelarge.dat
134 no tool found to merge stuff/maybelarge.dat
135 file 'stuff/maybelarge.dat' needs to be resolved.
135 file 'stuff/maybelarge.dat' needs to be resolved.
136 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
136 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
137 What do you want to do? u
137 What do you want to do? u
138 merging sub/normal2 and stuff/normal2 to stuff/normal2
138 merging sub/normal2 and stuff/normal2 to stuff/normal2
139 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
139 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
140 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
140 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
141 [1]
141 [1]
142 $ hg cat -r . sub/maybelarge.dat > stuff/maybelarge.dat
142 $ hg cat -r . sub/maybelarge.dat > stuff/maybelarge.dat
143 $ hg resolve -m stuff/maybelarge.dat
143 $ hg resolve -m stuff/maybelarge.dat
144 (no more unresolved files)
144 (no more unresolved files)
145 $ hg commit -m"merge"
145 $ hg commit -m"merge"
146 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
146 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
147 @ 5:4884f215abda merge
147 @ 5:4884f215abda merge
148 |\
148 |\
149 | o 4:7285f817b77e remove large, normal3
149 | o 4:7285f817b77e remove large, normal3
150 | |
150 | |
151 | o 3:67e3892e3534 add normal3, modify sub/*
151 | o 3:67e3892e3534 add normal3, modify sub/*
152 | |
152 | |
153 o | 2:c96c8beb5d56 rename sub/ to stuff/
153 o | 2:c96c8beb5d56 rename sub/ to stuff/
154 |/
154 |/
155 o 1:020c65d24e11 add sub/*
155 o 1:020c65d24e11 add sub/*
156 |
156 |
157 o 0:117b8328f97a add large, normal1
157 o 0:117b8328f97a add large, normal1
158
158
159 $ cd ..
159 $ cd ..
160
160
161 lfconvert with rename, merge, and remove
161 lfconvert with rename, merge, and remove
162 $ rm -rf largefiles-repo
162 $ rm -rf largefiles-repo
163 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
163 $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
164 initializing destination largefiles-repo
164 initializing destination largefiles-repo
165 $ cd largefiles-repo
165 $ cd largefiles-repo
166 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
166 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
167 o 5:9cc5aa7204f0 merge
167 o 5:9cc5aa7204f0 merge
168 |\
168 |\
169 | o 4:a5a02de7a8e4 remove large, normal3
169 | o 4:a5a02de7a8e4 remove large, normal3
170 | |
170 | |
171 | o 3:55759520c76f add normal3, modify sub/*
171 | o 3:55759520c76f add normal3, modify sub/*
172 | |
172 | |
173 o | 2:261ad3f3f037 rename sub/ to stuff/
173 o | 2:261ad3f3f037 rename sub/ to stuff/
174 |/
174 |/
175 o 1:334e5237836d add sub/*
175 o 1:334e5237836d add sub/*
176 |
176 |
177 o 0:d4892ec57ce2 add large, normal1
177 o 0:d4892ec57ce2 add large, normal1
178
178
179 $ hg locate -r 2
179 $ hg locate -r 2
180 .hglf/large
180 .hglf/large
181 .hglf/stuff/maybelarge.dat
181 .hglf/stuff/maybelarge.dat
182 normal1
182 normal1
183 stuff/normal2
183 stuff/normal2
184 $ hg locate -r 3
184 $ hg locate -r 3
185 .hglf/large
185 .hglf/large
186 .hglf/sub/maybelarge.dat
186 .hglf/sub/maybelarge.dat
187 normal1
187 normal1
188 normal3
188 normal3
189 sub/normal2
189 sub/normal2
190 $ hg locate -r 4
190 $ hg locate -r 4
191 .hglf/sub/maybelarge.dat
191 .hglf/sub/maybelarge.dat
192 normal1
192 normal1
193 sub/normal2
193 sub/normal2
194 $ hg locate -r 5
194 $ hg locate -r 5
195 .hglf/stuff/maybelarge.dat
195 .hglf/stuff/maybelarge.dat
196 normal1
196 normal1
197 stuff/normal2
197 stuff/normal2
198 $ hg update
198 $ hg update
199 getting changed largefiles
199 getting changed largefiles
200 1 largefiles updated, 0 removed
200 1 largefiles updated, 0 removed
201 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
202 $ cat stuff/normal2
202 $ cat stuff/normal2
203 alsonormal
203 alsonormal
204 blah
204 blah
205 $ md5sum.py stuff/maybelarge.dat
205 $ md5sum.py stuff/maybelarge.dat
206 1dd0b99ff80e19cff409702a1d3f5e15 stuff/maybelarge.dat
206 1dd0b99ff80e19cff409702a1d3f5e15 stuff/maybelarge.dat
207 $ cat .hglf/stuff/maybelarge.dat
207 $ cat .hglf/stuff/maybelarge.dat
208 76236b6a2c6102826c61af4297dd738fb3b1de38
208 76236b6a2c6102826c61af4297dd738fb3b1de38
209 $ cd ..
209 $ cd ..
210
210
211 "lfconvert" error cases
211 "lfconvert" error cases
212 $ hg lfconvert http://localhost/foo foo
212 $ hg lfconvert http://localhost/foo foo
213 abort: http://localhost/foo is not a local Mercurial repo
213 abort: http://localhost/foo is not a local Mercurial repo
214 [255]
214 [255]
215 $ hg lfconvert foo ssh://localhost/foo
215 $ hg lfconvert foo ssh://localhost/foo
216 abort: ssh://localhost/foo is not a local Mercurial repo
216 abort: ssh://localhost/foo is not a local Mercurial repo
217 [255]
217 [255]
218 $ hg lfconvert nosuchrepo foo
218 $ hg lfconvert nosuchrepo foo
219 abort: repository nosuchrepo not found
219 abort: repository nosuchrepo not found
220 [255]
220 [255]
221 $ hg share -q -U bigfile-repo shared
221 $ hg share -q -U bigfile-repo shared
222 $ printf 'bogus' > shared/.hg/sharedpath
222 $ printf 'bogus' > shared/.hg/sharedpath
223 $ hg lfconvert shared foo
223 $ hg lfconvert shared foo
224 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/bogus
224 abort: .hg/sharedpath points to nonexistent directory $TESTTMP/bogus
225 [255]
225 [255]
226 $ hg lfconvert bigfile-repo largefiles-repo
226 $ hg lfconvert bigfile-repo largefiles-repo
227 initializing destination largefiles-repo
227 initializing destination largefiles-repo
228 abort: repository largefiles-repo already exists
228 abort: repository largefiles-repo already exists
229 [255]
229 [255]
230
230
231 add another largefile to the new largefiles repo
231 add another largefile to the new largefiles repo
232 $ cd largefiles-repo
232 $ cd largefiles-repo
233 $ dd if=/dev/zero bs=1k count=1k > anotherlarge 2> /dev/null
233 $ dd if=/dev/zero bs=1k count=1k > anotherlarge 2> /dev/null
234 $ hg add --lfsize=1 anotherlarge
234 $ hg add --lfsize=1 anotherlarge
235 $ hg commit -m "add anotherlarge (should be a largefile)"
235 $ hg commit -m "add anotherlarge (should be a largefile)"
236 $ cat .hglf/anotherlarge
236 $ cat .hglf/anotherlarge
237 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
237 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
238 $ hg tag mytag
238 $ hg tag mytag
239 $ cd ..
239 $ cd ..
240
240
241 round-trip: converting back to a normal (non-largefiles) repo with
241 round-trip: converting back to a normal (non-largefiles) repo with
242 "lfconvert --to-normal" should give the same as ../bigfile-repo. The
242 "lfconvert --to-normal" should give the same as ../bigfile-repo. The
243 convert extension is disabled to show config items can be loaded without it.
243 convert extension is disabled to show config items can be loaded without it.
244 $ cd largefiles-repo
244 $ cd largefiles-repo
245 $ hg --config extensions.convert=! lfconvert --to-normal . ../normal-repo
245 $ hg --config extensions.convert=! lfconvert --to-normal . ../normal-repo
246 initializing destination ../normal-repo
246 initializing destination ../normal-repo
247 0 additional largefiles cached
247 0 additional largefiles cached
248 scanning source...
248 scanning source...
249 sorting...
249 sorting...
250 converting...
250 converting...
251 7 add large, normal1
251 7 add large, normal1
252 6 add sub/*
252 6 add sub/*
253 5 rename sub/ to stuff/
253 5 rename sub/ to stuff/
254 4 add normal3, modify sub/*
254 4 add normal3, modify sub/*
255 3 remove large, normal3
255 3 remove large, normal3
256 2 merge
256 2 merge
257 1 add anotherlarge (should be a largefile)
257 1 add anotherlarge (should be a largefile)
258 0 Added tag mytag for changeset 17126745edfd
258 0 Added tag mytag for changeset 17126745edfd
259 $ cd ../normal-repo
259 $ cd ../normal-repo
260 $ cat >> .hg/hgrc <<EOF
260 $ cat >> .hg/hgrc <<EOF
261 > [extensions]
261 > [extensions]
262 > largefiles = !
262 > largefiles = !
263 > EOF
263 > EOF
264
264
265 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
265 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
266 o 7:b5fedc110b9d Added tag mytag for changeset 867ab992ecf4
266 o 7:b5fedc110b9d Added tag mytag for changeset 867ab992ecf4
267 |
267 |
268 o 6:867ab992ecf4 add anotherlarge (should be a largefile)
268 o 6:867ab992ecf4 add anotherlarge (should be a largefile)
269 |
269 |
270 o 5:4884f215abda merge
270 o 5:4884f215abda merge
271 |\
271 |\
272 | o 4:7285f817b77e remove large, normal3
272 | o 4:7285f817b77e remove large, normal3
273 | |
273 | |
274 | o 3:67e3892e3534 add normal3, modify sub/*
274 | o 3:67e3892e3534 add normal3, modify sub/*
275 | |
275 | |
276 o | 2:c96c8beb5d56 rename sub/ to stuff/
276 o | 2:c96c8beb5d56 rename sub/ to stuff/
277 |/
277 |/
278 o 1:020c65d24e11 add sub/*
278 o 1:020c65d24e11 add sub/*
279 |
279 |
280 o 0:117b8328f97a add large, normal1
280 o 0:117b8328f97a add large, normal1
281
281
282 $ hg update
282 $ hg update
283 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 $ hg locate
284 $ hg locate
285 .hgtags
285 .hgtags
286 anotherlarge
286 anotherlarge
287 normal1
287 normal1
288 stuff/maybelarge.dat
288 stuff/maybelarge.dat
289 stuff/normal2
289 stuff/normal2
290 $ [ -d .hg/largefiles ] && echo fail || echo pass
290 $ [ -d .hg/largefiles ] && echo fail || echo pass
291 pass
291 pass
292
292
293 $ cd ..
293 $ cd ..
294
294
295 Clearing the usercache ensures that commitctx doesn't try to cache largefiles
295 Clearing the usercache ensures that commitctx doesn't try to cache largefiles
296 from the working dir on a convert.
296 from the working dir on a convert.
297 $ rm "${USERCACHE}"/*
297 $ rm "${USERCACHE}"/*
298 $ hg convert largefiles-repo
298 $ hg convert largefiles-repo
299 assuming destination largefiles-repo-hg
299 assuming destination largefiles-repo-hg
300 initializing destination largefiles-repo-hg repository
300 initializing destination largefiles-repo-hg repository
301 scanning source...
301 scanning source...
302 sorting...
302 sorting...
303 converting...
303 converting...
304 7 add large, normal1
304 7 add large, normal1
305 6 add sub/*
305 6 add sub/*
306 5 rename sub/ to stuff/
306 5 rename sub/ to stuff/
307 4 add normal3, modify sub/*
307 4 add normal3, modify sub/*
308 3 remove large, normal3
308 3 remove large, normal3
309 2 merge
309 2 merge
310 1 add anotherlarge (should be a largefile)
310 1 add anotherlarge (should be a largefile)
311 0 Added tag mytag for changeset 17126745edfd
311 0 Added tag mytag for changeset 17126745edfd
312
312
313 $ hg -R largefiles-repo-hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
313 $ hg -R largefiles-repo-hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
314 o 7:2f08f66459b7 Added tag mytag for changeset 17126745edfd
314 o 7:2f08f66459b7 Added tag mytag for changeset 17126745edfd
315 |
315 |
316 o 6:17126745edfd add anotherlarge (should be a largefile)
316 o 6:17126745edfd add anotherlarge (should be a largefile)
317 |
317 |
318 o 5:9cc5aa7204f0 merge
318 o 5:9cc5aa7204f0 merge
319 |\
319 |\
320 | o 4:a5a02de7a8e4 remove large, normal3
320 | o 4:a5a02de7a8e4 remove large, normal3
321 | |
321 | |
322 | o 3:55759520c76f add normal3, modify sub/*
322 | o 3:55759520c76f add normal3, modify sub/*
323 | |
323 | |
324 o | 2:261ad3f3f037 rename sub/ to stuff/
324 o | 2:261ad3f3f037 rename sub/ to stuff/
325 |/
325 |/
326 o 1:334e5237836d add sub/*
326 o 1:334e5237836d add sub/*
327 |
327 |
328 o 0:d4892ec57ce2 add large, normal1
328 o 0:d4892ec57ce2 add large, normal1
329
329
330 Verify will fail (for now) if the usercache is purged before converting, since
330 Verify will fail (for now) if the usercache is purged before converting, since
331 largefiles are not cached in the converted repo's local store by the conversion
331 largefiles are not cached in the converted repo's local store by the conversion
332 process.
332 process.
333 $ cd largefiles-repo-hg
333 $ cd largefiles-repo-hg
334 $ cat >> .hg/hgrc <<EOF
334 $ cat >> .hg/hgrc <<EOF
335 > [experimental]
335 > [experimental]
336 > evolution.createmarkers=True
336 > evolution.createmarkers=True
337 > EOF
337 > EOF
338 $ hg debugobsolete `hg log -r tip -T "{node}"`
338 $ hg debugobsolete `hg log -r tip -T "{node}"`
339 1 new obsolescence markers
339 1 new obsolescence markers
340 obsoleted 1 changesets
340 obsoleted 1 changesets
341 $ cd ..
341 $ cd ..
342
342
343 $ hg -R largefiles-repo-hg verify --large --lfa
343 $ hg -R largefiles-repo-hg verify --large --lfa
344 checking changesets
344 checking changesets
345 checking manifests
345 checking manifests
346 crosschecking files in changesets and manifests
346 crosschecking files in changesets and manifests
347 checking files
347 checking files
348 checking dirstate
348 checked 8 changesets with 13 changes to 9 files
349 checked 8 changesets with 13 changes to 9 files
349 searching 7 changesets for largefiles
350 searching 7 changesets for largefiles
350 changeset 0:d4892ec57ce2: large references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/2e000fa7e85759c7f4c254d4d9c33ef481e459a7
351 changeset 0:d4892ec57ce2: large references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/2e000fa7e85759c7f4c254d4d9c33ef481e459a7
351 changeset 1:334e5237836d: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
352 changeset 1:334e5237836d: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
352 changeset 2:261ad3f3f037: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
353 changeset 2:261ad3f3f037: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c
353 changeset 3:55759520c76f: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38
354 changeset 3:55759520c76f: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38
354 changeset 5:9cc5aa7204f0: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38
355 changeset 5:9cc5aa7204f0: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38
355 changeset 6:17126745edfd: anotherlarge references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
356 changeset 6:17126745edfd: anotherlarge references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
356 verified existence of 6 revisions of 4 largefiles
357 verified existence of 6 revisions of 4 largefiles
357 [1]
358 [1]
358 $ hg -R largefiles-repo-hg showconfig paths
359 $ hg -R largefiles-repo-hg showconfig paths
359 [1]
360 [1]
360
361
361
362
362 Avoid a traceback if a largefile isn't available (issue3519)
363 Avoid a traceback if a largefile isn't available (issue3519)
363
364
364 Ensure the largefile can be cached in the source if necessary
365 Ensure the largefile can be cached in the source if necessary
365 $ hg clone -U largefiles-repo issue3519
366 $ hg clone -U largefiles-repo issue3519
366 $ rm -f "${USERCACHE}"/*
367 $ rm -f "${USERCACHE}"/*
367 $ hg -R issue3519 branch -q mybranch
368 $ hg -R issue3519 branch -q mybranch
368 $ hg -R issue3519 ci -m 'change branch name only'
369 $ hg -R issue3519 ci -m 'change branch name only'
369 $ hg lfconvert --to-normal issue3519 normalized3519
370 $ hg lfconvert --to-normal issue3519 normalized3519
370 initializing destination normalized3519
371 initializing destination normalized3519
371 4 additional largefiles cached
372 4 additional largefiles cached
372 scanning source...
373 scanning source...
373 sorting...
374 sorting...
374 converting...
375 converting...
375 8 add large, normal1
376 8 add large, normal1
376 7 add sub/*
377 7 add sub/*
377 6 rename sub/ to stuff/
378 6 rename sub/ to stuff/
378 5 add normal3, modify sub/*
379 5 add normal3, modify sub/*
379 4 remove large, normal3
380 4 remove large, normal3
380 3 merge
381 3 merge
381 2 add anotherlarge (should be a largefile)
382 2 add anotherlarge (should be a largefile)
382 1 Added tag mytag for changeset 17126745edfd
383 1 Added tag mytag for changeset 17126745edfd
383 0 change branch name only
384 0 change branch name only
384
385
385 Ensure empty commits aren't lost in the conversion
386 Ensure empty commits aren't lost in the conversion
386 $ hg -R normalized3519 log -r tip -T '{desc}\n'
387 $ hg -R normalized3519 log -r tip -T '{desc}\n'
387 change branch name only
388 change branch name only
388
389
389 Ensure the abort message is useful if a largefile is entirely unavailable
390 Ensure the abort message is useful if a largefile is entirely unavailable
390 $ rm -rf normalized3519
391 $ rm -rf normalized3519
391 $ rm "${USERCACHE}"/*
392 $ rm "${USERCACHE}"/*
392 $ rm issue3519/.hg/largefiles/*
393 $ rm issue3519/.hg/largefiles/*
393 $ rm largefiles-repo/.hg/largefiles/*
394 $ rm largefiles-repo/.hg/largefiles/*
394 $ hg lfconvert --to-normal issue3519 normalized3519
395 $ hg lfconvert --to-normal issue3519 normalized3519
395 initializing destination normalized3519
396 initializing destination normalized3519
396 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
397 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
397 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
398 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
398 sub/maybelarge.dat: largefile 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c not available from file:/*/$TESTTMP/largefiles-repo (glob)
399 sub/maybelarge.dat: largefile 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c not available from file:/*/$TESTTMP/largefiles-repo (glob)
399 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
400 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
400 stuff/maybelarge.dat: largefile 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c not available from file:/*/$TESTTMP/largefiles-repo (glob)
401 stuff/maybelarge.dat: largefile 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c not available from file:/*/$TESTTMP/largefiles-repo (glob)
401 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
402 large: largefile 2e000fa7e85759c7f4c254d4d9c33ef481e459a7 not available from file:/*/$TESTTMP/largefiles-repo (glob)
402 sub/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
403 sub/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
403 sub/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
404 sub/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
404 stuff/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
405 stuff/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
405 anotherlarge: largefile 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 not available from file:/*/$TESTTMP/largefiles-repo (glob)
406 anotherlarge: largefile 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 not available from file:/*/$TESTTMP/largefiles-repo (glob)
406 stuff/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
407 stuff/maybelarge.dat: largefile 76236b6a2c6102826c61af4297dd738fb3b1de38 not available from file:/*/$TESTTMP/largefiles-repo (glob)
407 0 additional largefiles cached
408 0 additional largefiles cached
408 11 largefiles failed to download
409 11 largefiles failed to download
409 abort: all largefiles must be present locally
410 abort: all largefiles must be present locally
410 [255]
411 [255]
411
412
412
413
@@ -1,1240 +1,1248 b''
1 #require no-reposimplestore no-chg
1 #require no-reposimplestore no-chg
2
2
3 $ hg init requirements
3 $ hg init requirements
4 $ cd requirements
4 $ cd requirements
5
5
6 # LFS not loaded by default.
6 # LFS not loaded by default.
7
7
8 $ hg config extensions
8 $ hg config extensions
9 [1]
9 [1]
10
10
11 # Adding lfs to requires file will auto-load lfs extension.
11 # Adding lfs to requires file will auto-load lfs extension.
12
12
13 $ echo lfs >> .hg/requires
13 $ echo lfs >> .hg/requires
14 $ hg config extensions
14 $ hg config extensions
15 extensions.lfs=
15 extensions.lfs=
16
16
17 # But only if there is no config entry for the extension already.
17 # But only if there is no config entry for the extension already.
18
18
19 $ cat > .hg/hgrc << EOF
19 $ cat > .hg/hgrc << EOF
20 > [extensions]
20 > [extensions]
21 > lfs=!
21 > lfs=!
22 > EOF
22 > EOF
23
23
24 $ hg config extensions
24 $ hg config extensions
25 abort: repository requires features unknown to this Mercurial: lfs
25 abort: repository requires features unknown to this Mercurial: lfs
26 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
26 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
27 [255]
27 [255]
28
28
29 $ cat > .hg/hgrc << EOF
29 $ cat > .hg/hgrc << EOF
30 > [extensions]
30 > [extensions]
31 > lfs=
31 > lfs=
32 > EOF
32 > EOF
33
33
34 $ hg config extensions
34 $ hg config extensions
35 extensions.lfs=
35 extensions.lfs=
36
36
37 $ cat > .hg/hgrc << EOF
37 $ cat > .hg/hgrc << EOF
38 > [extensions]
38 > [extensions]
39 > lfs = missing.py
39 > lfs = missing.py
40 > EOF
40 > EOF
41
41
42 $ hg config extensions
42 $ hg config extensions
43 \*\*\* failed to import extension "lfs" from missing.py: [Errno *] $ENOENT$: 'missing.py' (glob)
43 \*\*\* failed to import extension "lfs" from missing.py: [Errno *] $ENOENT$: 'missing.py' (glob)
44 abort: repository requires features unknown to this Mercurial: lfs
44 abort: repository requires features unknown to this Mercurial: lfs
45 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
45 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
46 [255]
46 [255]
47
47
48 $ cd ..
48 $ cd ..
49
49
50 # Initial setup
50 # Initial setup
51
51
52 $ cat >> $HGRCPATH << EOF
52 $ cat >> $HGRCPATH << EOF
53 > [extensions]
53 > [extensions]
54 > lfs=
54 > lfs=
55 > [lfs]
55 > [lfs]
56 > # Test deprecated config
56 > # Test deprecated config
57 > threshold=1000B
57 > threshold=1000B
58 > EOF
58 > EOF
59
59
60 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
60 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
61
61
62 # Prepare server and enable extension
62 # Prepare server and enable extension
63 $ hg init server
63 $ hg init server
64 $ hg clone -q server client
64 $ hg clone -q server client
65 $ cd client
65 $ cd client
66
66
67 # Commit small file
67 # Commit small file
68 $ echo s > smallfile
68 $ echo s > smallfile
69 $ echo '**.py = LF' > .hgeol
69 $ echo '**.py = LF' > .hgeol
70 $ hg --config lfs.track='"size(\">1000B\")"' commit -Aqm "add small file"
70 $ hg --config lfs.track='"size(\">1000B\")"' commit -Aqm "add small file"
71 hg: parse error: unsupported file pattern: size(">1000B")
71 hg: parse error: unsupported file pattern: size(">1000B")
72 (paths must be prefixed with "path:")
72 (paths must be prefixed with "path:")
73 [10]
73 [10]
74 $ hg --config lfs.track='size(">1000B")' commit -Aqm "add small file"
74 $ hg --config lfs.track='size(">1000B")' commit -Aqm "add small file"
75
75
76 # Commit large file
76 # Commit large file
77 $ echo $LONG > largefile
77 $ echo $LONG > largefile
78 $ hg debugrequires | grep lfs
78 $ hg debugrequires | grep lfs
79 [1]
79 [1]
80 $ hg commit --traceback -Aqm "add large file"
80 $ hg commit --traceback -Aqm "add large file"
81 $ hg debugrequires | grep lfs
81 $ hg debugrequires | grep lfs
82 lfs
82 lfs
83
83
84 # Ensure metadata is stored
84 # Ensure metadata is stored
85 $ hg debugdata largefile 0
85 $ hg debugdata largefile 0
86 version https://git-lfs.github.com/spec/v1
86 version https://git-lfs.github.com/spec/v1
87 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
87 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
88 size 1501
88 size 1501
89 x-is-binary 0
89 x-is-binary 0
90
90
91 # Check the blobstore is populated
91 # Check the blobstore is populated
92 $ find .hg/store/lfs/objects | sort
92 $ find .hg/store/lfs/objects | sort
93 .hg/store/lfs/objects
93 .hg/store/lfs/objects
94 .hg/store/lfs/objects/f1
94 .hg/store/lfs/objects/f1
95 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
95 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
96
96
97 # Check the blob stored contains the actual contents of the file
97 # Check the blob stored contains the actual contents of the file
98 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
98 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
99 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
99 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
100
100
101 # Push changes to the server
101 # Push changes to the server
102
102
103 $ hg push
103 $ hg push
104 pushing to $TESTTMP/server
104 pushing to $TESTTMP/server
105 searching for changes
105 searching for changes
106 abort: lfs.url needs to be configured
106 abort: lfs.url needs to be configured
107 [255]
107 [255]
108
108
109 $ cat >> $HGRCPATH << EOF
109 $ cat >> $HGRCPATH << EOF
110 > [lfs]
110 > [lfs]
111 > url=file:$TESTTMP/dummy-remote/
111 > url=file:$TESTTMP/dummy-remote/
112 > EOF
112 > EOF
113
113
114 Push to a local non-lfs repo with the extension enabled will add the
114 Push to a local non-lfs repo with the extension enabled will add the
115 lfs requirement
115 lfs requirement
116
116
117 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
117 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
118 [1]
118 [1]
119 $ hg push -v | egrep -v '^(uncompressed| )'
119 $ hg push -v | egrep -v '^(uncompressed| )'
120 pushing to $TESTTMP/server
120 pushing to $TESTTMP/server
121 searching for changes
121 searching for changes
122 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
122 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
123 2 changesets found
123 2 changesets found
124 adding changesets
124 adding changesets
125 adding manifests
125 adding manifests
126 adding file changes
126 adding file changes
127 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
127 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
128 added 2 changesets with 3 changes to 3 files
128 added 2 changesets with 3 changes to 3 files
129 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
129 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
130 lfs
130 lfs
131
131
132 # Unknown URL scheme
132 # Unknown URL scheme
133
133
134 $ hg push --config lfs.url=ftp://foobar
134 $ hg push --config lfs.url=ftp://foobar
135 abort: lfs: unknown url scheme: ftp
135 abort: lfs: unknown url scheme: ftp
136 [255]
136 [255]
137
137
138 $ cd ../
138 $ cd ../
139
139
140 # Initialize new client (not cloning) and setup extension
140 # Initialize new client (not cloning) and setup extension
141 $ hg init client2
141 $ hg init client2
142 $ cd client2
142 $ cd client2
143 $ cat >> .hg/hgrc <<EOF
143 $ cat >> .hg/hgrc <<EOF
144 > [paths]
144 > [paths]
145 > default = $TESTTMP/server
145 > default = $TESTTMP/server
146 > EOF
146 > EOF
147
147
148 # Pull from server
148 # Pull from server
149
149
150 Pulling a local lfs repo into a local non-lfs repo with the extension
150 Pulling a local lfs repo into a local non-lfs repo with the extension
151 enabled adds the lfs requirement
151 enabled adds the lfs requirement
152
152
153 $ hg debugrequires | grep lfs || true
153 $ hg debugrequires | grep lfs || true
154 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
154 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
155 lfs
155 lfs
156 $ hg pull default
156 $ hg pull default
157 pulling from $TESTTMP/server
157 pulling from $TESTTMP/server
158 requesting all changes
158 requesting all changes
159 adding changesets
159 adding changesets
160 adding manifests
160 adding manifests
161 adding file changes
161 adding file changes
162 added 2 changesets with 3 changes to 3 files
162 added 2 changesets with 3 changes to 3 files
163 new changesets 0ead593177f7:b88141481348
163 new changesets 0ead593177f7:b88141481348
164 (run 'hg update' to get a working copy)
164 (run 'hg update' to get a working copy)
165 $ hg debugrequires | grep lfs
165 $ hg debugrequires | grep lfs
166 lfs
166 lfs
167 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
167 $ hg debugrequires -R $TESTTMP/server/ | grep lfs
168 lfs
168 lfs
169
169
170 # Check the blobstore is not yet populated
170 # Check the blobstore is not yet populated
171 $ [ -d .hg/store/lfs/objects ]
171 $ [ -d .hg/store/lfs/objects ]
172 [1]
172 [1]
173
173
174 # Update to the last revision containing the large file
174 # Update to the last revision containing the large file
175 $ hg update
175 $ hg update
176 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
176 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
177
177
178 # Check the blobstore has been populated on update
178 # Check the blobstore has been populated on update
179 $ find .hg/store/lfs/objects | sort
179 $ find .hg/store/lfs/objects | sort
180 .hg/store/lfs/objects
180 .hg/store/lfs/objects
181 .hg/store/lfs/objects/f1
181 .hg/store/lfs/objects/f1
182 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
182 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
183
183
184 # Check the contents of the file are fetched from blobstore when requested
184 # Check the contents of the file are fetched from blobstore when requested
185 $ hg cat -r . largefile
185 $ hg cat -r . largefile
186 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
186 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
187
187
188 # Check the file has been copied in the working copy
188 # Check the file has been copied in the working copy
189 $ cat largefile
189 $ cat largefile
190 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
190 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
191
191
192 $ cd ..
192 $ cd ..
193
193
194 # Check rename, and switch between large and small files
194 # Check rename, and switch between large and small files
195
195
196 $ hg init repo3
196 $ hg init repo3
197 $ cd repo3
197 $ cd repo3
198 $ cat >> .hg/hgrc << EOF
198 $ cat >> .hg/hgrc << EOF
199 > [lfs]
199 > [lfs]
200 > track=size(">10B")
200 > track=size(">10B")
201 > EOF
201 > EOF
202
202
203 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
203 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
204 $ echo SHORTER > small
204 $ echo SHORTER > small
205 $ hg add . -q
205 $ hg add . -q
206 $ hg commit -m 'commit with lfs content'
206 $ hg commit -m 'commit with lfs content'
207
207
208 $ hg files -r . 'set:added()'
208 $ hg files -r . 'set:added()'
209 large
209 large
210 small
210 small
211 $ hg files -r . 'set:added() & lfs()'
211 $ hg files -r . 'set:added() & lfs()'
212 large
212 large
213
213
214 $ hg mv large l
214 $ hg mv large l
215 $ hg mv small s
215 $ hg mv small s
216 $ hg status 'set:removed()'
216 $ hg status 'set:removed()'
217 R large
217 R large
218 R small
218 R small
219 $ hg status 'set:removed() & lfs()'
219 $ hg status 'set:removed() & lfs()'
220 R large
220 R large
221 $ hg commit -m 'renames'
221 $ hg commit -m 'renames'
222
222
223 $ hg cat -r . l -T '{rawdata}\n'
223 $ hg cat -r . l -T '{rawdata}\n'
224 version https://git-lfs.github.com/spec/v1
224 version https://git-lfs.github.com/spec/v1
225 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
225 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
226 size 39
226 size 39
227 x-hg-copy large
227 x-hg-copy large
228 x-hg-copyrev 2c531e0992ff3107c511b53cb82a91b6436de8b2
228 x-hg-copyrev 2c531e0992ff3107c511b53cb82a91b6436de8b2
229 x-is-binary 0
229 x-is-binary 0
230
230
231
231
232 $ hg files -r . 'set:copied()'
232 $ hg files -r . 'set:copied()'
233 l
233 l
234 s
234 s
235 $ hg files -r . 'set:copied() & lfs()'
235 $ hg files -r . 'set:copied() & lfs()'
236 l
236 l
237 $ hg status --change . 'set:removed()'
237 $ hg status --change . 'set:removed()'
238 R large
238 R large
239 R small
239 R small
240 $ hg status --change . 'set:removed() & lfs()'
240 $ hg status --change . 'set:removed() & lfs()'
241 R large
241 R large
242
242
243 $ echo SHORT > l
243 $ echo SHORT > l
244 $ echo BECOME-LARGER-FROM-SHORTER > s
244 $ echo BECOME-LARGER-FROM-SHORTER > s
245 $ hg commit -m 'large to small, small to large'
245 $ hg commit -m 'large to small, small to large'
246
246
247 $ echo 1 >> l
247 $ echo 1 >> l
248 $ echo 2 >> s
248 $ echo 2 >> s
249 $ hg commit -m 'random modifications'
249 $ hg commit -m 'random modifications'
250
250
251 $ echo RESTORE-TO-BE-LARGE > l
251 $ echo RESTORE-TO-BE-LARGE > l
252 $ echo SHORTER > s
252 $ echo SHORTER > s
253 $ hg commit -m 'switch large and small again'
253 $ hg commit -m 'switch large and small again'
254
254
255 # Test lfs_files template
255 # Test lfs_files template
256
256
257 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
257 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
258 0 large
258 0 large
259 1 l, large
259 1 l, large
260 2 s
260 2 s
261 3 s
261 3 s
262 4 l
262 4 l
263
263
264 # Push and pull the above repo
264 # Push and pull the above repo
265
265
266 $ hg --cwd .. init repo4
266 $ hg --cwd .. init repo4
267 $ hg push ../repo4
267 $ hg push ../repo4
268 pushing to ../repo4
268 pushing to ../repo4
269 searching for changes
269 searching for changes
270 adding changesets
270 adding changesets
271 adding manifests
271 adding manifests
272 adding file changes
272 adding file changes
273 added 5 changesets with 10 changes to 4 files
273 added 5 changesets with 10 changes to 4 files
274
274
275 $ hg --cwd .. init repo5
275 $ hg --cwd .. init repo5
276 $ hg --cwd ../repo5 pull ../repo3
276 $ hg --cwd ../repo5 pull ../repo3
277 pulling from ../repo3
277 pulling from ../repo3
278 requesting all changes
278 requesting all changes
279 adding changesets
279 adding changesets
280 adding manifests
280 adding manifests
281 adding file changes
281 adding file changes
282 added 5 changesets with 10 changes to 4 files
282 added 5 changesets with 10 changes to 4 files
283 new changesets fd47a419c4f7:5adf850972b9
283 new changesets fd47a419c4f7:5adf850972b9
284 (run 'hg update' to get a working copy)
284 (run 'hg update' to get a working copy)
285
285
286 $ cd ..
286 $ cd ..
287
287
288 # Test clone
288 # Test clone
289
289
290 $ hg init repo6
290 $ hg init repo6
291 $ cd repo6
291 $ cd repo6
292 $ cat >> .hg/hgrc << EOF
292 $ cat >> .hg/hgrc << EOF
293 > [lfs]
293 > [lfs]
294 > track=size(">30B")
294 > track=size(">30B")
295 > EOF
295 > EOF
296
296
297 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
297 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
298 $ echo SMALL > small
298 $ echo SMALL > small
299 $ hg commit -Aqm 'create a lfs file' large small
299 $ hg commit -Aqm 'create a lfs file' large small
300 $ hg debuglfsupload -r 'all()' -v
300 $ hg debuglfsupload -r 'all()' -v
301 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
301 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
302
302
303 $ cd ..
303 $ cd ..
304
304
305 $ hg clone repo6 repo7
305 $ hg clone repo6 repo7
306 updating to branch default
306 updating to branch default
307 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
307 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 $ cd repo7
308 $ cd repo7
309 $ cat large
309 $ cat large
310 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
310 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
311 $ cat small
311 $ cat small
312 SMALL
312 SMALL
313
313
314 $ cd ..
314 $ cd ..
315
315
316 $ hg --config extensions.share= share repo7 sharedrepo
316 $ hg --config extensions.share= share repo7 sharedrepo
317 updating working directory
317 updating working directory
318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 $ hg debugrequires -R sharedrepo/ | grep lfs
319 $ hg debugrequires -R sharedrepo/ | grep lfs
320 lfs
320 lfs
321
321
322 # Test rename and status
322 # Test rename and status
323
323
324 $ hg init repo8
324 $ hg init repo8
325 $ cd repo8
325 $ cd repo8
326 $ cat >> .hg/hgrc << EOF
326 $ cat >> .hg/hgrc << EOF
327 > [lfs]
327 > [lfs]
328 > track=size(">10B")
328 > track=size(">10B")
329 > EOF
329 > EOF
330
330
331 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
331 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
332 $ echo SMALL > a2
332 $ echo SMALL > a2
333 $ hg commit -m a -A a1 a2
333 $ hg commit -m a -A a1 a2
334 $ hg status
334 $ hg status
335 $ hg mv a1 b1
335 $ hg mv a1 b1
336 $ hg mv a2 a1
336 $ hg mv a2 a1
337 $ hg mv b1 a2
337 $ hg mv b1 a2
338 $ hg commit -m b
338 $ hg commit -m b
339 $ hg status
339 $ hg status
340 >>> with open('a2', 'wb') as f:
340 >>> with open('a2', 'wb') as f:
341 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA') and None
341 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA') and None
342 >>> with open('a1', 'wb') as f:
342 >>> with open('a1', 'wb') as f:
343 ... f.write(b'\1\nMETA\n') and None
343 ... f.write(b'\1\nMETA\n') and None
344 $ hg commit -m meta
344 $ hg commit -m meta
345 $ hg status
345 $ hg status
346 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
346 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
347 2: | |
347 2: | |
348 1: a1 (a2)a2 (a1) | |
348 1: a1 (a2)a2 (a1) | |
349 0: | | a1 a2
349 0: | | a1 a2
350
350
351 $ for n in a1 a2; do
351 $ for n in a1 a2; do
352 > for r in 0 1 2; do
352 > for r in 0 1 2; do
353 > printf '\n%s @ %s\n' $n $r
353 > printf '\n%s @ %s\n' $n $r
354 > hg debugdata $n $r
354 > hg debugdata $n $r
355 > done
355 > done
356 > done
356 > done
357
357
358 a1 @ 0
358 a1 @ 0
359 version https://git-lfs.github.com/spec/v1
359 version https://git-lfs.github.com/spec/v1
360 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
360 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
361 size 29
361 size 29
362 x-is-binary 0
362 x-is-binary 0
363
363
364 a1 @ 1
364 a1 @ 1
365 \x01 (esc)
365 \x01 (esc)
366 copy: a2
366 copy: a2
367 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
367 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
368 \x01 (esc)
368 \x01 (esc)
369 SMALL
369 SMALL
370
370
371 a1 @ 2
371 a1 @ 2
372 \x01 (esc)
372 \x01 (esc)
373 \x01 (esc)
373 \x01 (esc)
374 \x01 (esc)
374 \x01 (esc)
375 META
375 META
376
376
377 a2 @ 0
377 a2 @ 0
378 SMALL
378 SMALL
379
379
380 a2 @ 1
380 a2 @ 1
381 version https://git-lfs.github.com/spec/v1
381 version https://git-lfs.github.com/spec/v1
382 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
382 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
383 size 29
383 size 29
384 x-hg-copy a1
384 x-hg-copy a1
385 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
385 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
386 x-is-binary 0
386 x-is-binary 0
387
387
388 a2 @ 2
388 a2 @ 2
389 version https://git-lfs.github.com/spec/v1
389 version https://git-lfs.github.com/spec/v1
390 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
390 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
391 size 32
391 size 32
392 x-is-binary 0
392 x-is-binary 0
393
393
394 # Verify commit hashes include rename metadata
394 # Verify commit hashes include rename metadata
395
395
396 $ hg log -T '{rev}:{node|short} {desc}\n'
396 $ hg log -T '{rev}:{node|short} {desc}\n'
397 2:0fae949de7fa meta
397 2:0fae949de7fa meta
398 1:9cd6bdffdac0 b
398 1:9cd6bdffdac0 b
399 0:7f96794915f7 a
399 0:7f96794915f7 a
400
400
401 $ cd ..
401 $ cd ..
402
402
403 # Test bundle
403 # Test bundle
404
404
405 $ hg init repo9
405 $ hg init repo9
406 $ cd repo9
406 $ cd repo9
407 $ cat >> .hg/hgrc << EOF
407 $ cat >> .hg/hgrc << EOF
408 > [lfs]
408 > [lfs]
409 > track=size(">10B")
409 > track=size(">10B")
410 > [diff]
410 > [diff]
411 > git=1
411 > git=1
412 > EOF
412 > EOF
413
413
414 $ for i in 0 single two three 4; do
414 $ for i in 0 single two three 4; do
415 > echo 'THIS-IS-LFS-'$i > a
415 > echo 'THIS-IS-LFS-'$i > a
416 > hg commit -m a-$i -A a
416 > hg commit -m a-$i -A a
417 > done
417 > done
418
418
419 $ hg update 2 -q
419 $ hg update 2 -q
420 $ echo 'THIS-IS-LFS-2-CHILD' > a
420 $ echo 'THIS-IS-LFS-2-CHILD' > a
421 $ hg commit -m branching -q
421 $ hg commit -m branching -q
422
422
423 $ hg bundle --base 1 bundle.hg -v
423 $ hg bundle --base 1 bundle.hg -v
424 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
424 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
425 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
425 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
426 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
426 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
427 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
427 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
428 4 changesets found
428 4 changesets found
429 uncompressed size of bundle content:
429 uncompressed size of bundle content:
430 * (changelog) (glob)
430 * (changelog) (glob)
431 * (manifests) (glob)
431 * (manifests) (glob)
432 * a (glob)
432 * a (glob)
433 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
433 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
434 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
434 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
435 5 branching
435 5 branching
436 diff --git a/a b/a
436 diff --git a/a b/a
437 --- a/a
437 --- a/a
438 +++ b/a
438 +++ b/a
439 @@ -1,1 +1,1 @@
439 @@ -1,1 +1,1 @@
440 -THIS-IS-LFS-two
440 -THIS-IS-LFS-two
441 +THIS-IS-LFS-2-CHILD
441 +THIS-IS-LFS-2-CHILD
442
442
443 4 a-4
443 4 a-4
444 diff --git a/a b/a
444 diff --git a/a b/a
445 --- a/a
445 --- a/a
446 +++ b/a
446 +++ b/a
447 @@ -1,1 +1,1 @@
447 @@ -1,1 +1,1 @@
448 -THIS-IS-LFS-three
448 -THIS-IS-LFS-three
449 +THIS-IS-LFS-4
449 +THIS-IS-LFS-4
450
450
451 3 a-three
451 3 a-three
452 diff --git a/a b/a
452 diff --git a/a b/a
453 --- a/a
453 --- a/a
454 +++ b/a
454 +++ b/a
455 @@ -1,1 +1,1 @@
455 @@ -1,1 +1,1 @@
456 -THIS-IS-LFS-two
456 -THIS-IS-LFS-two
457 +THIS-IS-LFS-three
457 +THIS-IS-LFS-three
458
458
459 2 a-two
459 2 a-two
460 diff --git a/a b/a
460 diff --git a/a b/a
461 --- a/a
461 --- a/a
462 +++ b/a
462 +++ b/a
463 @@ -1,1 +1,1 @@
463 @@ -1,1 +1,1 @@
464 -THIS-IS-LFS-single
464 -THIS-IS-LFS-single
465 +THIS-IS-LFS-two
465 +THIS-IS-LFS-two
466
466
467 1 a-single
467 1 a-single
468 diff --git a/a b/a
468 diff --git a/a b/a
469 --- a/a
469 --- a/a
470 +++ b/a
470 +++ b/a
471 @@ -1,1 +1,1 @@
471 @@ -1,1 +1,1 @@
472 -THIS-IS-LFS-0
472 -THIS-IS-LFS-0
473 +THIS-IS-LFS-single
473 +THIS-IS-LFS-single
474
474
475 0 a-0
475 0 a-0
476 diff --git a/a b/a
476 diff --git a/a b/a
477 new file mode 100644
477 new file mode 100644
478 --- /dev/null
478 --- /dev/null
479 +++ b/a
479 +++ b/a
480 @@ -0,0 +1,1 @@
480 @@ -0,0 +1,1 @@
481 +THIS-IS-LFS-0
481 +THIS-IS-LFS-0
482
482
483 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
483 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
484 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
484 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
485 5 branching
485 5 branching
486 diff --git a/a b/a
486 diff --git a/a b/a
487 --- a/a
487 --- a/a
488 +++ b/a
488 +++ b/a
489 @@ -1,1 +1,1 @@
489 @@ -1,1 +1,1 @@
490 -THIS-IS-LFS-two
490 -THIS-IS-LFS-two
491 +THIS-IS-LFS-2-CHILD
491 +THIS-IS-LFS-2-CHILD
492
492
493 4 a-4
493 4 a-4
494 diff --git a/a b/a
494 diff --git a/a b/a
495 --- a/a
495 --- a/a
496 +++ b/a
496 +++ b/a
497 @@ -1,1 +1,1 @@
497 @@ -1,1 +1,1 @@
498 -THIS-IS-LFS-three
498 -THIS-IS-LFS-three
499 +THIS-IS-LFS-4
499 +THIS-IS-LFS-4
500
500
501 3 a-three
501 3 a-three
502 diff --git a/a b/a
502 diff --git a/a b/a
503 --- a/a
503 --- a/a
504 +++ b/a
504 +++ b/a
505 @@ -1,1 +1,1 @@
505 @@ -1,1 +1,1 @@
506 -THIS-IS-LFS-two
506 -THIS-IS-LFS-two
507 +THIS-IS-LFS-three
507 +THIS-IS-LFS-three
508
508
509 2 a-two
509 2 a-two
510 diff --git a/a b/a
510 diff --git a/a b/a
511 --- a/a
511 --- a/a
512 +++ b/a
512 +++ b/a
513 @@ -1,1 +1,1 @@
513 @@ -1,1 +1,1 @@
514 -THIS-IS-LFS-single
514 -THIS-IS-LFS-single
515 +THIS-IS-LFS-two
515 +THIS-IS-LFS-two
516
516
517 1 a-single
517 1 a-single
518 diff --git a/a b/a
518 diff --git a/a b/a
519 --- a/a
519 --- a/a
520 +++ b/a
520 +++ b/a
521 @@ -1,1 +1,1 @@
521 @@ -1,1 +1,1 @@
522 -THIS-IS-LFS-0
522 -THIS-IS-LFS-0
523 +THIS-IS-LFS-single
523 +THIS-IS-LFS-single
524
524
525 0 a-0
525 0 a-0
526 diff --git a/a b/a
526 diff --git a/a b/a
527 new file mode 100644
527 new file mode 100644
528 --- /dev/null
528 --- /dev/null
529 +++ b/a
529 +++ b/a
530 @@ -0,0 +1,1 @@
530 @@ -0,0 +1,1 @@
531 +THIS-IS-LFS-0
531 +THIS-IS-LFS-0
532
532
533 $ cd ..
533 $ cd ..
534
534
535 # Test isbinary
535 # Test isbinary
536
536
537 $ hg init repo10
537 $ hg init repo10
538 $ cd repo10
538 $ cd repo10
539 $ cat >> .hg/hgrc << EOF
539 $ cat >> .hg/hgrc << EOF
540 > [extensions]
540 > [extensions]
541 > lfs=
541 > lfs=
542 > [lfs]
542 > [lfs]
543 > track=all()
543 > track=all()
544 > EOF
544 > EOF
545 $ "$PYTHON" <<'EOF'
545 $ "$PYTHON" <<'EOF'
546 > def write(path, content):
546 > def write(path, content):
547 > with open(path, 'wb') as f:
547 > with open(path, 'wb') as f:
548 > f.write(content)
548 > f.write(content)
549 > write('a', b'\0\0')
549 > write('a', b'\0\0')
550 > write('b', b'\1\n')
550 > write('b', b'\1\n')
551 > write('c', b'\1\n\0')
551 > write('c', b'\1\n\0')
552 > write('d', b'xx')
552 > write('d', b'xx')
553 > EOF
553 > EOF
554 $ hg add a b c d
554 $ hg add a b c d
555 $ hg diff --stat
555 $ hg diff --stat
556 a | Bin
556 a | Bin
557 b | 1 +
557 b | 1 +
558 c | Bin
558 c | Bin
559 d | 1 +
559 d | 1 +
560 4 files changed, 2 insertions(+), 0 deletions(-)
560 4 files changed, 2 insertions(+), 0 deletions(-)
561 $ hg commit -m binarytest
561 $ hg commit -m binarytest
562 $ cat > $TESTTMP/dumpbinary.py << EOF
562 $ cat > $TESTTMP/dumpbinary.py << EOF
563 > from mercurial.utils import (
563 > from mercurial.utils import (
564 > stringutil,
564 > stringutil,
565 > )
565 > )
566 > def reposetup(ui, repo):
566 > def reposetup(ui, repo):
567 > for n in (b'a', b'b', b'c', b'd'):
567 > for n in (b'a', b'b', b'c', b'd'):
568 > ui.write((b'%s: binary=%s\n')
568 > ui.write((b'%s: binary=%s\n')
569 > % (n, stringutil.pprint(repo[b'.'][n].isbinary())))
569 > % (n, stringutil.pprint(repo[b'.'][n].isbinary())))
570 > EOF
570 > EOF
571 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
571 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
572 a: binary=True
572 a: binary=True
573 b: binary=False
573 b: binary=False
574 c: binary=True
574 c: binary=True
575 d: binary=False
575 d: binary=False
576 b55353847f02 tip
576 b55353847f02 tip
577
577
578 Binary blobs don't need to be present to be skipped in filesets. (And their
578 Binary blobs don't need to be present to be skipped in filesets. (And their
579 absence doesn't cause an abort.)
579 absence doesn't cause an abort.)
580
580
581 $ rm .hg/store/lfs/objects/96/a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7
581 $ rm .hg/store/lfs/objects/96/a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7
582 $ rm .hg/store/lfs/objects/92/f76135a4baf4faccb8586a60faf830c2bdfce147cefa188aaf4b790bd01b7e
582 $ rm .hg/store/lfs/objects/92/f76135a4baf4faccb8586a60faf830c2bdfce147cefa188aaf4b790bd01b7e
583
583
584 $ hg files --debug -r . 'set:eol("unix")' --config 'experimental.lfs.disableusercache=True'
584 $ hg files --debug -r . 'set:eol("unix")' --config 'experimental.lfs.disableusercache=True'
585 lfs: found c04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b7adeeafb5474c4adae9faa80 in the local lfs store
585 lfs: found c04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b7adeeafb5474c4adae9faa80 in the local lfs store
586 2 b
586 2 b
587 lfs: found 5dde896887f6754c9b15bfe3a441ae4806df2fde94001311e08bf110622e0bbe in the local lfs store
587 lfs: found 5dde896887f6754c9b15bfe3a441ae4806df2fde94001311e08bf110622e0bbe in the local lfs store
588
588
589 $ hg files --debug -r . 'set:binary()' --config 'experimental.lfs.disableusercache=True'
589 $ hg files --debug -r . 'set:binary()' --config 'experimental.lfs.disableusercache=True'
590 2 a
590 2 a
591 3 c
591 3 c
592
592
593 $ cd ..
593 $ cd ..
594
594
595 # Test fctx.cmp fastpath - diff without LFS blobs
595 # Test fctx.cmp fastpath - diff without LFS blobs
596
596
597 $ hg init repo12
597 $ hg init repo12
598 $ cd repo12
598 $ cd repo12
599 $ cat >> .hg/hgrc <<EOF
599 $ cat >> .hg/hgrc <<EOF
600 > [lfs]
600 > [lfs]
601 > threshold=1
601 > threshold=1
602 > EOF
602 > EOF
603 $ cat > ../patch.diff <<EOF
603 $ cat > ../patch.diff <<EOF
604 > # HG changeset patch
604 > # HG changeset patch
605 > 2
605 > 2
606 >
606 >
607 > diff --git a/a b/a
607 > diff --git a/a b/a
608 > old mode 100644
608 > old mode 100644
609 > new mode 100755
609 > new mode 100755
610 > EOF
610 > EOF
611
611
612 $ for i in 1 2 3; do
612 $ for i in 1 2 3; do
613 > cp ../repo10/a a
613 > cp ../repo10/a a
614 > if [ $i = 3 ]; then
614 > if [ $i = 3 ]; then
615 > # make a content-only change
615 > # make a content-only change
616 > hg import -q --bypass ../patch.diff
616 > hg import -q --bypass ../patch.diff
617 > hg update -q
617 > hg update -q
618 > rm ../patch.diff
618 > rm ../patch.diff
619 > else
619 > else
620 > echo $i >> a
620 > echo $i >> a
621 > hg commit -m $i -A a
621 > hg commit -m $i -A a
622 > fi
622 > fi
623 > done
623 > done
624 $ [ -d .hg/store/lfs/objects ]
624 $ [ -d .hg/store/lfs/objects ]
625
625
626 $ cd ..
626 $ cd ..
627
627
628 $ hg clone repo12 repo13 --noupdate
628 $ hg clone repo12 repo13 --noupdate
629 $ cd repo13
629 $ cd repo13
630 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
630 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
631 2
631 2
632 diff --git a/a b/a
632 diff --git a/a b/a
633 old mode 100644
633 old mode 100644
634 new mode 100755
634 new mode 100755
635
635
636 2
636 2
637 diff --git a/a b/a
637 diff --git a/a b/a
638 Binary file a has changed
638 Binary file a has changed
639
639
640 1
640 1
641 diff --git a/a b/a
641 diff --git a/a b/a
642 new file mode 100644
642 new file mode 100644
643 Binary file a has changed
643 Binary file a has changed
644
644
645 $ [ -d .hg/store/lfs/objects ]
645 $ [ -d .hg/store/lfs/objects ]
646 [1]
646 [1]
647
647
648 $ cd ..
648 $ cd ..
649
649
650 # Test filter
650 # Test filter
651
651
652 $ hg init repo11
652 $ hg init repo11
653 $ cd repo11
653 $ cd repo11
654 $ cat >> .hg/hgrc << EOF
654 $ cat >> .hg/hgrc << EOF
655 > [lfs]
655 > [lfs]
656 > track=(**.a & size(">5B")) | (**.b & !size(">5B"))
656 > track=(**.a & size(">5B")) | (**.b & !size(">5B"))
657 > | (**.c & "path:d" & !"path:d/c.c") | size(">10B")
657 > | (**.c & "path:d" & !"path:d/c.c") | size(">10B")
658 > EOF
658 > EOF
659
659
660 $ mkdir a
660 $ mkdir a
661 $ echo aaaaaa > a/1.a
661 $ echo aaaaaa > a/1.a
662 $ echo a > a/2.a
662 $ echo a > a/2.a
663 $ echo aaaaaa > 1.b
663 $ echo aaaaaa > 1.b
664 $ echo a > 2.b
664 $ echo a > 2.b
665 $ echo a > 1.c
665 $ echo a > 1.c
666 $ mkdir d
666 $ mkdir d
667 $ echo a > d/c.c
667 $ echo a > d/c.c
668 $ echo a > d/d.c
668 $ echo a > d/d.c
669 $ echo aaaaaaaaaaaa > x
669 $ echo aaaaaaaaaaaa > x
670 $ hg add . -q
670 $ hg add . -q
671 $ hg commit -m files
671 $ hg commit -m files
672
672
673 $ for p in a/1.a a/2.a 1.b 2.b 1.c d/c.c d/d.c x; do
673 $ for p in a/1.a a/2.a 1.b 2.b 1.c d/c.c d/d.c x; do
674 > if hg debugdata $p 0 2>&1 | grep git-lfs >/dev/null; then
674 > if hg debugdata $p 0 2>&1 | grep git-lfs >/dev/null; then
675 > echo "${p}: is lfs"
675 > echo "${p}: is lfs"
676 > else
676 > else
677 > echo "${p}: not lfs"
677 > echo "${p}: not lfs"
678 > fi
678 > fi
679 > done
679 > done
680 a/1.a: is lfs
680 a/1.a: is lfs
681 a/2.a: not lfs
681 a/2.a: not lfs
682 1.b: not lfs
682 1.b: not lfs
683 2.b: is lfs
683 2.b: is lfs
684 1.c: not lfs
684 1.c: not lfs
685 d/c.c: not lfs
685 d/c.c: not lfs
686 d/d.c: is lfs
686 d/d.c: is lfs
687 x: is lfs
687 x: is lfs
688
688
689 $ cd ..
689 $ cd ..
690
690
691 # Verify the repos
691 # Verify the repos
692
692
693 $ cat > $TESTTMP/dumpflog.py << EOF
693 $ cat > $TESTTMP/dumpflog.py << EOF
694 > # print raw revision sizes, flags, and hashes for certain files
694 > # print raw revision sizes, flags, and hashes for certain files
695 > import hashlib
695 > import hashlib
696 > from mercurial.node import short
696 > from mercurial.node import short
697 > from mercurial import (
697 > from mercurial import (
698 > pycompat,
698 > pycompat,
699 > revlog,
699 > revlog,
700 > )
700 > )
701 > from mercurial.utils import (
701 > from mercurial.utils import (
702 > procutil,
702 > procutil,
703 > stringutil,
703 > stringutil,
704 > )
704 > )
705 > def hash(rawtext):
705 > def hash(rawtext):
706 > h = hashlib.sha512()
706 > h = hashlib.sha512()
707 > h.update(rawtext)
707 > h.update(rawtext)
708 > return pycompat.sysbytes(h.hexdigest()[:4])
708 > return pycompat.sysbytes(h.hexdigest()[:4])
709 > def reposetup(ui, repo):
709 > def reposetup(ui, repo):
710 > # these 2 files are interesting
710 > # these 2 files are interesting
711 > for name in [b'l', b's']:
711 > for name in [b'l', b's']:
712 > fl = repo.file(name)
712 > fl = repo.file(name)
713 > if len(fl) == 0:
713 > if len(fl) == 0:
714 > continue
714 > continue
715 > sizes = [fl._revlog.rawsize(i) for i in fl]
715 > sizes = [fl._revlog.rawsize(i) for i in fl]
716 > texts = [fl.rawdata(i) for i in fl]
716 > texts = [fl.rawdata(i) for i in fl]
717 > flags = [int(fl._revlog.flags(i)) for i in fl]
717 > flags = [int(fl._revlog.flags(i)) for i in fl]
718 > hashes = [hash(t) for t in texts]
718 > hashes = [hash(t) for t in texts]
719 > procutil.stdout.write(b' %s: rawsizes=%r flags=%r hashes=%s\n'
719 > procutil.stdout.write(b' %s: rawsizes=%r flags=%r hashes=%s\n'
720 > % (name, sizes, flags, stringutil.pprint(hashes)))
720 > % (name, sizes, flags, stringutil.pprint(hashes)))
721 > EOF
721 > EOF
722
722
723 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
723 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
724 > repo10; do
724 > repo10; do
725 > echo 'repo:' $i
725 > echo 'repo:' $i
726 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
726 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
727 > done
727 > done
728 repo: client
728 repo: client
729 repo: client2
729 repo: client2
730 repo: server
730 repo: server
731 repo: repo3
731 repo: repo3
732 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
732 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
733 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
733 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
734 repo: repo4
734 repo: repo4
735 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
735 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
736 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
736 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
737 repo: repo5
737 repo: repo5
738 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
738 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
739 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
739 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
740 repo: repo6
740 repo: repo6
741 repo: repo7
741 repo: repo7
742 repo: repo8
742 repo: repo8
743 repo: repo9
743 repo: repo9
744 repo: repo10
744 repo: repo10
745
745
746 repo13 doesn't have any cached lfs files and its source never pushed its
746 repo13 doesn't have any cached lfs files and its source never pushed its
747 files. Therefore, the files don't exist in the remote store. Use the files in
747 files. Therefore, the files don't exist in the remote store. Use the files in
748 the user cache.
748 the user cache.
749
749
750 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
750 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
751 [1]
751 [1]
752
752
753 $ hg --config extensions.share= share repo13 repo14
753 $ hg --config extensions.share= share repo13 repo14
754 updating working directory
754 updating working directory
755 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
755 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
756 $ hg -R repo14 -q verify
756 $ hg -R repo14 -q verify
757
757
758 $ hg clone repo13 repo15
758 $ hg clone repo13 repo15
759 updating to branch default
759 updating to branch default
760 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
760 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
761 $ hg -R repo15 -q verify
761 $ hg -R repo15 -q verify
762
762
763 If the source repo doesn't have the blob (maybe it was pulled or cloned with
763 If the source repo doesn't have the blob (maybe it was pulled or cloned with
764 --noupdate), the blob is still accessible via the global cache to send to the
764 --noupdate), the blob is still accessible via the global cache to send to the
765 remote store.
765 remote store.
766
766
767 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
767 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
768 $ hg init repo16
768 $ hg init repo16
769 $ hg -R repo15 push repo16
769 $ hg -R repo15 push repo16
770 pushing to repo16
770 pushing to repo16
771 searching for changes
771 searching for changes
772 adding changesets
772 adding changesets
773 adding manifests
773 adding manifests
774 adding file changes
774 adding file changes
775 added 3 changesets with 2 changes to 1 files
775 added 3 changesets with 2 changes to 1 files
776 $ hg -R repo15 -q verify
776 $ hg -R repo15 -q verify
777
777
778 Test damaged file scenarios. (This also damages the usercache because of the
778 Test damaged file scenarios. (This also damages the usercache because of the
779 hardlinks.)
779 hardlinks.)
780
780
781 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
781 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
782
782
783 Repo with damaged lfs objects in any revision will fail verification.
783 Repo with damaged lfs objects in any revision will fail verification.
784
784
785 $ hg -R repo5 verify
785 $ hg -R repo5 verify
786 checking changesets
786 checking changesets
787 checking manifests
787 checking manifests
788 crosschecking files in changesets and manifests
788 crosschecking files in changesets and manifests
789 checking files
789 checking files
790 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
790 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
791 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
791 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
792 not checking dirstate because of previous errors
792 checked 5 changesets with 10 changes to 4 files
793 checked 5 changesets with 10 changes to 4 files
793 2 integrity errors encountered!
794 2 integrity errors encountered!
794 (first damaged changeset appears to be 0)
795 (first damaged changeset appears to be 0)
795 [1]
796 [1]
796
797
797 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
798 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
798 the update destination. Those objects won't be added to the new repo's store
799 the update destination. Those objects won't be added to the new repo's store
799 because they aren't accessed.
800 because they aren't accessed.
800
801
801 $ hg clone -v repo5 fromcorrupt
802 $ hg clone -v repo5 fromcorrupt
802 updating to branch default
803 updating to branch default
803 resolving manifests
804 resolving manifests
804 getting l
805 getting l
805 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
806 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
806 getting s
807 getting s
807 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
808 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
808 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
809 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
809 [1]
810 [1]
810
811
811 Verify will not try to download lfs blobs, if told not to process lfs content.
812 Verify will not try to download lfs blobs, if told not to process lfs content.
812 The extension makes sure that the filelog.renamed() path is taken on a missing
813 The extension makes sure that the filelog.renamed() path is taken on a missing
813 blob, and the output shows that it isn't fetched.
814 blob, and the output shows that it isn't fetched.
814
815
815 $ cat > $TESTTMP/lfsrename.py <<EOF
816 $ cat > $TESTTMP/lfsrename.py <<EOF
816 > import sys
817 > import sys
817 >
818 >
818 > from mercurial import (
819 > from mercurial import (
819 > exthelper,
820 > exthelper,
820 > pycompat,
821 > pycompat,
821 > )
822 > )
822 >
823 >
823 > from hgext.lfs import (
824 > from hgext.lfs import (
824 > pointer,
825 > pointer,
825 > wrapper,
826 > wrapper,
826 > )
827 > )
827 >
828 >
828 > eh = exthelper.exthelper()
829 > eh = exthelper.exthelper()
829 > uisetup = eh.finaluisetup
830 > uisetup = eh.finaluisetup
830 >
831 >
831 > @eh.wrapfunction(wrapper, b'filelogrenamed')
832 > @eh.wrapfunction(wrapper, b'filelogrenamed')
832 > def filelogrenamed(orig, orig1, self, node):
833 > def filelogrenamed(orig, orig1, self, node):
833 > ret = orig(orig1, self, node)
834 > ret = orig(orig1, self, node)
834 > if wrapper._islfs(self._revlog, node) and ret:
835 > if wrapper._islfs(self._revlog, node) and ret:
835 > rawtext = self._revlog.rawdata(node)
836 > rawtext = self._revlog.rawdata(node)
836 > metadata = pointer.deserialize(rawtext)
837 > metadata = pointer.deserialize(rawtext)
837 > print('lfs blob %s renamed %s -> %s'
838 > print('lfs blob %s renamed %s -> %s'
838 > % (pycompat.sysstr(metadata[b'oid']),
839 > % (pycompat.sysstr(metadata[b'oid']),
839 > pycompat.sysstr(ret[0]),
840 > pycompat.sysstr(ret[0]),
840 > pycompat.fsdecode(self._revlog.filename)))
841 > pycompat.fsdecode(self._revlog.filename)))
841 > sys.stdout.flush()
842 > sys.stdout.flush()
842 > return ret
843 > return ret
843 > EOF
844 > EOF
844
845
845 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v --no-lfs \
846 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v --no-lfs \
846 > --config extensions.x=$TESTTMP/lfsrename.py
847 > --config extensions.x=$TESTTMP/lfsrename.py
847 repository uses revlog format 1
848 repository uses revlog format 1
848 checking changesets
849 checking changesets
849 checking manifests
850 checking manifests
850 crosschecking files in changesets and manifests
851 crosschecking files in changesets and manifests
851 checking files
852 checking files
852 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
853 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
853 lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l
854 lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l
855 checking dirstate
854 checked 5 changesets with 10 changes to 4 files
856 checked 5 changesets with 10 changes to 4 files
855
857
856 Verify will not try to download lfs blobs, if told not to by the config option
858 Verify will not try to download lfs blobs, if told not to by the config option
857
859
858 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v \
860 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v \
859 > --config verify.skipflags=8192 \
861 > --config verify.skipflags=8192 \
860 > --config extensions.x=$TESTTMP/lfsrename.py
862 > --config extensions.x=$TESTTMP/lfsrename.py
861 repository uses revlog format 1
863 repository uses revlog format 1
862 checking changesets
864 checking changesets
863 checking manifests
865 checking manifests
864 crosschecking files in changesets and manifests
866 crosschecking files in changesets and manifests
865 checking files
867 checking files
866 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
868 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
867 lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l
869 lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l
870 checking dirstate
868 checked 5 changesets with 10 changes to 4 files
871 checked 5 changesets with 10 changes to 4 files
869
872
870 Verify will copy/link all lfs objects into the local store that aren't already
873 Verify will copy/link all lfs objects into the local store that aren't already
871 present. Bypass the corrupted usercache to show that verify works when fed by
874 present. Bypass the corrupted usercache to show that verify works when fed by
872 the (uncorrupted) remote store.
875 the (uncorrupted) remote store.
873
876
874 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
877 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
875 repository uses revlog format 1
878 repository uses revlog format 1
876 checking changesets
879 checking changesets
877 checking manifests
880 checking manifests
878 crosschecking files in changesets and manifests
881 crosschecking files in changesets and manifests
879 checking files
882 checking files
880 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
883 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
881 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
884 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
882 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
885 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
883 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
886 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
884 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
887 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
885 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
888 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
886 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
889 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
887 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
890 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
891 checking dirstate
888 checked 5 changesets with 10 changes to 4 files
892 checked 5 changesets with 10 changes to 4 files
889
893
890 Verify will not copy/link a corrupted file from the usercache into the local
894 Verify will not copy/link a corrupted file from the usercache into the local
891 store, and poison it. (The verify with a good remote now works.)
895 store, and poison it. (The verify with a good remote now works.)
892
896
893 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
897 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
894 $ hg -R fromcorrupt verify -v
898 $ hg -R fromcorrupt verify -v
895 repository uses revlog format 1
899 repository uses revlog format 1
896 checking changesets
900 checking changesets
897 checking manifests
901 checking manifests
898 crosschecking files in changesets and manifests
902 crosschecking files in changesets and manifests
899 checking files
903 checking files
900 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
904 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
901 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
905 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
902 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
906 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
903 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
907 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
904 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
908 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
909 not checking dirstate because of previous errors
905 checked 5 changesets with 10 changes to 4 files
910 checked 5 changesets with 10 changes to 4 files
906 2 integrity errors encountered!
911 2 integrity errors encountered!
907 (first damaged changeset appears to be 0)
912 (first damaged changeset appears to be 0)
908 [1]
913 [1]
909 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
914 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
910 repository uses revlog format 1
915 repository uses revlog format 1
911 checking changesets
916 checking changesets
912 checking manifests
917 checking manifests
913 crosschecking files in changesets and manifests
918 crosschecking files in changesets and manifests
914 checking files
919 checking files
915 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
920 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
916 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
921 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
917 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
922 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
918 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
923 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
919 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
924 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
925 checking dirstate
920 checked 5 changesets with 10 changes to 4 files
926 checked 5 changesets with 10 changes to 4 files
921
927
922 Damaging a file required by the update destination fails the update.
928 Damaging a file required by the update destination fails the update.
923
929
924 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
930 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
925 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
931 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
926 updating to branch default
932 updating to branch default
927 resolving manifests
933 resolving manifests
928 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
934 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
929 [255]
935 [255]
930
936
931 A corrupted lfs blob is not transferred from a file://remotestore to the
937 A corrupted lfs blob is not transferred from a file://remotestore to the
932 usercache or local store.
938 usercache or local store.
933
939
934 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
940 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
935 [1]
941 [1]
936 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
942 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
937 [1]
943 [1]
938
944
939 $ hg -R fromcorrupt2 verify
945 $ hg -R fromcorrupt2 verify
940 checking changesets
946 checking changesets
941 checking manifests
947 checking manifests
942 crosschecking files in changesets and manifests
948 crosschecking files in changesets and manifests
943 checking files
949 checking files
944 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
950 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
945 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
951 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
952 not checking dirstate because of previous errors
946 checked 5 changesets with 10 changes to 4 files
953 checked 5 changesets with 10 changes to 4 files
947 2 integrity errors encountered!
954 2 integrity errors encountered!
948 (first damaged changeset appears to be 0)
955 (first damaged changeset appears to be 0)
949 [1]
956 [1]
950
957
951 Corrupt local files are not sent upstream. (The alternate dummy remote
958 Corrupt local files are not sent upstream. (The alternate dummy remote
952 avoids the corrupt lfs object in the original remote.)
959 avoids the corrupt lfs object in the original remote.)
953
960
954 $ mkdir $TESTTMP/dummy-remote2
961 $ mkdir $TESTTMP/dummy-remote2
955 $ hg init dest
962 $ hg init dest
956 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
963 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
957 pushing to dest
964 pushing to dest
958 searching for changes
965 searching for changes
959 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
966 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
960 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
967 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
961 (run hg verify)
968 (run hg verify)
962 [255]
969 [255]
963
970
964 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
971 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
965 repository uses revlog format 1
972 repository uses revlog format 1
966 checking changesets
973 checking changesets
967 checking manifests
974 checking manifests
968 crosschecking files in changesets and manifests
975 crosschecking files in changesets and manifests
969 checking files
976 checking files
970 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
977 l@1: unpacking 46a2f24864bc: integrity check failed on l:0
971 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
978 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
972 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
979 large@0: unpacking 2c531e0992ff: integrity check failed on large:0
973 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
980 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
974 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
981 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
982 not checking dirstate because of previous errors
975 checked 5 changesets with 10 changes to 4 files
983 checked 5 changesets with 10 changes to 4 files
976 2 integrity errors encountered!
984 2 integrity errors encountered!
977 (first damaged changeset appears to be 0)
985 (first damaged changeset appears to be 0)
978 [1]
986 [1]
979
987
980 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
988 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
981 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
989 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
982 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
990 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
983 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
991 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
984 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
992 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
985 [1]
993 [1]
986
994
987 Accessing a corrupt file will complain
995 Accessing a corrupt file will complain
988
996
989 $ hg --cwd fromcorrupt2 cat -r 0 large
997 $ hg --cwd fromcorrupt2 cat -r 0 large
990 abort: integrity check failed on large:0
998 abort: integrity check failed on large:0
991 [50]
999 [50]
992
1000
993 lfs -> normal -> lfs round trip conversions are possible. The 'none()'
1001 lfs -> normal -> lfs round trip conversions are possible. The 'none()'
994 predicate on the command line will override whatever is configured globally and
1002 predicate on the command line will override whatever is configured globally and
995 locally, and ensures everything converts to a regular file. For lfs -> normal,
1003 locally, and ensures everything converts to a regular file. For lfs -> normal,
996 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
1004 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
997
1005
998 $ hg --config extensions.convert= --config 'lfs.track=none()' \
1006 $ hg --config extensions.convert= --config 'lfs.track=none()' \
999 > convert repo8 convert_normal
1007 > convert repo8 convert_normal
1000 initializing destination convert_normal repository
1008 initializing destination convert_normal repository
1001 scanning source...
1009 scanning source...
1002 sorting...
1010 sorting...
1003 converting...
1011 converting...
1004 2 a
1012 2 a
1005 1 b
1013 1 b
1006 0 meta
1014 0 meta
1007 $ hg debugrequires -R convert_normal | grep 'lfs'
1015 $ hg debugrequires -R convert_normal | grep 'lfs'
1008 [1]
1016 [1]
1009 $ hg --cwd convert_normal cat a1 -r 0 -T '{rawdata}'
1017 $ hg --cwd convert_normal cat a1 -r 0 -T '{rawdata}'
1010 THIS-IS-LFS-BECAUSE-10-BYTES
1018 THIS-IS-LFS-BECAUSE-10-BYTES
1011
1019
1012 $ hg --config extensions.convert= --config lfs.threshold=10B \
1020 $ hg --config extensions.convert= --config lfs.threshold=10B \
1013 > convert convert_normal convert_lfs
1021 > convert convert_normal convert_lfs
1014 initializing destination convert_lfs repository
1022 initializing destination convert_lfs repository
1015 scanning source...
1023 scanning source...
1016 sorting...
1024 sorting...
1017 converting...
1025 converting...
1018 2 a
1026 2 a
1019 1 b
1027 1 b
1020 0 meta
1028 0 meta
1021
1029
1022 $ hg --cwd convert_lfs cat -r 0 a1 -T '{rawdata}'
1030 $ hg --cwd convert_lfs cat -r 0 a1 -T '{rawdata}'
1023 version https://git-lfs.github.com/spec/v1
1031 version https://git-lfs.github.com/spec/v1
1024 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1032 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1025 size 29
1033 size 29
1026 x-is-binary 0
1034 x-is-binary 0
1027 $ hg --cwd convert_lfs debugdata a1 0
1035 $ hg --cwd convert_lfs debugdata a1 0
1028 version https://git-lfs.github.com/spec/v1
1036 version https://git-lfs.github.com/spec/v1
1029 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1037 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1030 size 29
1038 size 29
1031 x-is-binary 0
1039 x-is-binary 0
1032 $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfspointer % '{key}={value}\n'}'}"
1040 $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfspointer % '{key}={value}\n'}'}"
1033 version=https://git-lfs.github.com/spec/v1
1041 version=https://git-lfs.github.com/spec/v1
1034 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1042 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1035 size=29
1043 size=29
1036 x-is-binary=0
1044 x-is-binary=0
1037 $ hg --cwd convert_lfs log -r 0 \
1045 $ hg --cwd convert_lfs log -r 0 \
1038 > -T '{lfs_files % "{get(lfspointer, "oid")}\n"}{lfs_files % "{lfspointer.oid}\n"}'
1046 > -T '{lfs_files % "{get(lfspointer, "oid")}\n"}{lfs_files % "{lfspointer.oid}\n"}'
1039 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1047 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1040 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1048 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1041 $ hg --cwd convert_lfs log -r 0 -T '{lfs_files % "{lfspointer}\n"}'
1049 $ hg --cwd convert_lfs log -r 0 -T '{lfs_files % "{lfspointer}\n"}'
1042 version=https://git-lfs.github.com/spec/v1 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024 size=29 x-is-binary=0
1050 version=https://git-lfs.github.com/spec/v1 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024 size=29 x-is-binary=0
1043 $ hg --cwd convert_lfs \
1051 $ hg --cwd convert_lfs \
1044 > log -r 'all()' -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}'
1052 > log -r 'all()' -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}'
1045 0: a1: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1053 0: a1: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1046 1: a2: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1054 1: a2: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
1047 2: a2: 876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
1055 2: a2: 876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
1048
1056
1049 $ hg debugrequires -R convert_lfs | grep 'lfs'
1057 $ hg debugrequires -R convert_lfs | grep 'lfs'
1050 lfs
1058 lfs
1051
1059
1052 The hashes in all stages of the conversion are unchanged.
1060 The hashes in all stages of the conversion are unchanged.
1053
1061
1054 $ hg -R repo8 log -T '{node|short}\n'
1062 $ hg -R repo8 log -T '{node|short}\n'
1055 0fae949de7fa
1063 0fae949de7fa
1056 9cd6bdffdac0
1064 9cd6bdffdac0
1057 7f96794915f7
1065 7f96794915f7
1058 $ hg -R convert_normal log -T '{node|short}\n'
1066 $ hg -R convert_normal log -T '{node|short}\n'
1059 0fae949de7fa
1067 0fae949de7fa
1060 9cd6bdffdac0
1068 9cd6bdffdac0
1061 7f96794915f7
1069 7f96794915f7
1062 $ hg -R convert_lfs log -T '{node|short}\n'
1070 $ hg -R convert_lfs log -T '{node|short}\n'
1063 0fae949de7fa
1071 0fae949de7fa
1064 9cd6bdffdac0
1072 9cd6bdffdac0
1065 7f96794915f7
1073 7f96794915f7
1066
1074
1067 This convert is trickier, because it contains deleted files (via `hg mv`)
1075 This convert is trickier, because it contains deleted files (via `hg mv`)
1068
1076
1069 $ hg --config extensions.convert= --config lfs.threshold=1000M \
1077 $ hg --config extensions.convert= --config lfs.threshold=1000M \
1070 > convert repo3 convert_normal2
1078 > convert repo3 convert_normal2
1071 initializing destination convert_normal2 repository
1079 initializing destination convert_normal2 repository
1072 scanning source...
1080 scanning source...
1073 sorting...
1081 sorting...
1074 converting...
1082 converting...
1075 4 commit with lfs content
1083 4 commit with lfs content
1076 3 renames
1084 3 renames
1077 2 large to small, small to large
1085 2 large to small, small to large
1078 1 random modifications
1086 1 random modifications
1079 0 switch large and small again
1087 0 switch large and small again
1080 $ hg debugrequires -R convert_normal2 | grep 'lfs'
1088 $ hg debugrequires -R convert_normal2 | grep 'lfs'
1081 [1]
1089 [1]
1082 $ hg --cwd convert_normal2 debugdata large 0
1090 $ hg --cwd convert_normal2 debugdata large 0
1083 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
1091 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
1084
1092
1085 $ hg --config extensions.convert= --config lfs.threshold=10B \
1093 $ hg --config extensions.convert= --config lfs.threshold=10B \
1086 > convert convert_normal2 convert_lfs2
1094 > convert convert_normal2 convert_lfs2
1087 initializing destination convert_lfs2 repository
1095 initializing destination convert_lfs2 repository
1088 scanning source...
1096 scanning source...
1089 sorting...
1097 sorting...
1090 converting...
1098 converting...
1091 4 commit with lfs content
1099 4 commit with lfs content
1092 3 renames
1100 3 renames
1093 2 large to small, small to large
1101 2 large to small, small to large
1094 1 random modifications
1102 1 random modifications
1095 0 switch large and small again
1103 0 switch large and small again
1096 $ hg debugrequires -R convert_lfs2 | grep 'lfs'
1104 $ hg debugrequires -R convert_lfs2 | grep 'lfs'
1097 lfs
1105 lfs
1098 $ hg --cwd convert_lfs2 debugdata large 0
1106 $ hg --cwd convert_lfs2 debugdata large 0
1099 version https://git-lfs.github.com/spec/v1
1107 version https://git-lfs.github.com/spec/v1
1100 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
1108 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
1101 size 39
1109 size 39
1102 x-is-binary 0
1110 x-is-binary 0
1103
1111
1104 Committing deleted files works:
1112 Committing deleted files works:
1105
1113
1106 $ hg init $TESTTMP/repo-del
1114 $ hg init $TESTTMP/repo-del
1107 $ cd $TESTTMP/repo-del
1115 $ cd $TESTTMP/repo-del
1108 $ echo 1 > A
1116 $ echo 1 > A
1109 $ hg commit -m 'add A' -A A
1117 $ hg commit -m 'add A' -A A
1110 $ hg rm A
1118 $ hg rm A
1111 $ hg commit -m 'rm A'
1119 $ hg commit -m 'rm A'
1112
1120
1113 Bad .hglfs files will block the commit with a useful message
1121 Bad .hglfs files will block the commit with a useful message
1114
1122
1115 $ cat > .hglfs << EOF
1123 $ cat > .hglfs << EOF
1116 > [track]
1124 > [track]
1117 > **.test = size(">5B")
1125 > **.test = size(">5B")
1118 > bad file ... no commit
1126 > bad file ... no commit
1119 > EOF
1127 > EOF
1120
1128
1121 $ echo x > file.txt
1129 $ echo x > file.txt
1122 $ hg ci -Aqm 'should fail'
1130 $ hg ci -Aqm 'should fail'
1123 config error at .hglfs:3: bad file ... no commit
1131 config error at .hglfs:3: bad file ... no commit
1124 [30]
1132 [30]
1125
1133
1126 $ cat > .hglfs << EOF
1134 $ cat > .hglfs << EOF
1127 > [track]
1135 > [track]
1128 > **.test = size(">5B")
1136 > **.test = size(">5B")
1129 > ** = nonexistent()
1137 > ** = nonexistent()
1130 > EOF
1138 > EOF
1131
1139
1132 $ hg ci -Aqm 'should fail'
1140 $ hg ci -Aqm 'should fail'
1133 abort: parse error in .hglfs: unknown identifier: nonexistent
1141 abort: parse error in .hglfs: unknown identifier: nonexistent
1134 [255]
1142 [255]
1135
1143
1136 '**' works out to mean all files.
1144 '**' works out to mean all files.
1137
1145
1138 $ cat > .hglfs << EOF
1146 $ cat > .hglfs << EOF
1139 > [track]
1147 > [track]
1140 > path:.hglfs = none()
1148 > path:.hglfs = none()
1141 > **.test = size(">5B")
1149 > **.test = size(">5B")
1142 > **.exclude = none()
1150 > **.exclude = none()
1143 > ** = size(">10B")
1151 > ** = size(">10B")
1144 > EOF
1152 > EOF
1145
1153
1146 The LFS policy takes effect without tracking the .hglfs file
1154 The LFS policy takes effect without tracking the .hglfs file
1147
1155
1148 $ echo 'largefile' > lfs.test
1156 $ echo 'largefile' > lfs.test
1149 $ echo '012345678901234567890' > nolfs.exclude
1157 $ echo '012345678901234567890' > nolfs.exclude
1150 $ echo '01234567890123456' > lfs.catchall
1158 $ echo '01234567890123456' > lfs.catchall
1151 $ hg add *
1159 $ hg add *
1152 $ hg ci -qm 'before add .hglfs'
1160 $ hg ci -qm 'before add .hglfs'
1153 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1161 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1154 2: lfs.catchall: d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
1162 2: lfs.catchall: d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
1155 lfs.test: 5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
1163 lfs.test: 5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
1156
1164
1157 The .hglfs file works when tracked
1165 The .hglfs file works when tracked
1158
1166
1159 $ echo 'largefile2' > lfs.test
1167 $ echo 'largefile2' > lfs.test
1160 $ echo '012345678901234567890a' > nolfs.exclude
1168 $ echo '012345678901234567890a' > nolfs.exclude
1161 $ echo '01234567890123456a' > lfs.catchall
1169 $ echo '01234567890123456a' > lfs.catchall
1162 $ hg ci -Aqm 'after adding .hglfs'
1170 $ hg ci -Aqm 'after adding .hglfs'
1163 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1171 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1164 3: lfs.catchall: 31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1172 3: lfs.catchall: 31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1165 lfs.test: 8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1173 lfs.test: 8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1166
1174
1167 The LFS policy stops when the .hglfs is gone
1175 The LFS policy stops when the .hglfs is gone
1168
1176
1169 $ mv .hglfs .hglfs_
1177 $ mv .hglfs .hglfs_
1170 $ echo 'largefile3' > lfs.test
1178 $ echo 'largefile3' > lfs.test
1171 $ echo '012345678901234567890abc' > nolfs.exclude
1179 $ echo '012345678901234567890abc' > nolfs.exclude
1172 $ echo '01234567890123456abc' > lfs.catchall
1180 $ echo '01234567890123456abc' > lfs.catchall
1173 $ hg ci -qm 'file test' -X .hglfs
1181 $ hg ci -qm 'file test' -X .hglfs
1174 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1182 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1175 4:
1183 4:
1176
1184
1177 $ mv .hglfs_ .hglfs
1185 $ mv .hglfs_ .hglfs
1178 $ echo '012345678901234567890abc' > lfs.test
1186 $ echo '012345678901234567890abc' > lfs.test
1179 $ hg ci -m 'back to lfs'
1187 $ hg ci -m 'back to lfs'
1180 $ hg rm lfs.test
1188 $ hg rm lfs.test
1181 $ hg ci -qm 'remove lfs'
1189 $ hg ci -qm 'remove lfs'
1182
1190
1183 {lfs_files} will list deleted files too
1191 {lfs_files} will list deleted files too
1184
1192
1185 $ hg log -T "{lfs_files % '{rev} {file}: {lfspointer.oid}\n'}"
1193 $ hg log -T "{lfs_files % '{rev} {file}: {lfspointer.oid}\n'}"
1186 6 lfs.test:
1194 6 lfs.test:
1187 5 lfs.test: sha256:43f8f41171b6f62a6b61ba4ce98a8a6c1649240a47ebafd43120aa215ac9e7f6
1195 5 lfs.test: sha256:43f8f41171b6f62a6b61ba4ce98a8a6c1649240a47ebafd43120aa215ac9e7f6
1188 3 lfs.catchall: sha256:31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1196 3 lfs.catchall: sha256:31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1189 3 lfs.test: sha256:8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1197 3 lfs.test: sha256:8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1190 2 lfs.catchall: sha256:d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
1198 2 lfs.catchall: sha256:d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
1191 2 lfs.test: sha256:5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
1199 2 lfs.test: sha256:5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
1192
1200
1193 $ hg log -r 'file("set:lfs()")' -T '{rev} {join(lfs_files, ", ")}\n'
1201 $ hg log -r 'file("set:lfs()")' -T '{rev} {join(lfs_files, ", ")}\n'
1194 2 lfs.catchall, lfs.test
1202 2 lfs.catchall, lfs.test
1195 3 lfs.catchall, lfs.test
1203 3 lfs.catchall, lfs.test
1196 5 lfs.test
1204 5 lfs.test
1197 6 lfs.test
1205 6 lfs.test
1198
1206
1199 $ cd ..
1207 $ cd ..
1200
1208
1201 Unbundling adds a requirement to a non-lfs repo, if necessary.
1209 Unbundling adds a requirement to a non-lfs repo, if necessary.
1202
1210
1203 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
1211 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
1204 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
1212 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
1205 $ hg init unbundle
1213 $ hg init unbundle
1206 $ hg pull -R unbundle -q nolfs.hg
1214 $ hg pull -R unbundle -q nolfs.hg
1207 $ hg debugrequires -R unbundle | grep lfs
1215 $ hg debugrequires -R unbundle | grep lfs
1208 [1]
1216 [1]
1209 $ hg pull -R unbundle -q lfs.hg
1217 $ hg pull -R unbundle -q lfs.hg
1210 $ hg debugrequires -R unbundle | grep lfs
1218 $ hg debugrequires -R unbundle | grep lfs
1211 lfs
1219 lfs
1212
1220
1213 $ hg init no_lfs
1221 $ hg init no_lfs
1214 $ cat >> no_lfs/.hg/hgrc <<EOF
1222 $ cat >> no_lfs/.hg/hgrc <<EOF
1215 > [experimental]
1223 > [experimental]
1216 > changegroup3 = True
1224 > changegroup3 = True
1217 > [extensions]
1225 > [extensions]
1218 > lfs=!
1226 > lfs=!
1219 > EOF
1227 > EOF
1220 $ cp -R no_lfs no_lfs2
1228 $ cp -R no_lfs no_lfs2
1221
1229
1222 Pushing from a local lfs repo to a local repo without an lfs requirement and
1230 Pushing from a local lfs repo to a local repo without an lfs requirement and
1223 with lfs disabled, fails.
1231 with lfs disabled, fails.
1224
1232
1225 $ hg push -R convert_lfs2 no_lfs
1233 $ hg push -R convert_lfs2 no_lfs
1226 pushing to no_lfs
1234 pushing to no_lfs
1227 abort: required features are not supported in the destination: lfs
1235 abort: required features are not supported in the destination: lfs
1228 [255]
1236 [255]
1229 $ hg debugrequires -R no_lfs/ | grep lfs
1237 $ hg debugrequires -R no_lfs/ | grep lfs
1230 [1]
1238 [1]
1231
1239
1232 Pulling from a local lfs repo to a local repo without an lfs requirement and
1240 Pulling from a local lfs repo to a local repo without an lfs requirement and
1233 with lfs disabled, fails.
1241 with lfs disabled, fails.
1234
1242
1235 $ hg pull -R no_lfs2 convert_lfs2
1243 $ hg pull -R no_lfs2 convert_lfs2
1236 pulling from convert_lfs2
1244 pulling from convert_lfs2
1237 abort: required features are not supported in the destination: lfs
1245 abort: required features are not supported in the destination: lfs
1238 [255]
1246 [255]
1239 $ hg debugrequires -R no_lfs2/ | grep lfs
1247 $ hg debugrequires -R no_lfs2/ | grep lfs
1240 [1]
1248 [1]
@@ -1,104 +1,105 b''
1 #testcases tree flat-fncache flat-nofncache
1 #testcases tree flat-fncache flat-nofncache
2
2
3 Tests narrow stream clones
3 Tests narrow stream clones
4
4
5 $ . "$TESTDIR/narrow-library.sh"
5 $ . "$TESTDIR/narrow-library.sh"
6
6
7 #if tree
7 #if tree
8 $ cat << EOF >> $HGRCPATH
8 $ cat << EOF >> $HGRCPATH
9 > [experimental]
9 > [experimental]
10 > treemanifest = 1
10 > treemanifest = 1
11 > EOF
11 > EOF
12 #endif
12 #endif
13
13
14 #if flat-nofncache
14 #if flat-nofncache
15 $ cat << EOF >> $HGRCPATH
15 $ cat << EOF >> $HGRCPATH
16 > [format]
16 > [format]
17 > usefncache = 0
17 > usefncache = 0
18 > EOF
18 > EOF
19 #endif
19 #endif
20
20
21 Server setup
21 Server setup
22
22
23 $ hg init master
23 $ hg init master
24 $ cd master
24 $ cd master
25 $ mkdir dir
25 $ mkdir dir
26 $ mkdir dir/src
26 $ mkdir dir/src
27 $ cd dir/src
27 $ cd dir/src
28 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "F$x"; hg add "F$x"; hg commit -m "Commit src $x"; done
28 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "F$x"; hg add "F$x"; hg commit -m "Commit src $x"; done
29
29
30 $ cd ..
30 $ cd ..
31 $ mkdir tests
31 $ mkdir tests
32 $ cd tests
32 $ cd tests
33 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "F$x"; hg add "F$x"; hg commit -m "Commit src $x"; done
33 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "F$x"; hg add "F$x"; hg commit -m "Commit src $x"; done
34 $ cd ../../..
34 $ cd ../../..
35
35
36 Trying to stream clone when the server does not support it
36 Trying to stream clone when the server does not support it
37
37
38 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/F10" --stream
38 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/F10" --stream
39 streaming all changes
39 streaming all changes
40 remote: abort: server does not support narrow stream clones
40 remote: abort: server does not support narrow stream clones
41 abort: pull failed on remote
41 abort: pull failed on remote
42 [100]
42 [100]
43
43
44 Enable stream clone on the server
44 Enable stream clone on the server
45
45
46 $ echo "[experimental]" >> master/.hg/hgrc
46 $ echo "[experimental]" >> master/.hg/hgrc
47 $ echo "server.stream-narrow-clones=True" >> master/.hg/hgrc
47 $ echo "server.stream-narrow-clones=True" >> master/.hg/hgrc
48
48
49 Cloning a specific file when stream clone is supported
49 Cloning a specific file when stream clone is supported
50
50
51 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/F10" --stream
51 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/F10" --stream
52 streaming all changes
52 streaming all changes
53 * files to transfer, * KB of data (glob)
53 * files to transfer, * KB of data (glob)
54 transferred * KB in * seconds (* */sec) (glob)
54 transferred * KB in * seconds (* */sec) (glob)
55
55
56 $ cd narrow
56 $ cd narrow
57 $ ls -A
57 $ ls -A
58 .hg
58 .hg
59 $ hg tracked
59 $ hg tracked
60 I path:dir/src/F10
60 I path:dir/src/F10
61
61
62 Making sure we have the correct set of requirements
62 Making sure we have the correct set of requirements
63
63
64 $ hg debugrequires
64 $ hg debugrequires
65 dotencode (tree !)
65 dotencode (tree !)
66 dotencode (flat-fncache !)
66 dotencode (flat-fncache !)
67 dirstate-v2 (dirstate-v2 !)
67 dirstate-v2 (dirstate-v2 !)
68 fncache (tree !)
68 fncache (tree !)
69 fncache (flat-fncache !)
69 fncache (flat-fncache !)
70 generaldelta
70 generaldelta
71 narrowhg-experimental
71 narrowhg-experimental
72 persistent-nodemap (rust !)
72 persistent-nodemap (rust !)
73 revlog-compression-zstd (zstd !)
73 revlog-compression-zstd (zstd !)
74 revlogv1
74 revlogv1
75 share-safe
75 share-safe
76 sparserevlog
76 sparserevlog
77 store
77 store
78 treemanifest (tree !)
78 treemanifest (tree !)
79
79
80 Making sure store has the required files
80 Making sure store has the required files
81
81
82 $ ls .hg/store/
82 $ ls .hg/store/
83 00changelog.i
83 00changelog.i
84 00manifest.i
84 00manifest.i
85 data
85 data
86 fncache (tree !)
86 fncache (tree !)
87 fncache (flat-fncache !)
87 fncache (flat-fncache !)
88 meta (tree !)
88 meta (tree !)
89 narrowspec
89 narrowspec
90 requires
90 requires
91 undo
91 undo
92 undo.backupfiles
92 undo.backupfiles
93 undo.narrowspec
93 undo.narrowspec
94 undo.phaseroots
94 undo.phaseroots
95
95
96 Checking that repository has all the required data and not broken
96 Checking that repository has all the required data and not broken
97
97
98 $ hg verify
98 $ hg verify
99 checking changesets
99 checking changesets
100 checking manifests
100 checking manifests
101 checking directory manifests (tree !)
101 checking directory manifests (tree !)
102 crosschecking files in changesets and manifests
102 crosschecking files in changesets and manifests
103 checking files
103 checking files
104 checking dirstate
104 checked 40 changesets with 1 changes to 1 files
105 checked 40 changesets with 1 changes to 1 files
@@ -1,342 +1,344 b''
1 ==================================
1 ==================================
2 Basic testing for the push command
2 Basic testing for the push command
3 ==================================
3 ==================================
4
4
5 Testing of the '--rev' flag
5 Testing of the '--rev' flag
6 ===========================
6 ===========================
7
7
8 $ hg init test-revflag
8 $ hg init test-revflag
9 $ hg -R test-revflag unbundle "$TESTDIR/bundles/remote.hg"
9 $ hg -R test-revflag unbundle "$TESTDIR/bundles/remote.hg"
10 adding changesets
10 adding changesets
11 adding manifests
11 adding manifests
12 adding file changes
12 adding file changes
13 added 9 changesets with 7 changes to 4 files (+1 heads)
13 added 9 changesets with 7 changes to 4 files (+1 heads)
14 new changesets bfaf4b5cbf01:916f1afdef90 (9 drafts)
14 new changesets bfaf4b5cbf01:916f1afdef90 (9 drafts)
15 (run 'hg heads' to see heads, 'hg merge' to merge)
15 (run 'hg heads' to see heads, 'hg merge' to merge)
16
16
17 $ for i in 0 1 2 3 4 5 6 7 8; do
17 $ for i in 0 1 2 3 4 5 6 7 8; do
18 > echo
18 > echo
19 > hg init test-revflag-"$i"
19 > hg init test-revflag-"$i"
20 > hg -R test-revflag push -r "$i" test-revflag-"$i"
20 > hg -R test-revflag push -r "$i" test-revflag-"$i"
21 > hg -R test-revflag-"$i" verify -q
21 > hg -R test-revflag-"$i" verify -q
22 > done
22 > done
23
23
24 pushing to test-revflag-0
24 pushing to test-revflag-0
25 searching for changes
25 searching for changes
26 adding changesets
26 adding changesets
27 adding manifests
27 adding manifests
28 adding file changes
28 adding file changes
29 added 1 changesets with 1 changes to 1 files
29 added 1 changesets with 1 changes to 1 files
30
30
31 pushing to test-revflag-1
31 pushing to test-revflag-1
32 searching for changes
32 searching for changes
33 adding changesets
33 adding changesets
34 adding manifests
34 adding manifests
35 adding file changes
35 adding file changes
36 added 2 changesets with 2 changes to 1 files
36 added 2 changesets with 2 changes to 1 files
37
37
38 pushing to test-revflag-2
38 pushing to test-revflag-2
39 searching for changes
39 searching for changes
40 adding changesets
40 adding changesets
41 adding manifests
41 adding manifests
42 adding file changes
42 adding file changes
43 added 3 changesets with 3 changes to 1 files
43 added 3 changesets with 3 changes to 1 files
44
44
45 pushing to test-revflag-3
45 pushing to test-revflag-3
46 searching for changes
46 searching for changes
47 adding changesets
47 adding changesets
48 adding manifests
48 adding manifests
49 adding file changes
49 adding file changes
50 added 4 changesets with 4 changes to 1 files
50 added 4 changesets with 4 changes to 1 files
51
51
52 pushing to test-revflag-4
52 pushing to test-revflag-4
53 searching for changes
53 searching for changes
54 adding changesets
54 adding changesets
55 adding manifests
55 adding manifests
56 adding file changes
56 adding file changes
57 added 2 changesets with 2 changes to 1 files
57 added 2 changesets with 2 changes to 1 files
58
58
59 pushing to test-revflag-5
59 pushing to test-revflag-5
60 searching for changes
60 searching for changes
61 adding changesets
61 adding changesets
62 adding manifests
62 adding manifests
63 adding file changes
63 adding file changes
64 added 3 changesets with 3 changes to 1 files
64 added 3 changesets with 3 changes to 1 files
65
65
66 pushing to test-revflag-6
66 pushing to test-revflag-6
67 searching for changes
67 searching for changes
68 adding changesets
68 adding changesets
69 adding manifests
69 adding manifests
70 adding file changes
70 adding file changes
71 added 4 changesets with 5 changes to 2 files
71 added 4 changesets with 5 changes to 2 files
72
72
73 pushing to test-revflag-7
73 pushing to test-revflag-7
74 searching for changes
74 searching for changes
75 adding changesets
75 adding changesets
76 adding manifests
76 adding manifests
77 adding file changes
77 adding file changes
78 added 5 changesets with 6 changes to 3 files
78 added 5 changesets with 6 changes to 3 files
79
79
80 pushing to test-revflag-8
80 pushing to test-revflag-8
81 searching for changes
81 searching for changes
82 adding changesets
82 adding changesets
83 adding manifests
83 adding manifests
84 adding file changes
84 adding file changes
85 added 5 changesets with 5 changes to 2 files
85 added 5 changesets with 5 changes to 2 files
86
86
87 $ cd test-revflag-8
87 $ cd test-revflag-8
88
88
89 $ hg pull ../test-revflag-7
89 $ hg pull ../test-revflag-7
90 pulling from ../test-revflag-7
90 pulling from ../test-revflag-7
91 searching for changes
91 searching for changes
92 adding changesets
92 adding changesets
93 adding manifests
93 adding manifests
94 adding file changes
94 adding file changes
95 added 4 changesets with 2 changes to 3 files (+1 heads)
95 added 4 changesets with 2 changes to 3 files (+1 heads)
96 new changesets c70afb1ee985:faa2e4234c7a
96 new changesets c70afb1ee985:faa2e4234c7a
97 (run 'hg heads' to see heads, 'hg merge' to merge)
97 (run 'hg heads' to see heads, 'hg merge' to merge)
98
98
99 $ hg verify -q
99 $ hg verify -q
100
100
101 $ cd ..
101 $ cd ..
102
102
103 Test server side validation during push
103 Test server side validation during push
104 =======================================
104 =======================================
105
105
106 $ hg init test-validation
106 $ hg init test-validation
107 $ cd test-validation
107 $ cd test-validation
108
108
109 $ cat > .hg/hgrc <<EOF
109 $ cat > .hg/hgrc <<EOF
110 > [server]
110 > [server]
111 > validate=1
111 > validate=1
112 > EOF
112 > EOF
113
113
114 $ echo alpha > alpha
114 $ echo alpha > alpha
115 $ echo beta > beta
115 $ echo beta > beta
116 $ hg addr
116 $ hg addr
117 adding alpha
117 adding alpha
118 adding beta
118 adding beta
119 $ hg ci -m 1
119 $ hg ci -m 1
120
120
121 $ cd ..
121 $ cd ..
122 $ hg clone test-validation test-validation-clone
122 $ hg clone test-validation test-validation-clone
123 updating to branch default
123 updating to branch default
124 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
125
125
126 #if reporevlogstore
126 #if reporevlogstore
127
127
128 Test spurious filelog entries:
128 Test spurious filelog entries:
129
129
130 $ cd test-validation-clone
130 $ cd test-validation-clone
131 $ echo blah >> beta
131 $ echo blah >> beta
132 $ cp .hg/store/data/beta.i tmp1
132 $ cp .hg/store/data/beta.i tmp1
133 $ hg ci -m 2
133 $ hg ci -m 2
134 $ cp .hg/store/data/beta.i tmp2
134 $ cp .hg/store/data/beta.i tmp2
135 $ hg -q rollback
135 $ hg -q rollback
136 $ mv tmp2 .hg/store/data/beta.i
136 $ mv tmp2 .hg/store/data/beta.i
137 $ echo blah >> beta
137 $ echo blah >> beta
138 $ hg ci -m '2 (corrupt)'
138 $ hg ci -m '2 (corrupt)'
139
139
140 Expected to fail:
140 Expected to fail:
141
141
142 $ hg verify -q
142 $ hg verify -q
143 beta@1: dddc47b3ba30 not in manifests
143 beta@1: dddc47b3ba30 not in manifests
144 not checking dirstate because of previous errors
144 1 integrity errors encountered!
145 1 integrity errors encountered!
145 (first damaged changeset appears to be 1)
146 (first damaged changeset appears to be 1)
146 [1]
147 [1]
147
148
148 $ hg push
149 $ hg push
149 pushing to $TESTTMP/test-validation
150 pushing to $TESTTMP/test-validation
150 searching for changes
151 searching for changes
151 adding changesets
152 adding changesets
152 adding manifests
153 adding manifests
153 adding file changes
154 adding file changes
154 transaction abort!
155 transaction abort!
155 rollback completed
156 rollback completed
156 abort: received spurious file revlog entry
157 abort: received spurious file revlog entry
157 [255]
158 [255]
158
159
159 $ hg -q rollback
160 $ hg -q rollback
160 $ mv tmp1 .hg/store/data/beta.i
161 $ mv tmp1 .hg/store/data/beta.i
161 $ echo beta > beta
162 $ echo beta > beta
162
163
163 Test missing filelog entries:
164 Test missing filelog entries:
164
165
165 $ cp .hg/store/data/beta.i tmp
166 $ cp .hg/store/data/beta.i tmp
166 $ echo blah >> beta
167 $ echo blah >> beta
167 $ hg ci -m '2 (corrupt)'
168 $ hg ci -m '2 (corrupt)'
168 $ mv tmp .hg/store/data/beta.i
169 $ mv tmp .hg/store/data/beta.i
169
170
170 Expected to fail:
171 Expected to fail:
171
172
172 $ hg verify -q
173 $ hg verify -q
173 beta@1: manifest refers to unknown revision dddc47b3ba30
174 beta@1: manifest refers to unknown revision dddc47b3ba30
175 not checking dirstate because of previous errors
174 1 integrity errors encountered!
176 1 integrity errors encountered!
175 (first damaged changeset appears to be 1)
177 (first damaged changeset appears to be 1)
176 [1]
178 [1]
177
179
178 $ hg push
180 $ hg push
179 pushing to $TESTTMP/test-validation
181 pushing to $TESTTMP/test-validation
180 searching for changes
182 searching for changes
181 adding changesets
183 adding changesets
182 adding manifests
184 adding manifests
183 adding file changes
185 adding file changes
184 transaction abort!
186 transaction abort!
185 rollback completed
187 rollback completed
186 abort: missing file data for beta:dddc47b3ba30e54484720ce0f4f768a0f4b6efb9 - run hg verify
188 abort: missing file data for beta:dddc47b3ba30e54484720ce0f4f768a0f4b6efb9 - run hg verify
187 [255]
189 [255]
188
190
189 $ cd ..
191 $ cd ..
190
192
191 #endif
193 #endif
192
194
193 Test push hook locking
195 Test push hook locking
194 =====================
196 =====================
195
197
196 $ hg init 1
198 $ hg init 1
197
199
198 $ echo '[ui]' >> 1/.hg/hgrc
200 $ echo '[ui]' >> 1/.hg/hgrc
199 $ echo 'timeout = 10' >> 1/.hg/hgrc
201 $ echo 'timeout = 10' >> 1/.hg/hgrc
200
202
201 $ echo foo > 1/foo
203 $ echo foo > 1/foo
202 $ hg --cwd 1 ci -A -m foo
204 $ hg --cwd 1 ci -A -m foo
203 adding foo
205 adding foo
204
206
205 $ hg clone 1 2
207 $ hg clone 1 2
206 updating to branch default
208 updating to branch default
207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
209 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208
210
209 $ hg clone 2 3
211 $ hg clone 2 3
210 updating to branch default
212 updating to branch default
211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
212
214
213 $ cat <<EOF > $TESTTMP/debuglocks-pretxn-hook.sh
215 $ cat <<EOF > $TESTTMP/debuglocks-pretxn-hook.sh
214 > hg debuglocks
216 > hg debuglocks
215 > true
217 > true
216 > EOF
218 > EOF
217 $ echo '[hooks]' >> 2/.hg/hgrc
219 $ echo '[hooks]' >> 2/.hg/hgrc
218 $ echo "pretxnchangegroup.a = sh $TESTTMP/debuglocks-pretxn-hook.sh" >> 2/.hg/hgrc
220 $ echo "pretxnchangegroup.a = sh $TESTTMP/debuglocks-pretxn-hook.sh" >> 2/.hg/hgrc
219 $ echo 'changegroup.push = hg push -qf ../1' >> 2/.hg/hgrc
221 $ echo 'changegroup.push = hg push -qf ../1' >> 2/.hg/hgrc
220
222
221 $ echo bar >> 3/foo
223 $ echo bar >> 3/foo
222 $ hg --cwd 3 ci -m bar
224 $ hg --cwd 3 ci -m bar
223
225
224 $ hg --cwd 3 push ../2 --config devel.legacy.exchange=bundle1
226 $ hg --cwd 3 push ../2 --config devel.legacy.exchange=bundle1
225 pushing to ../2
227 pushing to ../2
226 searching for changes
228 searching for changes
227 adding changesets
229 adding changesets
228 adding manifests
230 adding manifests
229 adding file changes
231 adding file changes
230 lock: user *, process * (*s) (glob)
232 lock: user *, process * (*s) (glob)
231 wlock: free
233 wlock: free
232 added 1 changesets with 1 changes to 1 files
234 added 1 changesets with 1 changes to 1 files
233
235
234 $ hg --cwd 1 --config extensions.strip= strip tip -q
236 $ hg --cwd 1 --config extensions.strip= strip tip -q
235 $ hg --cwd 2 --config extensions.strip= strip tip -q
237 $ hg --cwd 2 --config extensions.strip= strip tip -q
236 $ hg --cwd 3 push ../2 # bundle2+
238 $ hg --cwd 3 push ../2 # bundle2+
237 pushing to ../2
239 pushing to ../2
238 searching for changes
240 searching for changes
239 adding changesets
241 adding changesets
240 adding manifests
242 adding manifests
241 adding file changes
243 adding file changes
242 lock: user *, process * (*s) (glob)
244 lock: user *, process * (*s) (glob)
243 wlock: user *, process * (*s) (glob)
245 wlock: user *, process * (*s) (glob)
244 added 1 changesets with 1 changes to 1 files
246 added 1 changesets with 1 changes to 1 files
245
247
246 Test bare push with multiple race checking options
248 Test bare push with multiple race checking options
247 --------------------------------------------------
249 --------------------------------------------------
248
250
249 $ hg init test-bare-push-no-concurrency
251 $ hg init test-bare-push-no-concurrency
250 $ hg init test-bare-push-unrelated-concurrency
252 $ hg init test-bare-push-unrelated-concurrency
251 $ hg -R test-revflag push -r 0 test-bare-push-no-concurrency --config server.concurrent-push-mode=strict
253 $ hg -R test-revflag push -r 0 test-bare-push-no-concurrency --config server.concurrent-push-mode=strict
252 pushing to test-bare-push-no-concurrency
254 pushing to test-bare-push-no-concurrency
253 searching for changes
255 searching for changes
254 adding changesets
256 adding changesets
255 adding manifests
257 adding manifests
256 adding file changes
258 adding file changes
257 added 1 changesets with 1 changes to 1 files
259 added 1 changesets with 1 changes to 1 files
258 $ hg -R test-revflag push -r 0 test-bare-push-unrelated-concurrency --config server.concurrent-push-mode=check-related
260 $ hg -R test-revflag push -r 0 test-bare-push-unrelated-concurrency --config server.concurrent-push-mode=check-related
259 pushing to test-bare-push-unrelated-concurrency
261 pushing to test-bare-push-unrelated-concurrency
260 searching for changes
262 searching for changes
261 adding changesets
263 adding changesets
262 adding manifests
264 adding manifests
263 adding file changes
265 adding file changes
264 added 1 changesets with 1 changes to 1 files
266 added 1 changesets with 1 changes to 1 files
265
267
266 SEC: check for unsafe ssh url
268 SEC: check for unsafe ssh url
267
269
268 $ cat >> $HGRCPATH << EOF
270 $ cat >> $HGRCPATH << EOF
269 > [ui]
271 > [ui]
270 > ssh = sh -c "read l; read l; read l"
272 > ssh = sh -c "read l; read l; read l"
271 > EOF
273 > EOF
272
274
273 $ hg -R test-revflag push 'ssh://-oProxyCommand=touch${IFS}owned/path'
275 $ hg -R test-revflag push 'ssh://-oProxyCommand=touch${IFS}owned/path'
274 pushing to ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
276 pushing to ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
275 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
277 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
276 [255]
278 [255]
277 $ hg -R test-revflag push 'ssh://%2DoProxyCommand=touch${IFS}owned/path'
279 $ hg -R test-revflag push 'ssh://%2DoProxyCommand=touch${IFS}owned/path'
278 pushing to ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
280 pushing to ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path
279 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
281 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
280 [255]
282 [255]
281 $ hg -R test-revflag push 'ssh://fakehost|touch${IFS}owned/path'
283 $ hg -R test-revflag push 'ssh://fakehost|touch${IFS}owned/path'
282 pushing to ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path
284 pushing to ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path
283 abort: no suitable response from remote hg
285 abort: no suitable response from remote hg
284 [255]
286 [255]
285 $ hg -R test-revflag push 'ssh://fakehost%7Ctouch%20owned/path'
287 $ hg -R test-revflag push 'ssh://fakehost%7Ctouch%20owned/path'
286 pushing to ssh://fakehost%7Ctouch%20owned/path
288 pushing to ssh://fakehost%7Ctouch%20owned/path
287 abort: no suitable response from remote hg
289 abort: no suitable response from remote hg
288 [255]
290 [255]
289
291
290 $ [ ! -f owned ] || echo 'you got owned'
292 $ [ ! -f owned ] || echo 'you got owned'
291
293
292 Test `commands.push.require-revs`
294 Test `commands.push.require-revs`
293 ---------------------------------
295 ---------------------------------
294
296
295 $ hg clone -q test-revflag test-require-revs-source
297 $ hg clone -q test-revflag test-require-revs-source
296 $ hg init test-require-revs-dest
298 $ hg init test-require-revs-dest
297 $ cd test-require-revs-source
299 $ cd test-require-revs-source
298 $ cat >> .hg/hgrc << EOF
300 $ cat >> .hg/hgrc << EOF
299 > [paths]
301 > [paths]
300 > default = ../test-require-revs-dest
302 > default = ../test-require-revs-dest
301 > [commands]
303 > [commands]
302 > push.require-revs=1
304 > push.require-revs=1
303 > EOF
305 > EOF
304 $ hg push
306 $ hg push
305 pushing to $TESTTMP/test-require-revs-dest
307 pushing to $TESTTMP/test-require-revs-dest
306 abort: no revisions specified to push
308 abort: no revisions specified to push
307 (did you mean "hg push -r ."?)
309 (did you mean "hg push -r ."?)
308 [10]
310 [10]
309 $ hg push -r 0
311 $ hg push -r 0
310 pushing to $TESTTMP/test-require-revs-dest
312 pushing to $TESTTMP/test-require-revs-dest
311 searching for changes
313 searching for changes
312 adding changesets
314 adding changesets
313 adding manifests
315 adding manifests
314 adding file changes
316 adding file changes
315 added 1 changesets with 1 changes to 1 files
317 added 1 changesets with 1 changes to 1 files
316 $ hg bookmark -r 0 push-this-bookmark
318 $ hg bookmark -r 0 push-this-bookmark
317 (test that -B (bookmark) works for specifying "revs")
319 (test that -B (bookmark) works for specifying "revs")
318 $ hg push -B push-this-bookmark
320 $ hg push -B push-this-bookmark
319 pushing to $TESTTMP/test-require-revs-dest
321 pushing to $TESTTMP/test-require-revs-dest
320 searching for changes
322 searching for changes
321 no changes found
323 no changes found
322 exporting bookmark push-this-bookmark
324 exporting bookmark push-this-bookmark
323 [1]
325 [1]
324 (test that -b (branch) works for specifying "revs")
326 (test that -b (branch) works for specifying "revs")
325 $ hg push -b default
327 $ hg push -b default
326 pushing to $TESTTMP/test-require-revs-dest
328 pushing to $TESTTMP/test-require-revs-dest
327 searching for changes
329 searching for changes
328 abort: push creates new remote head [0-9a-f]+ (re)
330 abort: push creates new remote head [0-9a-f]+ (re)
329 (merge or see 'hg help push' for details about pushing new heads)
331 (merge or see 'hg help push' for details about pushing new heads)
330 [20]
332 [20]
331 (demonstrate that even though we don't have anything to exchange, we're still
333 (demonstrate that even though we don't have anything to exchange, we're still
332 showing the error)
334 showing the error)
333 $ hg push
335 $ hg push
334 pushing to $TESTTMP/test-require-revs-dest
336 pushing to $TESTTMP/test-require-revs-dest
335 abort: no revisions specified to push
337 abort: no revisions specified to push
336 (did you mean "hg push -r ."?)
338 (did you mean "hg push -r ."?)
337 [10]
339 [10]
338 $ hg push --config paths.default:pushrev=0
340 $ hg push --config paths.default:pushrev=0
339 pushing to $TESTTMP/test-require-revs-dest
341 pushing to $TESTTMP/test-require-revs-dest
340 searching for changes
342 searching for changes
341 no changes found
343 no changes found
342 [1]
344 [1]
@@ -1,143 +1,148 b''
1 #require unix-permissions no-root reporevlogstore
1 #require unix-permissions no-root reporevlogstore
2
2
3 $ cat > $TESTTMP/dumpjournal.py <<EOF
3 $ cat > $TESTTMP/dumpjournal.py <<EOF
4 > import sys
4 > import sys
5 > for entry in sys.stdin.read().split('\n'):
5 > for entry in sys.stdin.read().split('\n'):
6 > if entry:
6 > if entry:
7 > print(entry.split('\x00')[0])
7 > print(entry.split('\x00')[0])
8 > EOF
8 > EOF
9
9
10 $ echo "[extensions]" >> $HGRCPATH
10 $ echo "[extensions]" >> $HGRCPATH
11 $ echo "mq=">> $HGRCPATH
11 $ echo "mq=">> $HGRCPATH
12
12
13 $ teststrip() {
13 $ teststrip() {
14 > hg -q up -C $1
14 > hg -q up -C $1
15 > echo % before update $1, strip $2
15 > echo % before update $1, strip $2
16 > hg parents
16 > hg parents
17 > chmod -$3 $4
17 > chmod -$3 $4
18 > hg strip $2 2>&1 | sed 's/\(bundle\).*/\1/' | sed 's/Permission denied.*\.hg\/store\/\(.*\)/Permission denied \.hg\/store\/\1/'
18 > hg strip $2 2>&1 | sed 's/\(bundle\).*/\1/' | sed 's/Permission denied.*\.hg\/store\/\(.*\)/Permission denied \.hg\/store\/\1/'
19 > echo % after update $1, strip $2
19 > echo % after update $1, strip $2
20 > chmod +$3 $4
20 > chmod +$3 $4
21 > hg verify
21 > hg verify
22 > echo % journal contents
22 > echo % journal contents
23 > if [ -f .hg/store/journal ]; then
23 > if [ -f .hg/store/journal ]; then
24 > cat .hg/store/journal | "$PYTHON" $TESTTMP/dumpjournal.py
24 > cat .hg/store/journal | "$PYTHON" $TESTTMP/dumpjournal.py
25 > else
25 > else
26 > echo "(no journal)"
26 > echo "(no journal)"
27 > fi
27 > fi
28 > if ls .hg/store/journal >/dev/null 2>&1; then
28 > if ls .hg/store/journal >/dev/null 2>&1; then
29 > hg recover --verify
29 > hg recover --verify
30 > fi
30 > fi
31 > ls .hg/strip-backup/* >/dev/null 2>&1 && hg unbundle -q .hg/strip-backup/*
31 > ls .hg/strip-backup/* >/dev/null 2>&1 && hg unbundle -q .hg/strip-backup/*
32 > rm -rf .hg/strip-backup
32 > rm -rf .hg/strip-backup
33 > }
33 > }
34
34
35 $ hg init test
35 $ hg init test
36 $ cd test
36 $ cd test
37 $ echo a > a
37 $ echo a > a
38 $ hg -q ci -m "a" -A
38 $ hg -q ci -m "a" -A
39 $ echo b > b
39 $ echo b > b
40 $ hg -q ci -m "b" -A
40 $ hg -q ci -m "b" -A
41 $ echo b2 >> b
41 $ echo b2 >> b
42 $ hg -q ci -m "b2" -A
42 $ hg -q ci -m "b2" -A
43 $ echo c > c
43 $ echo c > c
44 $ hg -q ci -m "c" -A
44 $ hg -q ci -m "c" -A
45 $ teststrip 0 2 w .hg/store/data/b.i
45 $ teststrip 0 2 w .hg/store/data/b.i
46 % before update 0, strip 2
46 % before update 0, strip 2
47 changeset: 0:cb9a9f314b8b
47 changeset: 0:cb9a9f314b8b
48 user: test
48 user: test
49 date: Thu Jan 01 00:00:00 1970 +0000
49 date: Thu Jan 01 00:00:00 1970 +0000
50 summary: a
50 summary: a
51
51
52 saved backup bundle
52 saved backup bundle
53 transaction abort!
53 transaction abort!
54 failed to truncate data/b.i
54 failed to truncate data/b.i
55 rollback failed - please run hg recover
55 rollback failed - please run hg recover
56 (failure reason: [Errno *] Permission denied .hg/store/data/b.i') (glob)
56 (failure reason: [Errno *] Permission denied .hg/store/data/b.i') (glob)
57 strip failed, backup bundle
57 strip failed, backup bundle
58 abort: Permission denied .hg/store/data/b.i'
58 abort: Permission denied .hg/store/data/b.i'
59 % after update 0, strip 2
59 % after update 0, strip 2
60 abandoned transaction found - run hg recover
60 abandoned transaction found - run hg recover
61 checking changesets
61 checking changesets
62 checking manifests
62 checking manifests
63 crosschecking files in changesets and manifests
63 crosschecking files in changesets and manifests
64 checking files
64 checking files
65 b@?: rev 1 points to nonexistent changeset 2
65 b@?: rev 1 points to nonexistent changeset 2
66 (expected 1)
66 (expected 1)
67 b@?: 736c29771fba not in manifests
67 b@?: 736c29771fba not in manifests
68 warning: orphan data file 'data/c.i'
68 warning: orphan data file 'data/c.i'
69 not checking dirstate because of previous errors
69 checked 2 changesets with 3 changes to 2 files
70 checked 2 changesets with 3 changes to 2 files
70 2 warnings encountered!
71 2 warnings encountered!
71 2 integrity errors encountered!
72 2 integrity errors encountered!
72 % journal contents
73 % journal contents
73 00changelog.i
74 00changelog.i
74 00manifest.i
75 00manifest.i
75 data/b.i
76 data/b.i
76 data/c.i
77 data/c.i
77 rolling back interrupted transaction
78 rolling back interrupted transaction
78 checking changesets
79 checking changesets
79 checking manifests
80 checking manifests
80 crosschecking files in changesets and manifests
81 crosschecking files in changesets and manifests
81 checking files
82 checking files
83 checking dirstate
82 checked 2 changesets with 2 changes to 2 files
84 checked 2 changesets with 2 changes to 2 files
83 $ teststrip 0 2 r .hg/store/data/b.i
85 $ teststrip 0 2 r .hg/store/data/b.i
84 % before update 0, strip 2
86 % before update 0, strip 2
85 changeset: 0:cb9a9f314b8b
87 changeset: 0:cb9a9f314b8b
86 user: test
88 user: test
87 date: Thu Jan 01 00:00:00 1970 +0000
89 date: Thu Jan 01 00:00:00 1970 +0000
88 summary: a
90 summary: a
89
91
90 abort: Permission denied .hg/store/data/b.i'
92 abort: Permission denied .hg/store/data/b.i'
91 % after update 0, strip 2
93 % after update 0, strip 2
92 checking changesets
94 checking changesets
93 checking manifests
95 checking manifests
94 crosschecking files in changesets and manifests
96 crosschecking files in changesets and manifests
95 checking files
97 checking files
98 checking dirstate
96 checked 4 changesets with 4 changes to 3 files
99 checked 4 changesets with 4 changes to 3 files
97 % journal contents
100 % journal contents
98 (no journal)
101 (no journal)
99 $ teststrip 0 2 w .hg/store/00manifest.i
102 $ teststrip 0 2 w .hg/store/00manifest.i
100 % before update 0, strip 2
103 % before update 0, strip 2
101 changeset: 0:cb9a9f314b8b
104 changeset: 0:cb9a9f314b8b
102 user: test
105 user: test
103 date: Thu Jan 01 00:00:00 1970 +0000
106 date: Thu Jan 01 00:00:00 1970 +0000
104 summary: a
107 summary: a
105
108
106 saved backup bundle
109 saved backup bundle
107 transaction abort!
110 transaction abort!
108 failed to truncate 00manifest.i
111 failed to truncate 00manifest.i
109 rollback failed - please run hg recover
112 rollback failed - please run hg recover
110 (failure reason: [Errno *] Permission denied .hg/store/00manifest.i') (glob)
113 (failure reason: [Errno *] Permission denied .hg/store/00manifest.i') (glob)
111 strip failed, backup bundle
114 strip failed, backup bundle
112 abort: Permission denied .hg/store/00manifest.i'
115 abort: Permission denied .hg/store/00manifest.i'
113 % after update 0, strip 2
116 % after update 0, strip 2
114 abandoned transaction found - run hg recover
117 abandoned transaction found - run hg recover
115 checking changesets
118 checking changesets
116 checking manifests
119 checking manifests
117 manifest@?: rev 2 points to nonexistent changeset 2
120 manifest@?: rev 2 points to nonexistent changeset 2
118 manifest@?: 3362547cdf64 not in changesets
121 manifest@?: 3362547cdf64 not in changesets
119 manifest@?: rev 3 points to nonexistent changeset 3
122 manifest@?: rev 3 points to nonexistent changeset 3
120 manifest@?: 265a85892ecb not in changesets
123 manifest@?: 265a85892ecb not in changesets
121 crosschecking files in changesets and manifests
124 crosschecking files in changesets and manifests
122 c@3: in manifest but not in changeset
125 c@3: in manifest but not in changeset
123 checking files
126 checking files
124 b@?: rev 1 points to nonexistent changeset 2
127 b@?: rev 1 points to nonexistent changeset 2
125 (expected 1)
128 (expected 1)
126 c@?: rev 0 points to nonexistent changeset 3
129 c@?: rev 0 points to nonexistent changeset 3
130 not checking dirstate because of previous errors
127 checked 2 changesets with 4 changes to 3 files
131 checked 2 changesets with 4 changes to 3 files
128 1 warnings encountered!
132 1 warnings encountered!
129 7 integrity errors encountered!
133 7 integrity errors encountered!
130 (first damaged changeset appears to be 3)
134 (first damaged changeset appears to be 3)
131 % journal contents
135 % journal contents
132 00changelog.i
136 00changelog.i
133 00manifest.i
137 00manifest.i
134 data/b.i
138 data/b.i
135 data/c.i
139 data/c.i
136 rolling back interrupted transaction
140 rolling back interrupted transaction
137 checking changesets
141 checking changesets
138 checking manifests
142 checking manifests
139 crosschecking files in changesets and manifests
143 crosschecking files in changesets and manifests
140 checking files
144 checking files
145 checking dirstate
141 checked 2 changesets with 2 changes to 2 files
146 checked 2 changesets with 2 changes to 2 files
142
147
143 $ cd ..
148 $ cd ..
@@ -1,842 +1,844 b''
1 Set up repo
1 Set up repo
2
2
3 $ hg --config experimental.treemanifest=True init repo
3 $ hg --config experimental.treemanifest=True init repo
4 $ cd repo
4 $ cd repo
5
5
6 Requirements get set on init
6 Requirements get set on init
7
7
8 $ hg debugrequires | grep treemanifest
8 $ hg debugrequires | grep treemanifest
9 treemanifest
9 treemanifest
10
10
11 Without directories, looks like any other repo
11 Without directories, looks like any other repo
12
12
13 $ echo 0 > a
13 $ echo 0 > a
14 $ echo 0 > b
14 $ echo 0 > b
15 $ hg ci -Aqm initial
15 $ hg ci -Aqm initial
16 $ hg debugdata -m 0
16 $ hg debugdata -m 0
17 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
17 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
18 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
18 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
19
19
20 Submanifest is stored in separate revlog
20 Submanifest is stored in separate revlog
21
21
22 $ mkdir dir1
22 $ mkdir dir1
23 $ echo 1 > dir1/a
23 $ echo 1 > dir1/a
24 $ echo 1 > dir1/b
24 $ echo 1 > dir1/b
25 $ echo 1 > e
25 $ echo 1 > e
26 $ hg ci -Aqm 'add dir1'
26 $ hg ci -Aqm 'add dir1'
27 $ hg debugdata -m 1
27 $ hg debugdata -m 1
28 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
28 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
29 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
29 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
30 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
30 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
31 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
31 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
32 $ hg debugdata --dir dir1 0
32 $ hg debugdata --dir dir1 0
33 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
33 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
34 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
34 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
35
35
36 Can add nested directories
36 Can add nested directories
37
37
38 $ mkdir dir1/dir1
38 $ mkdir dir1/dir1
39 $ echo 2 > dir1/dir1/a
39 $ echo 2 > dir1/dir1/a
40 $ echo 2 > dir1/dir1/b
40 $ echo 2 > dir1/dir1/b
41 $ mkdir dir1/dir2
41 $ mkdir dir1/dir2
42 $ echo 2 > dir1/dir2/a
42 $ echo 2 > dir1/dir2/a
43 $ echo 2 > dir1/dir2/b
43 $ echo 2 > dir1/dir2/b
44 $ hg ci -Aqm 'add dir1/dir1'
44 $ hg ci -Aqm 'add dir1/dir1'
45 $ hg files -r .
45 $ hg files -r .
46 a
46 a
47 b
47 b
48 dir1/a
48 dir1/a
49 dir1/b
49 dir1/b
50 dir1/dir1/a
50 dir1/dir1/a
51 dir1/dir1/b
51 dir1/dir1/b
52 dir1/dir2/a
52 dir1/dir2/a
53 dir1/dir2/b
53 dir1/dir2/b
54 e
54 e
55
55
56 The manifest command works
56 The manifest command works
57
57
58 $ hg manifest
58 $ hg manifest
59 a
59 a
60 b
60 b
61 dir1/a
61 dir1/a
62 dir1/b
62 dir1/b
63 dir1/dir1/a
63 dir1/dir1/a
64 dir1/dir1/b
64 dir1/dir1/b
65 dir1/dir2/a
65 dir1/dir2/a
66 dir1/dir2/b
66 dir1/dir2/b
67 e
67 e
68
68
69 Revision is not created for unchanged directory
69 Revision is not created for unchanged directory
70
70
71 $ mkdir dir2
71 $ mkdir dir2
72 $ echo 3 > dir2/a
72 $ echo 3 > dir2/a
73 $ hg add dir2
73 $ hg add dir2
74 adding dir2/a
74 adding dir2/a
75 $ hg debugindex --dir dir1 > before
75 $ hg debugindex --dir dir1 > before
76 $ hg ci -qm 'add dir2'
76 $ hg ci -qm 'add dir2'
77 $ hg debugindex --dir dir1 > after
77 $ hg debugindex --dir dir1 > after
78 $ diff before after
78 $ diff before after
79 $ rm before after
79 $ rm before after
80
80
81 Removing directory does not create an revlog entry
81 Removing directory does not create an revlog entry
82
82
83 $ hg rm dir1/dir1
83 $ hg rm dir1/dir1
84 removing dir1/dir1/a
84 removing dir1/dir1/a
85 removing dir1/dir1/b
85 removing dir1/dir1/b
86 $ hg debugindex --dir dir1/dir1 > before
86 $ hg debugindex --dir dir1/dir1 > before
87 $ hg ci -qm 'remove dir1/dir1'
87 $ hg ci -qm 'remove dir1/dir1'
88 $ hg debugindex --dir dir1/dir1 > after
88 $ hg debugindex --dir dir1/dir1 > after
89 $ diff before after
89 $ diff before after
90 $ rm before after
90 $ rm before after
91
91
92 Check that hg files (calls treemanifest.walk()) works
92 Check that hg files (calls treemanifest.walk()) works
93 without loading all directory revlogs
93 without loading all directory revlogs
94
94
95 $ hg co 'desc("add dir2")'
95 $ hg co 'desc("add dir2")'
96 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
96 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
97 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
98 $ hg files -r . dir1
98 $ hg files -r . dir1
99 dir1/a
99 dir1/a
100 dir1/b
100 dir1/b
101 dir1/dir1/a
101 dir1/dir1/a
102 dir1/dir1/b
102 dir1/dir1/b
103 dir1/dir2/a
103 dir1/dir2/a
104 dir1/dir2/b
104 dir1/dir2/b
105
105
106 Check that status between revisions works (calls treemanifest.matches())
106 Check that status between revisions works (calls treemanifest.matches())
107 without loading all directory revlogs
107 without loading all directory revlogs
108
108
109 $ hg status --rev 'desc("add dir1")' --rev . dir1
109 $ hg status --rev 'desc("add dir1")' --rev . dir1
110 A dir1/dir1/a
110 A dir1/dir1/a
111 A dir1/dir1/b
111 A dir1/dir1/b
112 A dir1/dir2/a
112 A dir1/dir2/a
113 A dir1/dir2/b
113 A dir1/dir2/b
114 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
114 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
115
115
116 Merge creates 2-parent revision of directory revlog
116 Merge creates 2-parent revision of directory revlog
117
117
118 $ echo 5 > dir1/a
118 $ echo 5 > dir1/a
119 $ hg ci -Aqm 'modify dir1/a'
119 $ hg ci -Aqm 'modify dir1/a'
120 $ hg co '.^'
120 $ hg co '.^'
121 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 $ echo 6 > dir1/b
122 $ echo 6 > dir1/b
123 $ hg ci -Aqm 'modify dir1/b'
123 $ hg ci -Aqm 'modify dir1/b'
124 $ hg merge 'desc("modify dir1/a")'
124 $ hg merge 'desc("modify dir1/a")'
125 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
125 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 (branch merge, don't forget to commit)
126 (branch merge, don't forget to commit)
127 $ hg ci -m 'conflict-free merge involving dir1/'
127 $ hg ci -m 'conflict-free merge involving dir1/'
128 $ cat dir1/a
128 $ cat dir1/a
129 5
129 5
130 $ cat dir1/b
130 $ cat dir1/b
131 6
131 6
132 $ hg debugindex --dir dir1
132 $ hg debugindex --dir dir1
133 rev linkrev nodeid p1-nodeid p2-nodeid
133 rev linkrev nodeid p1-nodeid p2-nodeid
134 0 1 8b3ffd73f901 000000000000 000000000000
134 0 1 8b3ffd73f901 000000000000 000000000000
135 1 2 68e9d057c5a8 8b3ffd73f901 000000000000
135 1 2 68e9d057c5a8 8b3ffd73f901 000000000000
136 2 4 4698198d2624 68e9d057c5a8 000000000000
136 2 4 4698198d2624 68e9d057c5a8 000000000000
137 3 5 44844058ccce 68e9d057c5a8 000000000000
137 3 5 44844058ccce 68e9d057c5a8 000000000000
138 4 6 bf3d9b744927 68e9d057c5a8 000000000000
138 4 6 bf3d9b744927 68e9d057c5a8 000000000000
139 5 7 dde7c0af2a03 bf3d9b744927 44844058ccce
139 5 7 dde7c0af2a03 bf3d9b744927 44844058ccce
140
140
141 Merge keeping directory from parent 1 does not create revlog entry. (Note that
141 Merge keeping directory from parent 1 does not create revlog entry. (Note that
142 dir1's manifest does change, but only because dir1/a's filelog changes.)
142 dir1's manifest does change, but only because dir1/a's filelog changes.)
143
143
144 $ hg co 'desc("add dir2")'
144 $ hg co 'desc("add dir2")'
145 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
145 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 $ echo 8 > dir2/a
146 $ echo 8 > dir2/a
147 $ hg ci -m 'modify dir2/a'
147 $ hg ci -m 'modify dir2/a'
148 created new head
148 created new head
149
149
150 $ hg debugindex --dir dir2 > before
150 $ hg debugindex --dir dir2 > before
151 $ hg merge 'desc("modify dir1/a")'
151 $ hg merge 'desc("modify dir1/a")'
152 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
152 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
153 (branch merge, don't forget to commit)
153 (branch merge, don't forget to commit)
154 $ hg revert -r 'desc("modify dir2/a")' .
154 $ hg revert -r 'desc("modify dir2/a")' .
155 reverting dir1/a
155 reverting dir1/a
156 $ hg ci -m 'merge, keeping parent 1'
156 $ hg ci -m 'merge, keeping parent 1'
157 $ hg debugindex --dir dir2 > after
157 $ hg debugindex --dir dir2 > after
158 $ diff before after
158 $ diff before after
159 $ rm before after
159 $ rm before after
160
160
161 Merge keeping directory from parent 2 does not create revlog entry. (Note that
161 Merge keeping directory from parent 2 does not create revlog entry. (Note that
162 dir2's manifest does change, but only because dir2/a's filelog changes.)
162 dir2's manifest does change, but only because dir2/a's filelog changes.)
163
163
164 $ hg co 'desc("modify dir2/a")'
164 $ hg co 'desc("modify dir2/a")'
165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 $ hg debugindex --dir dir1 > before
166 $ hg debugindex --dir dir1 > before
167 $ hg merge 'desc("modify dir1/a")'
167 $ hg merge 'desc("modify dir1/a")'
168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 (branch merge, don't forget to commit)
169 (branch merge, don't forget to commit)
170 $ hg revert -r 'desc("modify dir1/a")' .
170 $ hg revert -r 'desc("modify dir1/a")' .
171 reverting dir2/a
171 reverting dir2/a
172 $ hg ci -m 'merge, keeping parent 2'
172 $ hg ci -m 'merge, keeping parent 2'
173 created new head
173 created new head
174 $ hg debugindex --dir dir1 > after
174 $ hg debugindex --dir dir1 > after
175 $ diff before after
175 $ diff before after
176 $ rm before after
176 $ rm before after
177
177
178 Create flat source repo for tests with mixed flat/tree manifests
178 Create flat source repo for tests with mixed flat/tree manifests
179
179
180 $ cd ..
180 $ cd ..
181 $ hg init repo-flat
181 $ hg init repo-flat
182 $ cd repo-flat
182 $ cd repo-flat
183
183
184 Create a few commits with flat manifest
184 Create a few commits with flat manifest
185
185
186 $ echo 0 > a
186 $ echo 0 > a
187 $ echo 0 > b
187 $ echo 0 > b
188 $ echo 0 > e
188 $ echo 0 > e
189 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
189 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
190 > do
190 > do
191 > mkdir $d
191 > mkdir $d
192 > echo 0 > $d/a
192 > echo 0 > $d/a
193 > echo 0 > $d/b
193 > echo 0 > $d/b
194 > done
194 > done
195 $ hg ci -Aqm initial
195 $ hg ci -Aqm initial
196
196
197 $ echo 1 > a
197 $ echo 1 > a
198 $ echo 1 > dir1/a
198 $ echo 1 > dir1/a
199 $ echo 1 > dir1/dir1/a
199 $ echo 1 > dir1/dir1/a
200 $ hg ci -Aqm 'modify on branch 1'
200 $ hg ci -Aqm 'modify on branch 1'
201
201
202 $ hg co 0
202 $ hg co 0
203 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 $ echo 2 > b
204 $ echo 2 > b
205 $ echo 2 > dir1/b
205 $ echo 2 > dir1/b
206 $ echo 2 > dir1/dir1/b
206 $ echo 2 > dir1/dir1/b
207 $ hg ci -Aqm 'modify on branch 2'
207 $ hg ci -Aqm 'modify on branch 2'
208
208
209 $ hg merge 1
209 $ hg merge 1
210 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 (branch merge, don't forget to commit)
211 (branch merge, don't forget to commit)
212 $ hg ci -m 'merge of flat manifests to new flat manifest'
212 $ hg ci -m 'merge of flat manifests to new flat manifest'
213
213
214 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
214 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
215 $ cat hg.pid >> $DAEMON_PIDS
215 $ cat hg.pid >> $DAEMON_PIDS
216
216
217 Create clone with tree manifests enabled
217 Create clone with tree manifests enabled
218
218
219 $ cd ..
219 $ cd ..
220 $ hg clone --config experimental.treemanifest=1 \
220 $ hg clone --config experimental.treemanifest=1 \
221 > http://localhost:$HGPORT repo-mixed -r 1
221 > http://localhost:$HGPORT repo-mixed -r 1
222 adding changesets
222 adding changesets
223 adding manifests
223 adding manifests
224 adding file changes
224 adding file changes
225 added 2 changesets with 14 changes to 11 files
225 added 2 changesets with 14 changes to 11 files
226 new changesets 5b02a3e8db7e:581ef6037d8b
226 new changesets 5b02a3e8db7e:581ef6037d8b
227 updating to branch default
227 updating to branch default
228 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
228 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 $ cd repo-mixed
229 $ cd repo-mixed
230 $ test -d .hg/store/meta
230 $ test -d .hg/store/meta
231 [1]
231 [1]
232 $ hg debugrequires | grep treemanifest
232 $ hg debugrequires | grep treemanifest
233 treemanifest
233 treemanifest
234
234
235 Should be possible to push updates from flat to tree manifest repo
235 Should be possible to push updates from flat to tree manifest repo
236
236
237 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
237 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
238 pushing to ssh://user@dummy/repo-mixed
238 pushing to ssh://user@dummy/repo-mixed
239 searching for changes
239 searching for changes
240 remote: adding changesets
240 remote: adding changesets
241 remote: adding manifests
241 remote: adding manifests
242 remote: adding file changes
242 remote: adding file changes
243 remote: added 2 changesets with 3 changes to 3 files
243 remote: added 2 changesets with 3 changes to 3 files
244
244
245 Commit should store revlog per directory
245 Commit should store revlog per directory
246
246
247 $ hg co 1
247 $ hg co 1
248 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 $ echo 3 > a
249 $ echo 3 > a
250 $ echo 3 > dir1/a
250 $ echo 3 > dir1/a
251 $ echo 3 > dir1/dir1/a
251 $ echo 3 > dir1/dir1/a
252 $ hg ci -m 'first tree'
252 $ hg ci -m 'first tree'
253 created new head
253 created new head
254 $ find .hg/store/meta | sort
254 $ find .hg/store/meta | sort
255 .hg/store/meta
255 .hg/store/meta
256 .hg/store/meta/dir1
256 .hg/store/meta/dir1
257 .hg/store/meta/dir1/00manifest.i
257 .hg/store/meta/dir1/00manifest.i
258 .hg/store/meta/dir1/dir1
258 .hg/store/meta/dir1/dir1
259 .hg/store/meta/dir1/dir1/00manifest.i
259 .hg/store/meta/dir1/dir1/00manifest.i
260 .hg/store/meta/dir1/dir2
260 .hg/store/meta/dir1/dir2
261 .hg/store/meta/dir1/dir2/00manifest.i
261 .hg/store/meta/dir1/dir2/00manifest.i
262 .hg/store/meta/dir2
262 .hg/store/meta/dir2
263 .hg/store/meta/dir2/00manifest.i
263 .hg/store/meta/dir2/00manifest.i
264
264
265 Merge of two trees
265 Merge of two trees
266
266
267 $ hg co 2
267 $ hg co 2
268 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 $ hg merge 1
269 $ hg merge 1
270 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
270 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
271 (branch merge, don't forget to commit)
271 (branch merge, don't forget to commit)
272 $ hg ci -m 'merge of flat manifests to new tree manifest'
272 $ hg ci -m 'merge of flat manifests to new tree manifest'
273 created new head
273 created new head
274 $ hg diff -r 3
274 $ hg diff -r 3
275
275
276 Parent of tree root manifest should be flat manifest, and two for merge
276 Parent of tree root manifest should be flat manifest, and two for merge
277
277
278 $ hg debugindex -m
278 $ hg debugindex -m
279 rev linkrev nodeid p1-nodeid p2-nodeid
279 rev linkrev nodeid p1-nodeid p2-nodeid
280 0 0 40536115ed9e 000000000000 000000000000
280 0 0 40536115ed9e 000000000000 000000000000
281 1 1 f3376063c255 40536115ed9e 000000000000
281 1 1 f3376063c255 40536115ed9e 000000000000
282 2 2 5d9b9da231a2 40536115ed9e 000000000000
282 2 2 5d9b9da231a2 40536115ed9e 000000000000
283 3 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
283 3 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
284 4 4 51e32a8c60ee f3376063c255 000000000000
284 4 4 51e32a8c60ee f3376063c255 000000000000
285 5 5 cc5baa78b230 5d9b9da231a2 f3376063c255
285 5 5 cc5baa78b230 5d9b9da231a2 f3376063c255
286
286
287
287
288 Status across flat/tree boundary should work
288 Status across flat/tree boundary should work
289
289
290 $ hg status --rev '.^' --rev .
290 $ hg status --rev '.^' --rev .
291 M a
291 M a
292 M dir1/a
292 M dir1/a
293 M dir1/dir1/a
293 M dir1/dir1/a
294
294
295
295
296 Turning off treemanifest config has no effect
296 Turning off treemanifest config has no effect
297
297
298 $ hg debugindex --dir dir1
298 $ hg debugindex --dir dir1
299 rev linkrev nodeid p1-nodeid p2-nodeid
299 rev linkrev nodeid p1-nodeid p2-nodeid
300 0 4 064927a0648a 000000000000 000000000000
300 0 4 064927a0648a 000000000000 000000000000
301 1 5 25ecb8cb8618 000000000000 000000000000
301 1 5 25ecb8cb8618 000000000000 000000000000
302 $ echo 2 > dir1/a
302 $ echo 2 > dir1/a
303 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
303 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
304 $ hg debugindex --dir dir1
304 $ hg debugindex --dir dir1
305 rev linkrev nodeid p1-nodeid p2-nodeid
305 rev linkrev nodeid p1-nodeid p2-nodeid
306 0 4 064927a0648a 000000000000 000000000000
306 0 4 064927a0648a 000000000000 000000000000
307 1 5 25ecb8cb8618 000000000000 000000000000
307 1 5 25ecb8cb8618 000000000000 000000000000
308 2 6 5b16163a30c6 25ecb8cb8618 000000000000
308 2 6 5b16163a30c6 25ecb8cb8618 000000000000
309
309
310 Stripping and recovering changes should work
310 Stripping and recovering changes should work
311
311
312 $ hg st --change tip
312 $ hg st --change tip
313 M dir1/a
313 M dir1/a
314 $ hg --config extensions.strip= strip tip
314 $ hg --config extensions.strip= strip tip
315 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
315 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg
316 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg
317 $ hg debugindex --dir dir1
317 $ hg debugindex --dir dir1
318 rev linkrev nodeid p1-nodeid p2-nodeid
318 rev linkrev nodeid p1-nodeid p2-nodeid
319 0 4 064927a0648a 000000000000 000000000000
319 0 4 064927a0648a 000000000000 000000000000
320 1 5 25ecb8cb8618 000000000000 000000000000
320 1 5 25ecb8cb8618 000000000000 000000000000
321
321
322 #if repobundlerepo
322 #if repobundlerepo
323 $ hg incoming .hg/strip-backup/*
323 $ hg incoming .hg/strip-backup/*
324 comparing with .hg/strip-backup/*-backup.hg (glob)
324 comparing with .hg/strip-backup/*-backup.hg (glob)
325 searching for changes
325 searching for changes
326 changeset: 6:51cfd7b1e13b
326 changeset: 6:51cfd7b1e13b
327 tag: tip
327 tag: tip
328 user: test
328 user: test
329 date: Thu Jan 01 00:00:00 1970 +0000
329 date: Thu Jan 01 00:00:00 1970 +0000
330 summary: modify dir1/a
330 summary: modify dir1/a
331
331
332 #endif
332 #endif
333
333
334 $ hg unbundle .hg/strip-backup/*
334 $ hg unbundle .hg/strip-backup/*
335 adding changesets
335 adding changesets
336 adding manifests
336 adding manifests
337 adding file changes
337 adding file changes
338 added 1 changesets with 1 changes to 1 files
338 added 1 changesets with 1 changes to 1 files
339 new changesets 51cfd7b1e13b (1 drafts)
339 new changesets 51cfd7b1e13b (1 drafts)
340 (run 'hg update' to get a working copy)
340 (run 'hg update' to get a working copy)
341 $ hg --config extensions.strip= strip tip
341 $ hg --config extensions.strip= strip tip
342 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/*-backup.hg (glob)
342 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/*-backup.hg (glob)
343 $ hg unbundle -q .hg/strip-backup/*
343 $ hg unbundle -q .hg/strip-backup/*
344 $ hg debugindex --dir dir1
344 $ hg debugindex --dir dir1
345 rev linkrev nodeid p1-nodeid p2-nodeid
345 rev linkrev nodeid p1-nodeid p2-nodeid
346 0 4 064927a0648a 000000000000 000000000000
346 0 4 064927a0648a 000000000000 000000000000
347 1 5 25ecb8cb8618 000000000000 000000000000
347 1 5 25ecb8cb8618 000000000000 000000000000
348 2 6 5b16163a30c6 25ecb8cb8618 000000000000
348 2 6 5b16163a30c6 25ecb8cb8618 000000000000
349 $ hg st --change tip
349 $ hg st --change tip
350 M dir1/a
350 M dir1/a
351
351
352 Shelving and unshelving should work
352 Shelving and unshelving should work
353
353
354 $ echo foo >> dir1/a
354 $ echo foo >> dir1/a
355 $ hg shelve
355 $ hg shelve
356 shelved as default
356 shelved as default
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ hg unshelve
358 $ hg unshelve
359 unshelving change 'default'
359 unshelving change 'default'
360 $ hg diff --nodates
360 $ hg diff --nodates
361 diff -r 708a273da119 dir1/a
361 diff -r 708a273da119 dir1/a
362 --- a/dir1/a
362 --- a/dir1/a
363 +++ b/dir1/a
363 +++ b/dir1/a
364 @@ -1,1 +1,2 @@
364 @@ -1,1 +1,2 @@
365 1
365 1
366 +foo
366 +foo
367
367
368 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
368 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
369
369
370 $ cd ..
370 $ cd ..
371 $ hg init empty-repo
371 $ hg init empty-repo
372 $ cat << EOF >> empty-repo/.hg/hgrc
372 $ cat << EOF >> empty-repo/.hg/hgrc
373 > [experimental]
373 > [experimental]
374 > changegroup3=yes
374 > changegroup3=yes
375 > EOF
375 > EOF
376 $ hg debugrequires -R empty-repo | grep treemanifest
376 $ hg debugrequires -R empty-repo | grep treemanifest
377 [1]
377 [1]
378 $ hg push -R repo -r 0 empty-repo
378 $ hg push -R repo -r 0 empty-repo
379 pushing to empty-repo
379 pushing to empty-repo
380 searching for changes
380 searching for changes
381 adding changesets
381 adding changesets
382 adding manifests
382 adding manifests
383 adding file changes
383 adding file changes
384 added 1 changesets with 2 changes to 2 files
384 added 1 changesets with 2 changes to 2 files
385 $ hg debugrequires -R empty-repo | grep treemanifest
385 $ hg debugrequires -R empty-repo | grep treemanifest
386 treemanifest
386 treemanifest
387
387
388 Pushing to an empty repo works
388 Pushing to an empty repo works
389
389
390 $ hg --config experimental.treemanifest=1 init clone
390 $ hg --config experimental.treemanifest=1 init clone
391 $ hg debugrequires -R clone | grep treemanifest
391 $ hg debugrequires -R clone | grep treemanifest
392 treemanifest
392 treemanifest
393 $ hg push -R repo clone
393 $ hg push -R repo clone
394 pushing to clone
394 pushing to clone
395 searching for changes
395 searching for changes
396 adding changesets
396 adding changesets
397 adding manifests
397 adding manifests
398 adding file changes
398 adding file changes
399 added 11 changesets with 15 changes to 10 files (+3 heads)
399 added 11 changesets with 15 changes to 10 files (+3 heads)
400 $ hg debugrequires -R clone | grep treemanifest
400 $ hg debugrequires -R clone | grep treemanifest
401 treemanifest
401 treemanifest
402 $ hg -R clone verify -q
402 $ hg -R clone verify -q
403
403
404 Create deeper repo with tree manifests.
404 Create deeper repo with tree manifests.
405
405
406 $ hg --config experimental.treemanifest=True init deeprepo
406 $ hg --config experimental.treemanifest=True init deeprepo
407 $ cd deeprepo
407 $ cd deeprepo
408
408
409 $ mkdir .A
409 $ mkdir .A
410 $ mkdir b
410 $ mkdir b
411 $ mkdir b/bar
411 $ mkdir b/bar
412 $ mkdir b/bar/orange
412 $ mkdir b/bar/orange
413 $ mkdir b/bar/orange/fly
413 $ mkdir b/bar/orange/fly
414 $ mkdir b/foo
414 $ mkdir b/foo
415 $ mkdir b/foo/apple
415 $ mkdir b/foo/apple
416 $ mkdir b/foo/apple/bees
416 $ mkdir b/foo/apple/bees
417
417
418 $ touch .A/one.txt
418 $ touch .A/one.txt
419 $ touch .A/two.txt
419 $ touch .A/two.txt
420 $ touch b/bar/fruits.txt
420 $ touch b/bar/fruits.txt
421 $ touch b/bar/orange/fly/gnat.py
421 $ touch b/bar/orange/fly/gnat.py
422 $ touch b/bar/orange/fly/housefly.txt
422 $ touch b/bar/orange/fly/housefly.txt
423 $ touch b/foo/apple/bees/flower.py
423 $ touch b/foo/apple/bees/flower.py
424 $ touch c.txt
424 $ touch c.txt
425 $ touch d.py
425 $ touch d.py
426
426
427 $ hg ci -Aqm 'initial'
427 $ hg ci -Aqm 'initial'
428
428
429 $ echo >> .A/one.txt
429 $ echo >> .A/one.txt
430 $ echo >> .A/two.txt
430 $ echo >> .A/two.txt
431 $ echo >> b/bar/fruits.txt
431 $ echo >> b/bar/fruits.txt
432 $ echo >> b/bar/orange/fly/gnat.py
432 $ echo >> b/bar/orange/fly/gnat.py
433 $ echo >> b/bar/orange/fly/housefly.txt
433 $ echo >> b/bar/orange/fly/housefly.txt
434 $ echo >> b/foo/apple/bees/flower.py
434 $ echo >> b/foo/apple/bees/flower.py
435 $ echo >> c.txt
435 $ echo >> c.txt
436 $ echo >> d.py
436 $ echo >> d.py
437 $ hg ci -Aqm 'second'
437 $ hg ci -Aqm 'second'
438
438
439 We'll see that visitdir works by removing some treemanifest revlogs and running
439 We'll see that visitdir works by removing some treemanifest revlogs and running
440 the files command with various parameters.
440 the files command with various parameters.
441
441
442 Test files from the root.
442 Test files from the root.
443
443
444 $ hg files -r .
444 $ hg files -r .
445 .A/one.txt
445 .A/one.txt
446 .A/two.txt
446 .A/two.txt
447 b/bar/fruits.txt
447 b/bar/fruits.txt
448 b/bar/orange/fly/gnat.py
448 b/bar/orange/fly/gnat.py
449 b/bar/orange/fly/housefly.txt
449 b/bar/orange/fly/housefly.txt
450 b/foo/apple/bees/flower.py
450 b/foo/apple/bees/flower.py
451 c.txt
451 c.txt
452 d.py
452 d.py
453
453
454 Excludes with a glob should not exclude everything from the glob's root
454 Excludes with a glob should not exclude everything from the glob's root
455
455
456 $ hg files -r . -X 'b/fo?' b
456 $ hg files -r . -X 'b/fo?' b
457 b/bar/fruits.txt
457 b/bar/fruits.txt
458 b/bar/orange/fly/gnat.py
458 b/bar/orange/fly/gnat.py
459 b/bar/orange/fly/housefly.txt
459 b/bar/orange/fly/housefly.txt
460 $ cp -R .hg/store .hg/store-copy
460 $ cp -R .hg/store .hg/store-copy
461
461
462 Test files for a subdirectory.
462 Test files for a subdirectory.
463
463
464 #if reporevlogstore
464 #if reporevlogstore
465 $ rm -r .hg/store/meta/~2e_a
465 $ rm -r .hg/store/meta/~2e_a
466 #endif
466 #endif
467 #if reposimplestore
467 #if reposimplestore
468 $ rm -r .hg/store/meta/._a
468 $ rm -r .hg/store/meta/._a
469 #endif
469 #endif
470 $ hg files -r . b
470 $ hg files -r . b
471 b/bar/fruits.txt
471 b/bar/fruits.txt
472 b/bar/orange/fly/gnat.py
472 b/bar/orange/fly/gnat.py
473 b/bar/orange/fly/housefly.txt
473 b/bar/orange/fly/housefly.txt
474 b/foo/apple/bees/flower.py
474 b/foo/apple/bees/flower.py
475 $ hg diff -r '.^' -r . --stat b
475 $ hg diff -r '.^' -r . --stat b
476 b/bar/fruits.txt | 1 +
476 b/bar/fruits.txt | 1 +
477 b/bar/orange/fly/gnat.py | 1 +
477 b/bar/orange/fly/gnat.py | 1 +
478 b/bar/orange/fly/housefly.txt | 1 +
478 b/bar/orange/fly/housefly.txt | 1 +
479 b/foo/apple/bees/flower.py | 1 +
479 b/foo/apple/bees/flower.py | 1 +
480 4 files changed, 4 insertions(+), 0 deletions(-)
480 4 files changed, 4 insertions(+), 0 deletions(-)
481 $ cp -R .hg/store-copy/. .hg/store
481 $ cp -R .hg/store-copy/. .hg/store
482
482
483 Test files with just includes and excludes.
483 Test files with just includes and excludes.
484
484
485 #if reporevlogstore
485 #if reporevlogstore
486 $ rm -r .hg/store/meta/~2e_a
486 $ rm -r .hg/store/meta/~2e_a
487 #endif
487 #endif
488 #if reposimplestore
488 #if reposimplestore
489 $ rm -r .hg/store/meta/._a
489 $ rm -r .hg/store/meta/._a
490 #endif
490 #endif
491 $ rm -r .hg/store/meta/b/bar/orange/fly
491 $ rm -r .hg/store/meta/b/bar/orange/fly
492 $ rm -r .hg/store/meta/b/foo/apple/bees
492 $ rm -r .hg/store/meta/b/foo/apple/bees
493 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
493 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
494 b/bar/fruits.txt
494 b/bar/fruits.txt
495 $ hg diff -r '.^' -r . --stat -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
495 $ hg diff -r '.^' -r . --stat -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
496 b/bar/fruits.txt | 1 +
496 b/bar/fruits.txt | 1 +
497 1 files changed, 1 insertions(+), 0 deletions(-)
497 1 files changed, 1 insertions(+), 0 deletions(-)
498 $ cp -R .hg/store-copy/. .hg/store
498 $ cp -R .hg/store-copy/. .hg/store
499
499
500 Test files for a subdirectory, excluding a directory within it.
500 Test files for a subdirectory, excluding a directory within it.
501
501
502 #if reporevlogstore
502 #if reporevlogstore
503 $ rm -r .hg/store/meta/~2e_a
503 $ rm -r .hg/store/meta/~2e_a
504 #endif
504 #endif
505 #if reposimplestore
505 #if reposimplestore
506 $ rm -r .hg/store/meta/._a
506 $ rm -r .hg/store/meta/._a
507 #endif
507 #endif
508 $ rm -r .hg/store/meta/b/foo
508 $ rm -r .hg/store/meta/b/foo
509 $ hg files -r . -X path:b/foo b
509 $ hg files -r . -X path:b/foo b
510 b/bar/fruits.txt
510 b/bar/fruits.txt
511 b/bar/orange/fly/gnat.py
511 b/bar/orange/fly/gnat.py
512 b/bar/orange/fly/housefly.txt
512 b/bar/orange/fly/housefly.txt
513 $ hg diff -r '.^' -r . --stat -X path:b/foo b
513 $ hg diff -r '.^' -r . --stat -X path:b/foo b
514 b/bar/fruits.txt | 1 +
514 b/bar/fruits.txt | 1 +
515 b/bar/orange/fly/gnat.py | 1 +
515 b/bar/orange/fly/gnat.py | 1 +
516 b/bar/orange/fly/housefly.txt | 1 +
516 b/bar/orange/fly/housefly.txt | 1 +
517 3 files changed, 3 insertions(+), 0 deletions(-)
517 3 files changed, 3 insertions(+), 0 deletions(-)
518 $ cp -R .hg/store-copy/. .hg/store
518 $ cp -R .hg/store-copy/. .hg/store
519
519
520 Test files for a sub directory, including only a directory within it, and
520 Test files for a sub directory, including only a directory within it, and
521 including an unrelated directory.
521 including an unrelated directory.
522
522
523 #if reporevlogstore
523 #if reporevlogstore
524 $ rm -r .hg/store/meta/~2e_a
524 $ rm -r .hg/store/meta/~2e_a
525 #endif
525 #endif
526 #if reposimplestore
526 #if reposimplestore
527 $ rm -r .hg/store/meta/._a
527 $ rm -r .hg/store/meta/._a
528 #endif
528 #endif
529 $ rm -r .hg/store/meta/b/foo
529 $ rm -r .hg/store/meta/b/foo
530 $ hg files -r . -I path:b/bar/orange -I path:a b
530 $ hg files -r . -I path:b/bar/orange -I path:a b
531 b/bar/orange/fly/gnat.py
531 b/bar/orange/fly/gnat.py
532 b/bar/orange/fly/housefly.txt
532 b/bar/orange/fly/housefly.txt
533 $ hg diff -r '.^' -r . --stat -I path:b/bar/orange -I path:a b
533 $ hg diff -r '.^' -r . --stat -I path:b/bar/orange -I path:a b
534 b/bar/orange/fly/gnat.py | 1 +
534 b/bar/orange/fly/gnat.py | 1 +
535 b/bar/orange/fly/housefly.txt | 1 +
535 b/bar/orange/fly/housefly.txt | 1 +
536 2 files changed, 2 insertions(+), 0 deletions(-)
536 2 files changed, 2 insertions(+), 0 deletions(-)
537 $ cp -R .hg/store-copy/. .hg/store
537 $ cp -R .hg/store-copy/. .hg/store
538
538
539 Test files for a pattern, including a directory, and excluding a directory
539 Test files for a pattern, including a directory, and excluding a directory
540 within that.
540 within that.
541
541
542 #if reporevlogstore
542 #if reporevlogstore
543 $ rm -r .hg/store/meta/~2e_a
543 $ rm -r .hg/store/meta/~2e_a
544 #endif
544 #endif
545 #if reposimplestore
545 #if reposimplestore
546 $ rm -r .hg/store/meta/._a
546 $ rm -r .hg/store/meta/._a
547 #endif
547 #endif
548 $ rm -r .hg/store/meta/b/foo
548 $ rm -r .hg/store/meta/b/foo
549 $ rm -r .hg/store/meta/b/bar/orange
549 $ rm -r .hg/store/meta/b/bar/orange
550 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
550 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
551 b/bar/fruits.txt
551 b/bar/fruits.txt
552 $ hg diff -r '.^' -r . --stat glob:**.txt -I path:b/bar -X path:b/bar/orange
552 $ hg diff -r '.^' -r . --stat glob:**.txt -I path:b/bar -X path:b/bar/orange
553 b/bar/fruits.txt | 1 +
553 b/bar/fruits.txt | 1 +
554 1 files changed, 1 insertions(+), 0 deletions(-)
554 1 files changed, 1 insertions(+), 0 deletions(-)
555 $ cp -R .hg/store-copy/. .hg/store
555 $ cp -R .hg/store-copy/. .hg/store
556
556
557 Add some more changes to the deep repo
557 Add some more changes to the deep repo
558 $ echo narf >> b/bar/fruits.txt
558 $ echo narf >> b/bar/fruits.txt
559 $ hg ci -m narf
559 $ hg ci -m narf
560 $ echo troz >> b/bar/orange/fly/gnat.py
560 $ echo troz >> b/bar/orange/fly/gnat.py
561 $ hg ci -m troz
561 $ hg ci -m troz
562
562
563 Verify works
563 Verify works
564 $ hg verify -q
564 $ hg verify -q
565
565
566 #if repofncache
566 #if repofncache
567 Dirlogs are included in fncache
567 Dirlogs are included in fncache
568 $ grep meta/.A/00manifest.i .hg/store/fncache
568 $ grep meta/.A/00manifest.i .hg/store/fncache
569 meta/.A/00manifest.i
569 meta/.A/00manifest.i
570
570
571 Rebuilt fncache includes dirlogs
571 Rebuilt fncache includes dirlogs
572 $ rm .hg/store/fncache
572 $ rm .hg/store/fncache
573 $ hg debugrebuildfncache
573 $ hg debugrebuildfncache
574 adding data/.A/one.txt.i
574 adding data/.A/one.txt.i
575 adding data/.A/two.txt.i
575 adding data/.A/two.txt.i
576 adding data/b/bar/fruits.txt.i
576 adding data/b/bar/fruits.txt.i
577 adding data/b/bar/orange/fly/gnat.py.i
577 adding data/b/bar/orange/fly/gnat.py.i
578 adding data/b/bar/orange/fly/housefly.txt.i
578 adding data/b/bar/orange/fly/housefly.txt.i
579 adding data/b/foo/apple/bees/flower.py.i
579 adding data/b/foo/apple/bees/flower.py.i
580 adding data/c.txt.i
580 adding data/c.txt.i
581 adding data/d.py.i
581 adding data/d.py.i
582 adding meta/.A/00manifest.i
582 adding meta/.A/00manifest.i
583 adding meta/b/00manifest.i
583 adding meta/b/00manifest.i
584 adding meta/b/bar/00manifest.i
584 adding meta/b/bar/00manifest.i
585 adding meta/b/bar/orange/00manifest.i
585 adding meta/b/bar/orange/00manifest.i
586 adding meta/b/bar/orange/fly/00manifest.i
586 adding meta/b/bar/orange/fly/00manifest.i
587 adding meta/b/foo/00manifest.i
587 adding meta/b/foo/00manifest.i
588 adding meta/b/foo/apple/00manifest.i
588 adding meta/b/foo/apple/00manifest.i
589 adding meta/b/foo/apple/bees/00manifest.i
589 adding meta/b/foo/apple/bees/00manifest.i
590 16 items added, 0 removed from fncache
590 16 items added, 0 removed from fncache
591 #endif
591 #endif
592
592
593 Finish first server
593 Finish first server
594 $ killdaemons.py
594 $ killdaemons.py
595
595
596 Back up the recently added revlogs
596 Back up the recently added revlogs
597 $ cp -R .hg/store .hg/store-newcopy
597 $ cp -R .hg/store .hg/store-newcopy
598
598
599 Verify reports missing dirlog
599 Verify reports missing dirlog
600 $ rm .hg/store/meta/b/00manifest.*
600 $ rm .hg/store/meta/b/00manifest.*
601 $ hg verify
601 $ hg verify
602 checking changesets
602 checking changesets
603 checking manifests
603 checking manifests
604 checking directory manifests
604 checking directory manifests
605 0: empty or missing b/
605 0: empty or missing b/
606 b/@0: parent-directory manifest refers to unknown revision 67688a370455
606 b/@0: parent-directory manifest refers to unknown revision 67688a370455
607 b/@1: parent-directory manifest refers to unknown revision f065da70369e
607 b/@1: parent-directory manifest refers to unknown revision f065da70369e
608 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
608 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
609 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
609 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
610 warning: orphan data file 'meta/b/bar/00manifest.i' (reporevlogstore !)
610 warning: orphan data file 'meta/b/bar/00manifest.i' (reporevlogstore !)
611 warning: orphan data file 'meta/b/bar/orange/00manifest.i' (reporevlogstore !)
611 warning: orphan data file 'meta/b/bar/orange/00manifest.i' (reporevlogstore !)
612 warning: orphan data file 'meta/b/bar/orange/fly/00manifest.i' (reporevlogstore !)
612 warning: orphan data file 'meta/b/bar/orange/fly/00manifest.i' (reporevlogstore !)
613 warning: orphan data file 'meta/b/foo/00manifest.i' (reporevlogstore !)
613 warning: orphan data file 'meta/b/foo/00manifest.i' (reporevlogstore !)
614 warning: orphan data file 'meta/b/foo/apple/00manifest.i' (reporevlogstore !)
614 warning: orphan data file 'meta/b/foo/apple/00manifest.i' (reporevlogstore !)
615 warning: orphan data file 'meta/b/foo/apple/bees/00manifest.i' (reporevlogstore !)
615 warning: orphan data file 'meta/b/foo/apple/bees/00manifest.i' (reporevlogstore !)
616 crosschecking files in changesets and manifests
616 crosschecking files in changesets and manifests
617 b/bar/fruits.txt@0: in changeset but not in manifest
617 b/bar/fruits.txt@0: in changeset but not in manifest
618 b/bar/orange/fly/gnat.py@0: in changeset but not in manifest
618 b/bar/orange/fly/gnat.py@0: in changeset but not in manifest
619 b/bar/orange/fly/housefly.txt@0: in changeset but not in manifest
619 b/bar/orange/fly/housefly.txt@0: in changeset but not in manifest
620 b/foo/apple/bees/flower.py@0: in changeset but not in manifest
620 b/foo/apple/bees/flower.py@0: in changeset but not in manifest
621 checking files
621 checking files
622 not checking dirstate because of previous errors
622 checked 4 changesets with 18 changes to 8 files
623 checked 4 changesets with 18 changes to 8 files
623 6 warnings encountered! (reporevlogstore !)
624 6 warnings encountered! (reporevlogstore !)
624 9 integrity errors encountered!
625 9 integrity errors encountered!
625 (first damaged changeset appears to be 0)
626 (first damaged changeset appears to be 0)
626 [1]
627 [1]
627 $ cp -R .hg/store-newcopy/. .hg/store
628 $ cp -R .hg/store-newcopy/. .hg/store
628
629
629 Verify reports missing dirlog entry
630 Verify reports missing dirlog entry
630 $ mv -f .hg/store-copy/meta/b/00manifest.* .hg/store/meta/b/
631 $ mv -f .hg/store-copy/meta/b/00manifest.* .hg/store/meta/b/
631 $ hg verify
632 $ hg verify
632 checking changesets
633 checking changesets
633 checking manifests
634 checking manifests
634 checking directory manifests
635 checking directory manifests
635 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
636 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
636 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
637 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
637 b/bar/@?: rev 2 points to unexpected changeset 2
638 b/bar/@?: rev 2 points to unexpected changeset 2
638 b/bar/@?: 44d7e1146e0d not in parent-directory manifest
639 b/bar/@?: 44d7e1146e0d not in parent-directory manifest
639 b/bar/@?: rev 3 points to unexpected changeset 3
640 b/bar/@?: rev 3 points to unexpected changeset 3
640 b/bar/@?: 70b10c6b17b7 not in parent-directory manifest
641 b/bar/@?: 70b10c6b17b7 not in parent-directory manifest
641 b/bar/orange/@?: rev 2 points to unexpected changeset 3
642 b/bar/orange/@?: rev 2 points to unexpected changeset 3
642 (expected None)
643 (expected None)
643 b/bar/orange/fly/@?: rev 2 points to unexpected changeset 3
644 b/bar/orange/fly/@?: rev 2 points to unexpected changeset 3
644 (expected None)
645 (expected None)
645 crosschecking files in changesets and manifests
646 crosschecking files in changesets and manifests
646 checking files
647 checking files
648 not checking dirstate because of previous errors
647 checked 4 changesets with 18 changes to 8 files
649 checked 4 changesets with 18 changes to 8 files
648 2 warnings encountered!
650 2 warnings encountered!
649 8 integrity errors encountered!
651 8 integrity errors encountered!
650 (first damaged changeset appears to be 2)
652 (first damaged changeset appears to be 2)
651 [1]
653 [1]
652 $ cp -R .hg/store-newcopy/. .hg/store
654 $ cp -R .hg/store-newcopy/. .hg/store
653
655
654 Test cloning a treemanifest repo over http.
656 Test cloning a treemanifest repo over http.
655 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
657 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
656 $ cat hg.pid >> $DAEMON_PIDS
658 $ cat hg.pid >> $DAEMON_PIDS
657 $ cd ..
659 $ cd ..
658 We can clone even with the knob turned off and we'll get a treemanifest repo.
660 We can clone even with the knob turned off and we'll get a treemanifest repo.
659 $ hg clone --config experimental.treemanifest=False \
661 $ hg clone --config experimental.treemanifest=False \
660 > --config experimental.changegroup3=True \
662 > --config experimental.changegroup3=True \
661 > http://localhost:$HGPORT deepclone
663 > http://localhost:$HGPORT deepclone
662 requesting all changes
664 requesting all changes
663 adding changesets
665 adding changesets
664 adding manifests
666 adding manifests
665 adding file changes
667 adding file changes
666 added 4 changesets with 18 changes to 8 files
668 added 4 changesets with 18 changes to 8 files
667 new changesets 775704be6f52:523e5c631710
669 new changesets 775704be6f52:523e5c631710
668 updating to branch default
670 updating to branch default
669 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
671 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
670 No server errors.
672 No server errors.
671 $ cat deeprepo/errors.log
673 $ cat deeprepo/errors.log
672 requires got updated to include treemanifest
674 requires got updated to include treemanifest
673 $ hg debugrequires -R deepclone | grep treemanifest
675 $ hg debugrequires -R deepclone | grep treemanifest
674 treemanifest
676 treemanifest
675 Tree manifest revlogs exist.
677 Tree manifest revlogs exist.
676 $ find deepclone/.hg/store/meta | sort
678 $ find deepclone/.hg/store/meta | sort
677 deepclone/.hg/store/meta
679 deepclone/.hg/store/meta
678 deepclone/.hg/store/meta/._a (reposimplestore !)
680 deepclone/.hg/store/meta/._a (reposimplestore !)
679 deepclone/.hg/store/meta/._a/00manifest.i (reposimplestore !)
681 deepclone/.hg/store/meta/._a/00manifest.i (reposimplestore !)
680 deepclone/.hg/store/meta/b
682 deepclone/.hg/store/meta/b
681 deepclone/.hg/store/meta/b/00manifest.i
683 deepclone/.hg/store/meta/b/00manifest.i
682 deepclone/.hg/store/meta/b/bar
684 deepclone/.hg/store/meta/b/bar
683 deepclone/.hg/store/meta/b/bar/00manifest.i
685 deepclone/.hg/store/meta/b/bar/00manifest.i
684 deepclone/.hg/store/meta/b/bar/orange
686 deepclone/.hg/store/meta/b/bar/orange
685 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
687 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
686 deepclone/.hg/store/meta/b/bar/orange/fly
688 deepclone/.hg/store/meta/b/bar/orange/fly
687 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
689 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
688 deepclone/.hg/store/meta/b/foo
690 deepclone/.hg/store/meta/b/foo
689 deepclone/.hg/store/meta/b/foo/00manifest.i
691 deepclone/.hg/store/meta/b/foo/00manifest.i
690 deepclone/.hg/store/meta/b/foo/apple
692 deepclone/.hg/store/meta/b/foo/apple
691 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
693 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
692 deepclone/.hg/store/meta/b/foo/apple/bees
694 deepclone/.hg/store/meta/b/foo/apple/bees
693 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
695 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
694 deepclone/.hg/store/meta/~2e_a (reporevlogstore !)
696 deepclone/.hg/store/meta/~2e_a (reporevlogstore !)
695 deepclone/.hg/store/meta/~2e_a/00manifest.i (reporevlogstore !)
697 deepclone/.hg/store/meta/~2e_a/00manifest.i (reporevlogstore !)
696 Verify passes.
698 Verify passes.
697 $ cd deepclone
699 $ cd deepclone
698 $ hg verify -q
700 $ hg verify -q
699 $ cd ..
701 $ cd ..
700
702
701 #if reporevlogstore
703 #if reporevlogstore
702 Create clones using old repo formats to use in later tests
704 Create clones using old repo formats to use in later tests
703 $ hg clone --config format.usestore=False \
705 $ hg clone --config format.usestore=False \
704 > --config experimental.changegroup3=True \
706 > --config experimental.changegroup3=True \
705 > http://localhost:$HGPORT deeprepo-basicstore
707 > http://localhost:$HGPORT deeprepo-basicstore
706 requesting all changes
708 requesting all changes
707 adding changesets
709 adding changesets
708 adding manifests
710 adding manifests
709 adding file changes
711 adding file changes
710 added 4 changesets with 18 changes to 8 files
712 added 4 changesets with 18 changes to 8 files
711 new changesets 775704be6f52:523e5c631710
713 new changesets 775704be6f52:523e5c631710
712 updating to branch default
714 updating to branch default
713 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
715 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
714 $ cd deeprepo-basicstore
716 $ cd deeprepo-basicstore
715 $ hg debugrequires | grep store
717 $ hg debugrequires | grep store
716 [1]
718 [1]
717 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --errorlog=errors.log
719 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --errorlog=errors.log
718 $ cat hg.pid >> $DAEMON_PIDS
720 $ cat hg.pid >> $DAEMON_PIDS
719 $ cd ..
721 $ cd ..
720 $ hg clone --config format.usefncache=False \
722 $ hg clone --config format.usefncache=False \
721 > --config experimental.changegroup3=True \
723 > --config experimental.changegroup3=True \
722 > http://localhost:$HGPORT deeprepo-encodedstore
724 > http://localhost:$HGPORT deeprepo-encodedstore
723 requesting all changes
725 requesting all changes
724 adding changesets
726 adding changesets
725 adding manifests
727 adding manifests
726 adding file changes
728 adding file changes
727 added 4 changesets with 18 changes to 8 files
729 added 4 changesets with 18 changes to 8 files
728 new changesets 775704be6f52:523e5c631710
730 new changesets 775704be6f52:523e5c631710
729 updating to branch default
731 updating to branch default
730 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
731 $ cd deeprepo-encodedstore
733 $ cd deeprepo-encodedstore
732 $ hg debugrequires | grep fncache
734 $ hg debugrequires | grep fncache
733 [1]
735 [1]
734 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
736 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
735 $ cat hg.pid >> $DAEMON_PIDS
737 $ cat hg.pid >> $DAEMON_PIDS
736 $ cd ..
738 $ cd ..
737
739
738 Local clone with basicstore
740 Local clone with basicstore
739 $ hg clone -U deeprepo-basicstore local-clone-basicstore
741 $ hg clone -U deeprepo-basicstore local-clone-basicstore
740 $ hg -R local-clone-basicstore verify -q
742 $ hg -R local-clone-basicstore verify -q
741
743
742 Local clone with encodedstore
744 Local clone with encodedstore
743 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
745 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
744 $ hg -R local-clone-encodedstore verify -q
746 $ hg -R local-clone-encodedstore verify -q
745
747
746 Local clone with fncachestore
748 Local clone with fncachestore
747 $ hg clone -U deeprepo local-clone-fncachestore
749 $ hg clone -U deeprepo local-clone-fncachestore
748 $ hg -R local-clone-fncachestore verify -q
750 $ hg -R local-clone-fncachestore verify -q
749
751
750 Stream clone with basicstore
752 Stream clone with basicstore
751 $ hg clone --config experimental.changegroup3=True --stream -U \
753 $ hg clone --config experimental.changegroup3=True --stream -U \
752 > http://localhost:$HGPORT1 stream-clone-basicstore
754 > http://localhost:$HGPORT1 stream-clone-basicstore
753 streaming all changes
755 streaming all changes
754 28 files to transfer, * of data (glob)
756 28 files to transfer, * of data (glob)
755 transferred * in * seconds (*) (glob)
757 transferred * in * seconds (*) (glob)
756 $ hg -R stream-clone-basicstore verify -q
758 $ hg -R stream-clone-basicstore verify -q
757
759
758 Stream clone with encodedstore
760 Stream clone with encodedstore
759 $ hg clone --config experimental.changegroup3=True --stream -U \
761 $ hg clone --config experimental.changegroup3=True --stream -U \
760 > http://localhost:$HGPORT2 stream-clone-encodedstore
762 > http://localhost:$HGPORT2 stream-clone-encodedstore
761 streaming all changes
763 streaming all changes
762 28 files to transfer, * of data (glob)
764 28 files to transfer, * of data (glob)
763 transferred * in * seconds (*) (glob)
765 transferred * in * seconds (*) (glob)
764 $ hg -R stream-clone-encodedstore verify -q
766 $ hg -R stream-clone-encodedstore verify -q
765
767
766 Stream clone with fncachestore
768 Stream clone with fncachestore
767 $ hg clone --config experimental.changegroup3=True --stream -U \
769 $ hg clone --config experimental.changegroup3=True --stream -U \
768 > http://localhost:$HGPORT stream-clone-fncachestore
770 > http://localhost:$HGPORT stream-clone-fncachestore
769 streaming all changes
771 streaming all changes
770 22 files to transfer, * of data (glob)
772 22 files to transfer, * of data (glob)
771 transferred * in * seconds (*) (glob)
773 transferred * in * seconds (*) (glob)
772 $ hg -R stream-clone-fncachestore verify -q
774 $ hg -R stream-clone-fncachestore verify -q
773
775
774 Packed bundle
776 Packed bundle
775 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
777 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
776 writing 5330 bytes for 18 files (no-zstd !)
778 writing 5330 bytes for 18 files (no-zstd !)
777 writing 5400 bytes for 18 files (zstd !)
779 writing 5400 bytes for 18 files (zstd !)
778 bundle requirements:.* treemanifest(,.*)? (re)
780 bundle requirements:.* treemanifest(,.*)? (re)
779 $ hg debugbundle --spec repo-packed.hg
781 $ hg debugbundle --spec repo-packed.hg
780 none-packed1;requirements%3D(.*%2C)?treemanifest(%2C.*)? (re)
782 none-packed1;requirements%3D(.*%2C)?treemanifest(%2C.*)? (re)
781
783
782 #endif
784 #endif
783
785
784 Bundle with changegroup2 is not supported
786 Bundle with changegroup2 is not supported
785
787
786 $ hg -R deeprepo bundle --all -t v2 deeprepo.bundle
788 $ hg -R deeprepo bundle --all -t v2 deeprepo.bundle
787 abort: repository does not support bundle version 02
789 abort: repository does not support bundle version 02
788 [255]
790 [255]
789
791
790 Pull does not include changegroup for manifest the client already has from
792 Pull does not include changegroup for manifest the client already has from
791 other branch
793 other branch
792
794
793 $ mkdir grafted-dir-repo
795 $ mkdir grafted-dir-repo
794 $ cd grafted-dir-repo
796 $ cd grafted-dir-repo
795 $ hg --config experimental.treemanifest=1 init
797 $ hg --config experimental.treemanifest=1 init
796 $ mkdir dir
798 $ mkdir dir
797 $ echo a > dir/file
799 $ echo a > dir/file
798 $ echo a > file
800 $ echo a > file
799 $ hg ci -Am initial
801 $ hg ci -Am initial
800 adding dir/file
802 adding dir/file
801 adding file
803 adding file
802 $ echo b > dir/file
804 $ echo b > dir/file
803 $ hg ci -m updated
805 $ hg ci -m updated
804 $ hg co '.^'
806 $ hg co '.^'
805 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
807 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
806 $ hg revert -r tip dir/
808 $ hg revert -r tip dir/
807 reverting dir/file
809 reverting dir/file
808 $ echo b > file # to make sure root manifest is sent
810 $ echo b > file # to make sure root manifest is sent
809 $ hg ci -m grafted
811 $ hg ci -m grafted
810 created new head
812 created new head
811 $ cd ..
813 $ cd ..
812
814
813 $ hg --config experimental.treemanifest=1 clone --pull -r 1 \
815 $ hg --config experimental.treemanifest=1 clone --pull -r 1 \
814 > grafted-dir-repo grafted-dir-repo-clone
816 > grafted-dir-repo grafted-dir-repo-clone
815 adding changesets
817 adding changesets
816 adding manifests
818 adding manifests
817 adding file changes
819 adding file changes
818 added 2 changesets with 3 changes to 2 files
820 added 2 changesets with 3 changes to 2 files
819 new changesets d84f4c419457:09ab742f3b0f
821 new changesets d84f4c419457:09ab742f3b0f
820 updating to branch default
822 updating to branch default
821 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
823 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
822 $ cd grafted-dir-repo-clone
824 $ cd grafted-dir-repo-clone
823 $ hg pull -r 2
825 $ hg pull -r 2
824 pulling from $TESTTMP/grafted-dir-repo
826 pulling from $TESTTMP/grafted-dir-repo
825 searching for changes
827 searching for changes
826 adding changesets
828 adding changesets
827 adding manifests
829 adding manifests
828 adding file changes
830 adding file changes
829 added 1 changesets with 1 changes to 1 files (+1 heads)
831 added 1 changesets with 1 changes to 1 files (+1 heads)
830 new changesets 73699489fb7c
832 new changesets 73699489fb7c
831 (run 'hg heads' to see heads, 'hg merge' to merge)
833 (run 'hg heads' to see heads, 'hg merge' to merge)
832
834
833 Committing a empty commit does not duplicate root treemanifest
835 Committing a empty commit does not duplicate root treemanifest
834 $ echo z >> z
836 $ echo z >> z
835 $ hg commit -Aqm 'pre-empty commit'
837 $ hg commit -Aqm 'pre-empty commit'
836 $ hg rm z
838 $ hg rm z
837 $ hg commit --amend -m 'empty commit'
839 $ hg commit --amend -m 'empty commit'
838 saved backup bundle to $TESTTMP/grafted-dir-repo-clone/.hg/strip-backup/cb99d5717cea-9e3b6b02-amend.hg
840 saved backup bundle to $TESTTMP/grafted-dir-repo-clone/.hg/strip-backup/cb99d5717cea-9e3b6b02-amend.hg
839 $ hg log -r 'tip + tip^' -T '{manifest}\n'
841 $ hg log -r 'tip + tip^' -T '{manifest}\n'
840 1:678d3574b88c
842 1:678d3574b88c
841 1:678d3574b88c
843 1:678d3574b88c
842 $ hg --config extensions.strip= strip -r . -q
844 $ hg --config extensions.strip= strip -r . -q
@@ -1,339 +1,365 b''
1 #require reporevlogstore
1 #require reporevlogstore
2
2
3 prepare repo
3 prepare repo
4
4
5 $ hg init a
5 $ hg init a
6 $ cd a
6 $ cd a
7 $ echo "some text" > FOO.txt
7 $ echo "some text" > FOO.txt
8 $ echo "another text" > bar.txt
8 $ echo "another text" > bar.txt
9 $ echo "more text" > QUICK.txt
9 $ echo "more text" > QUICK.txt
10 $ hg add
10 $ hg add
11 adding FOO.txt
11 adding FOO.txt
12 adding QUICK.txt
12 adding QUICK.txt
13 adding bar.txt
13 adding bar.txt
14 $ hg ci -mtest1
14 $ hg ci -mtest1
15
15
16 verify
16 verify
17
17
18 $ hg verify
18 $ hg verify
19 checking changesets
19 checking changesets
20 checking manifests
20 checking manifests
21 crosschecking files in changesets and manifests
21 crosschecking files in changesets and manifests
22 checking files
22 checking files
23 checking dirstate
23 checked 1 changesets with 3 changes to 3 files
24 checked 1 changesets with 3 changes to 3 files
24
25
25 verify with journal
26 verify with journal
26
27
27 $ touch .hg/store/journal
28 $ touch .hg/store/journal
28 $ hg verify
29 $ hg verify
29 abandoned transaction found - run hg recover
30 abandoned transaction found - run hg recover
30 checking changesets
31 checking changesets
31 checking manifests
32 checking manifests
32 crosschecking files in changesets and manifests
33 crosschecking files in changesets and manifests
33 checking files
34 checking files
35 checking dirstate
34 checked 1 changesets with 3 changes to 3 files
36 checked 1 changesets with 3 changes to 3 files
35 $ rm .hg/store/journal
37 $ rm .hg/store/journal
36
38
37 introduce some bugs in repo
39 introduce some bugs in repo
38
40
39 $ cd .hg/store/data
41 $ cd .hg/store/data
40 $ mv _f_o_o.txt.i X_f_o_o.txt.i
42 $ mv _f_o_o.txt.i X_f_o_o.txt.i
41 $ mv bar.txt.i xbar.txt.i
43 $ mv bar.txt.i xbar.txt.i
42 $ rm _q_u_i_c_k.txt.i
44 $ rm _q_u_i_c_k.txt.i
43
45
44 $ hg verify
46 $ hg verify
45 checking changesets
47 checking changesets
46 checking manifests
48 checking manifests
47 crosschecking files in changesets and manifests
49 crosschecking files in changesets and manifests
48 checking files
50 checking files
49 warning: revlog 'data/FOO.txt.i' not in fncache!
51 warning: revlog 'data/FOO.txt.i' not in fncache!
50 0: empty or missing FOO.txt
52 0: empty or missing FOO.txt
51 FOO.txt@0: manifest refers to unknown revision f62022d3d590
53 FOO.txt@0: manifest refers to unknown revision f62022d3d590
52 warning: revlog 'data/QUICK.txt.i' not in fncache!
54 warning: revlog 'data/QUICK.txt.i' not in fncache!
53 0: empty or missing QUICK.txt
55 0: empty or missing QUICK.txt
54 QUICK.txt@0: manifest refers to unknown revision 88b857db8eba
56 QUICK.txt@0: manifest refers to unknown revision 88b857db8eba
55 warning: revlog 'data/bar.txt.i' not in fncache!
57 warning: revlog 'data/bar.txt.i' not in fncache!
56 0: empty or missing bar.txt
58 0: empty or missing bar.txt
57 bar.txt@0: manifest refers to unknown revision 256559129457
59 bar.txt@0: manifest refers to unknown revision 256559129457
60 not checking dirstate because of previous errors
58 checked 1 changesets with 0 changes to 3 files
61 checked 1 changesets with 0 changes to 3 files
59 3 warnings encountered!
62 3 warnings encountered!
60 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
63 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
61 6 integrity errors encountered!
64 6 integrity errors encountered!
62 (first damaged changeset appears to be 0)
65 (first damaged changeset appears to be 0)
63 [1]
66 [1]
64
67
65 $ cd ../../..
68 $ cd ../../..
66 $ cd ..
69 $ cd ..
67
70
68 Set up a repo for testing missing revlog entries
71 Set up a repo for testing missing revlog entries
69
72
70 $ hg init missing-entries
73 $ hg init missing-entries
71 $ cd missing-entries
74 $ cd missing-entries
72 $ echo 0 > file
75 $ echo 0 > file
73 $ hg ci -Aqm0
76 $ hg ci -Aqm0
74 $ cp -R .hg/store .hg/store-partial
77 $ cp -R .hg/store .hg/store-partial
75 $ echo 1 > file
78 $ echo 1 > file
76 $ hg ci -Aqm1
79 $ hg ci -Aqm1
77 $ cp -R .hg/store .hg/store-full
80 $ cp -R .hg/store .hg/store-full
78
81
79 Entire changelog missing
82 Entire changelog missing
80
83
81 $ rm .hg/store/00changelog.*
84 $ rm .hg/store/00changelog.*
82 $ hg verify -q
85 $ hg verify -q
83 0: empty or missing changelog
86 0: empty or missing changelog
84 manifest@0: d0b6632564d4 not in changesets
87 manifest@0: d0b6632564d4 not in changesets
85 manifest@1: 941fc4534185 not in changesets
88 manifest@1: 941fc4534185 not in changesets
89 not checking dirstate because of previous errors
86 3 integrity errors encountered!
90 3 integrity errors encountered!
87 (first damaged changeset appears to be 0)
91 (first damaged changeset appears to be 0)
88 [1]
92 [1]
89 $ cp -R .hg/store-full/. .hg/store
93 $ cp -R .hg/store-full/. .hg/store
90
94
91 Entire manifest log missing
95 Entire manifest log missing
92
96
93 $ rm .hg/store/00manifest.*
97 $ rm .hg/store/00manifest.*
94 $ hg verify -q
98 $ hg verify -q
95 0: empty or missing manifest
99 0: empty or missing manifest
100 not checking dirstate because of previous errors
96 1 integrity errors encountered!
101 1 integrity errors encountered!
97 (first damaged changeset appears to be 0)
102 (first damaged changeset appears to be 0)
98 [1]
103 [1]
99 $ cp -R .hg/store-full/. .hg/store
104 $ cp -R .hg/store-full/. .hg/store
100
105
101 Entire filelog missing
106 Entire filelog missing
102
107
103 $ rm .hg/store/data/file.*
108 $ rm .hg/store/data/file.*
104 $ hg verify -q
109 $ hg verify -q
105 warning: revlog 'data/file.i' not in fncache!
110 warning: revlog 'data/file.i' not in fncache!
106 0: empty or missing file
111 0: empty or missing file
107 file@0: manifest refers to unknown revision 362fef284ce2
112 file@0: manifest refers to unknown revision 362fef284ce2
108 file@1: manifest refers to unknown revision c10f2164107d
113 file@1: manifest refers to unknown revision c10f2164107d
114 not checking dirstate because of previous errors
109 1 warnings encountered!
115 1 warnings encountered!
110 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
116 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
111 3 integrity errors encountered!
117 3 integrity errors encountered!
112 (first damaged changeset appears to be 0)
118 (first damaged changeset appears to be 0)
113 [1]
119 [1]
114 $ cp -R .hg/store-full/. .hg/store
120 $ cp -R .hg/store-full/. .hg/store
115
121
116 Entire changelog and manifest log missing
122 Entire changelog and manifest log missing
117
123
118 $ rm .hg/store/00changelog.*
124 $ rm .hg/store/00changelog.*
119 $ rm .hg/store/00manifest.*
125 $ rm .hg/store/00manifest.*
120 $ hg verify -q
126 $ hg verify -q
121 warning: orphan data file 'data/file.i'
127 warning: orphan data file 'data/file.i'
128 warning: ignoring unknown working parent c5ddb05ab828!
129 file marked as tracked in p1 but not in manifest1
122 1 warnings encountered!
130 1 warnings encountered!
131 1 integrity errors encountered!
132 dirstate inconsistent with current parent's manifest
133 1 dirstate errors
134 [1]
123 $ cp -R .hg/store-full/. .hg/store
135 $ cp -R .hg/store-full/. .hg/store
124
136
125 Entire changelog and filelog missing
137 Entire changelog and filelog missing
126
138
127 $ rm .hg/store/00changelog.*
139 $ rm .hg/store/00changelog.*
128 $ rm .hg/store/data/file.*
140 $ rm .hg/store/data/file.*
129 $ hg verify -q
141 $ hg verify -q
130 0: empty or missing changelog
142 0: empty or missing changelog
131 manifest@0: d0b6632564d4 not in changesets
143 manifest@0: d0b6632564d4 not in changesets
132 manifest@1: 941fc4534185 not in changesets
144 manifest@1: 941fc4534185 not in changesets
133 warning: revlog 'data/file.i' not in fncache!
145 warning: revlog 'data/file.i' not in fncache!
134 ?: empty or missing file
146 ?: empty or missing file
135 file@0: manifest refers to unknown revision 362fef284ce2
147 file@0: manifest refers to unknown revision 362fef284ce2
136 file@1: manifest refers to unknown revision c10f2164107d
148 file@1: manifest refers to unknown revision c10f2164107d
149 not checking dirstate because of previous errors
137 1 warnings encountered!
150 1 warnings encountered!
138 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
151 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
139 6 integrity errors encountered!
152 6 integrity errors encountered!
140 (first damaged changeset appears to be 0)
153 (first damaged changeset appears to be 0)
141 [1]
154 [1]
142 $ cp -R .hg/store-full/. .hg/store
155 $ cp -R .hg/store-full/. .hg/store
143
156
144 Entire manifest log and filelog missing
157 Entire manifest log and filelog missing
145
158
146 $ rm .hg/store/00manifest.*
159 $ rm .hg/store/00manifest.*
147 $ rm .hg/store/data/file.*
160 $ rm .hg/store/data/file.*
148 $ hg verify -q
161 $ hg verify -q
149 0: empty or missing manifest
162 0: empty or missing manifest
150 warning: revlog 'data/file.i' not in fncache!
163 warning: revlog 'data/file.i' not in fncache!
151 0: empty or missing file
164 0: empty or missing file
165 not checking dirstate because of previous errors
152 1 warnings encountered!
166 1 warnings encountered!
153 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
167 hint: run "hg debugrebuildfncache" to recover from corrupt fncache
154 2 integrity errors encountered!
168 2 integrity errors encountered!
155 (first damaged changeset appears to be 0)
169 (first damaged changeset appears to be 0)
156 [1]
170 [1]
157 $ cp -R .hg/store-full/. .hg/store
171 $ cp -R .hg/store-full/. .hg/store
158
172
159 Changelog missing entry
173 Changelog missing entry
160
174
161 $ cp -f .hg/store-partial/00changelog.* .hg/store
175 $ cp -f .hg/store-partial/00changelog.* .hg/store
162 $ hg verify -q
176 $ hg verify -q
163 manifest@?: rev 1 points to nonexistent changeset 1
177 manifest@?: rev 1 points to nonexistent changeset 1
164 manifest@?: 941fc4534185 not in changesets
178 manifest@?: 941fc4534185 not in changesets
165 file@?: rev 1 points to nonexistent changeset 1
179 file@?: rev 1 points to nonexistent changeset 1
166 (expected 0)
180 (expected 0)
181 not checking dirstate because of previous errors
167 1 warnings encountered!
182 1 warnings encountered!
168 3 integrity errors encountered!
183 3 integrity errors encountered!
169 [1]
184 [1]
170 $ cp -R .hg/store-full/. .hg/store
185 $ cp -R .hg/store-full/. .hg/store
171
186
172 Manifest log missing entry
187 Manifest log missing entry
173
188
174 $ cp -f .hg/store-partial/00manifest.* .hg/store
189 $ cp -f .hg/store-partial/00manifest.* .hg/store
175 $ hg verify -q
190 $ hg verify -q
176 manifest@1: changeset refers to unknown revision 941fc4534185
191 manifest@1: changeset refers to unknown revision 941fc4534185
177 file@1: c10f2164107d not in manifests
192 file@1: c10f2164107d not in manifests
193 not checking dirstate because of previous errors
178 2 integrity errors encountered!
194 2 integrity errors encountered!
179 (first damaged changeset appears to be 1)
195 (first damaged changeset appears to be 1)
180 [1]
196 [1]
181 $ cp -R .hg/store-full/. .hg/store
197 $ cp -R .hg/store-full/. .hg/store
182
198
183 Filelog missing entry
199 Filelog missing entry
184
200
185 $ cp -f .hg/store-partial/data/file.* .hg/store/data
201 $ cp -f .hg/store-partial/data/file.* .hg/store/data
186 $ hg verify -q
202 $ hg verify -q
187 file@1: manifest refers to unknown revision c10f2164107d
203 file@1: manifest refers to unknown revision c10f2164107d
204 not checking dirstate because of previous errors
188 1 integrity errors encountered!
205 1 integrity errors encountered!
189 (first damaged changeset appears to be 1)
206 (first damaged changeset appears to be 1)
190 [1]
207 [1]
191 $ cp -R .hg/store-full/. .hg/store
208 $ cp -R .hg/store-full/. .hg/store
192
209
193 Changelog and manifest log missing entry
210 Changelog and manifest log missing entry
194
211
195 $ cp -f .hg/store-partial/00changelog.* .hg/store
212 $ cp -f .hg/store-partial/00changelog.* .hg/store
196 $ cp -f .hg/store-partial/00manifest.* .hg/store
213 $ cp -f .hg/store-partial/00manifest.* .hg/store
197 $ hg verify -q
214 $ hg verify -q
198 file@?: rev 1 points to nonexistent changeset 1
215 file@?: rev 1 points to nonexistent changeset 1
199 (expected 0)
216 (expected 0)
200 file@?: c10f2164107d not in manifests
217 file@?: c10f2164107d not in manifests
218 not checking dirstate because of previous errors
201 1 warnings encountered!
219 1 warnings encountered!
202 2 integrity errors encountered!
220 2 integrity errors encountered!
203 [1]
221 [1]
204 $ cp -R .hg/store-full/. .hg/store
222 $ cp -R .hg/store-full/. .hg/store
205
223
206 Changelog and filelog missing entry
224 Changelog and filelog missing entry
207
225
208 $ cp -f .hg/store-partial/00changelog.* .hg/store
226 $ cp -f .hg/store-partial/00changelog.* .hg/store
209 $ cp -f .hg/store-partial/data/file.* .hg/store/data
227 $ cp -f .hg/store-partial/data/file.* .hg/store/data
210 $ hg verify -q
228 $ hg verify -q
211 manifest@?: rev 1 points to nonexistent changeset 1
229 manifest@?: rev 1 points to nonexistent changeset 1
212 manifest@?: 941fc4534185 not in changesets
230 manifest@?: 941fc4534185 not in changesets
213 file@?: manifest refers to unknown revision c10f2164107d
231 file@?: manifest refers to unknown revision c10f2164107d
232 not checking dirstate because of previous errors
214 3 integrity errors encountered!
233 3 integrity errors encountered!
215 [1]
234 [1]
216 $ cp -R .hg/store-full/. .hg/store
235 $ cp -R .hg/store-full/. .hg/store
217
236
218 Manifest and filelog missing entry
237 Manifest and filelog missing entry
219
238
220 $ cp -f .hg/store-partial/00manifest.* .hg/store
239 $ cp -f .hg/store-partial/00manifest.* .hg/store
221 $ cp -f .hg/store-partial/data/file.* .hg/store/data
240 $ cp -f .hg/store-partial/data/file.* .hg/store/data
222 $ hg verify -q
241 $ hg verify -q
223 manifest@1: changeset refers to unknown revision 941fc4534185
242 manifest@1: changeset refers to unknown revision 941fc4534185
243 not checking dirstate because of previous errors
224 1 integrity errors encountered!
244 1 integrity errors encountered!
225 (first damaged changeset appears to be 1)
245 (first damaged changeset appears to be 1)
226 [1]
246 [1]
227 $ cp -R .hg/store-full/. .hg/store
247 $ cp -R .hg/store-full/. .hg/store
228
248
229 Corrupt changelog base node to cause failure to read revision
249 Corrupt changelog base node to cause failure to read revision
230
250
231 $ printf abcd | dd conv=notrunc of=.hg/store/00changelog.i bs=1 seek=16 \
251 $ printf abcd | dd conv=notrunc of=.hg/store/00changelog.i bs=1 seek=16 \
232 > 2> /dev/null
252 > 2> /dev/null
233 $ hg verify -q
253 $ hg verify -q
234 0: unpacking changeset 08b1860757c2: * (glob)
254 0: unpacking changeset 08b1860757c2: * (glob)
235 manifest@?: rev 0 points to unexpected changeset 0
255 manifest@?: rev 0 points to unexpected changeset 0
236 manifest@?: d0b6632564d4 not in changesets
256 manifest@?: d0b6632564d4 not in changesets
237 file@?: rev 0 points to unexpected changeset 0
257 file@?: rev 0 points to unexpected changeset 0
238 (expected 1)
258 (expected 1)
259 not checking dirstate because of previous errors
239 1 warnings encountered!
260 1 warnings encountered!
240 4 integrity errors encountered!
261 4 integrity errors encountered!
241 (first damaged changeset appears to be 0)
262 (first damaged changeset appears to be 0)
242 [1]
263 [1]
243 $ cp -R .hg/store-full/. .hg/store
264 $ cp -R .hg/store-full/. .hg/store
244
265
245 Corrupt manifest log base node to cause failure to read revision
266 Corrupt manifest log base node to cause failure to read revision
246
267
247 $ printf abcd | dd conv=notrunc of=.hg/store/00manifest.i bs=1 seek=16 \
268 $ printf abcd | dd conv=notrunc of=.hg/store/00manifest.i bs=1 seek=16 \
248 > 2> /dev/null
269 > 2> /dev/null
249 $ hg verify -q
270 $ hg verify -q
250 manifest@0: reading delta d0b6632564d4: * (glob)
271 manifest@0: reading delta d0b6632564d4: * (glob)
251 file@0: 362fef284ce2 not in manifests
272 file@0: 362fef284ce2 not in manifests
273 not checking dirstate because of previous errors
252 2 integrity errors encountered!
274 2 integrity errors encountered!
253 (first damaged changeset appears to be 0)
275 (first damaged changeset appears to be 0)
254 [1]
276 [1]
255 $ cp -R .hg/store-full/. .hg/store
277 $ cp -R .hg/store-full/. .hg/store
256
278
257 Corrupt filelog base node to cause failure to read revision
279 Corrupt filelog base node to cause failure to read revision
258
280
259 $ printf abcd | dd conv=notrunc of=.hg/store/data/file.i bs=1 seek=16 \
281 $ printf abcd | dd conv=notrunc of=.hg/store/data/file.i bs=1 seek=16 \
260 > 2> /dev/null
282 > 2> /dev/null
261 $ hg verify -q
283 $ hg verify -q
262 file@0: unpacking 362fef284ce2: * (glob)
284 file@0: unpacking 362fef284ce2: * (glob)
285 not checking dirstate because of previous errors
263 1 integrity errors encountered!
286 1 integrity errors encountered!
264 (first damaged changeset appears to be 0)
287 (first damaged changeset appears to be 0)
265 [1]
288 [1]
266 $ cp -R .hg/store-full/. .hg/store
289 $ cp -R .hg/store-full/. .hg/store
267
290
268 $ cd ..
291 $ cd ..
269
292
270 test changelog without a manifest
293 test changelog without a manifest
271
294
272 $ hg init b
295 $ hg init b
273 $ cd b
296 $ cd b
274 $ hg branch foo
297 $ hg branch foo
275 marked working directory as branch foo
298 marked working directory as branch foo
276 (branches are permanent and global, did you want a bookmark?)
299 (branches are permanent and global, did you want a bookmark?)
277 $ hg ci -m branchfoo
300 $ hg ci -m branchfoo
278 $ hg verify -q
301 $ hg verify -q
279
302
280 test revlog corruption
303 test revlog corruption
281
304
282 $ touch a
305 $ touch a
283 $ hg add a
306 $ hg add a
284 $ hg ci -m a
307 $ hg ci -m a
285
308
286 $ echo 'corrupted' > b
309 $ echo 'corrupted' > b
287 $ dd if=.hg/store/data/a.i of=start bs=1 count=20 2>/dev/null
310 $ dd if=.hg/store/data/a.i of=start bs=1 count=20 2>/dev/null
288 $ cat start b > .hg/store/data/a.i
311 $ cat start b > .hg/store/data/a.i
289
312
290 $ hg verify -q
313 $ hg verify -q
291 a@1: broken revlog! (index a is corrupted)
314 a@1: broken revlog! (index a is corrupted)
292 warning: orphan data file 'data/a.i'
315 warning: orphan data file 'data/a.i'
316 not checking dirstate because of previous errors
293 1 warnings encountered!
317 1 warnings encountered!
294 1 integrity errors encountered!
318 1 integrity errors encountered!
295 (first damaged changeset appears to be 1)
319 (first damaged changeset appears to be 1)
296 [1]
320 [1]
297
321
298 $ cd ..
322 $ cd ..
299
323
300 test revlog format 0
324 test revlog format 0
301
325
302 $ revlog-formatv0.py
326 $ revlog-formatv0.py
303 $ cd formatv0
327 $ cd formatv0
304 $ hg verify
328 $ hg verify
305 repository uses revlog format 0
329 repository uses revlog format 0
306 checking changesets
330 checking changesets
307 checking manifests
331 checking manifests
308 crosschecking files in changesets and manifests
332 crosschecking files in changesets and manifests
309 checking files
333 checking files
334 checking dirstate
310 checked 1 changesets with 1 changes to 1 files
335 checked 1 changesets with 1 changes to 1 files
311 $ cd ..
336 $ cd ..
312
337
313 test flag processor and skipflags
338 test flag processor and skipflags
314
339
315 $ hg init skipflags
340 $ hg init skipflags
316 $ cd skipflags
341 $ cd skipflags
317 $ cat >> .hg/hgrc <<EOF
342 $ cat >> .hg/hgrc <<EOF
318 > [extensions]
343 > [extensions]
319 > flagprocessor=$RUNTESTDIR/flagprocessorext.py
344 > flagprocessor=$RUNTESTDIR/flagprocessorext.py
320 > EOF
345 > EOF
321 $ echo '[BASE64]content' > base64
346 $ echo '[BASE64]content' > base64
322 $ hg commit -Aqm 'flag processor content' base64
347 $ hg commit -Aqm 'flag processor content' base64
323 $ hg verify -q
348 $ hg verify -q
324
349
325 $ cat >> $TESTTMP/break-base64.py <<EOF
350 $ cat >> $TESTTMP/break-base64.py <<EOF
326 > import base64
351 > import base64
327 > base64.b64decode=lambda x: x
352 > base64.b64decode=lambda x: x
328 > EOF
353 > EOF
329 $ cat >> .hg/hgrc <<EOF
354 $ cat >> .hg/hgrc <<EOF
330 > breakbase64=$TESTTMP/break-base64.py
355 > breakbase64=$TESTTMP/break-base64.py
331 > EOF
356 > EOF
332
357
333 $ hg verify -q
358 $ hg verify -q
334 base64@0: unpacking 794cee7777cb: integrity check failed on base64:0
359 base64@0: unpacking 794cee7777cb: integrity check failed on base64:0
360 not checking dirstate because of previous errors
335 1 integrity errors encountered!
361 1 integrity errors encountered!
336 (first damaged changeset appears to be 0)
362 (first damaged changeset appears to be 0)
337 [1]
363 [1]
338 $ hg verify --config verify.skipflags=2147483647 -q
364 $ hg verify --config verify.skipflags=2147483647 -q
339
365
General Comments 0
You need to be logged in to leave comments. Login now