##// END OF EJS Templates
debugdirstate: deprecate --nodates in favor of --no-dates...
Martin von Zweigbergk -
r39796:7e99b027 default
parent child Browse files
Show More
@@ -1,3364 +1,3367 b''
1 1 # debugcommands.py - command processing for debug* commands
2 2 #
3 3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import codecs
11 11 import collections
12 12 import difflib
13 13 import errno
14 14 import operator
15 15 import os
16 16 import random
17 17 import re
18 18 import socket
19 19 import ssl
20 20 import stat
21 21 import string
22 22 import subprocess
23 23 import sys
24 24 import time
25 25
26 26 from .i18n import _
27 27 from .node import (
28 28 bin,
29 29 hex,
30 30 nullhex,
31 31 nullid,
32 32 nullrev,
33 33 short,
34 34 )
35 35 from . import (
36 36 bundle2,
37 37 changegroup,
38 38 cmdutil,
39 39 color,
40 40 context,
41 41 dagparser,
42 42 encoding,
43 43 error,
44 44 exchange,
45 45 extensions,
46 46 filemerge,
47 47 filesetlang,
48 48 formatter,
49 49 hg,
50 50 httppeer,
51 51 localrepo,
52 52 lock as lockmod,
53 53 logcmdutil,
54 54 merge as mergemod,
55 55 obsolete,
56 56 obsutil,
57 57 phases,
58 58 policy,
59 59 pvec,
60 60 pycompat,
61 61 registrar,
62 62 repair,
63 63 revlog,
64 64 revset,
65 65 revsetlang,
66 66 scmutil,
67 67 setdiscovery,
68 68 simplemerge,
69 69 sshpeer,
70 70 sslutil,
71 71 streamclone,
72 72 templater,
73 73 treediscovery,
74 74 upgrade,
75 75 url as urlmod,
76 76 util,
77 77 vfs as vfsmod,
78 78 wireprotoframing,
79 79 wireprotoserver,
80 80 wireprotov2peer,
81 81 )
82 82 from .utils import (
83 83 cborutil,
84 84 dateutil,
85 85 procutil,
86 86 stringutil,
87 87 )
88 88
89 89 from .revlogutils import (
90 90 deltas as deltautil
91 91 )
92 92
93 93 release = lockmod.release
94 94
95 95 command = registrar.command()
96 96
97 97 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
98 98 def debugancestor(ui, repo, *args):
99 99 """find the ancestor revision of two revisions in a given index"""
100 100 if len(args) == 3:
101 101 index, rev1, rev2 = args
102 102 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
103 103 lookup = r.lookup
104 104 elif len(args) == 2:
105 105 if not repo:
106 106 raise error.Abort(_('there is no Mercurial repository here '
107 107 '(.hg not found)'))
108 108 rev1, rev2 = args
109 109 r = repo.changelog
110 110 lookup = repo.lookup
111 111 else:
112 112 raise error.Abort(_('either two or three arguments required'))
113 113 a = r.ancestor(lookup(rev1), lookup(rev2))
114 114 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
115 115
116 116 @command('debugapplystreamclonebundle', [], 'FILE')
117 117 def debugapplystreamclonebundle(ui, repo, fname):
118 118 """apply a stream clone bundle file"""
119 119 f = hg.openpath(ui, fname)
120 120 gen = exchange.readbundle(ui, f, fname)
121 121 gen.apply(repo)
122 122
123 123 @command('debugbuilddag',
124 124 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
125 125 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
126 126 ('n', 'new-file', None, _('add new file at each rev'))],
127 127 _('[OPTION]... [TEXT]'))
128 128 def debugbuilddag(ui, repo, text=None,
129 129 mergeable_file=False,
130 130 overwritten_file=False,
131 131 new_file=False):
132 132 """builds a repo with a given DAG from scratch in the current empty repo
133 133
134 134 The description of the DAG is read from stdin if not given on the
135 135 command line.
136 136
137 137 Elements:
138 138
139 139 - "+n" is a linear run of n nodes based on the current default parent
140 140 - "." is a single node based on the current default parent
141 141 - "$" resets the default parent to null (implied at the start);
142 142 otherwise the default parent is always the last node created
143 143 - "<p" sets the default parent to the backref p
144 144 - "*p" is a fork at parent p, which is a backref
145 145 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
146 146 - "/p2" is a merge of the preceding node and p2
147 147 - ":tag" defines a local tag for the preceding node
148 148 - "@branch" sets the named branch for subsequent nodes
149 149 - "#...\\n" is a comment up to the end of the line
150 150
151 151 Whitespace between the above elements is ignored.
152 152
153 153 A backref is either
154 154
155 155 - a number n, which references the node curr-n, where curr is the current
156 156 node, or
157 157 - the name of a local tag you placed earlier using ":tag", or
158 158 - empty to denote the default parent.
159 159
160 160 All string valued-elements are either strictly alphanumeric, or must
161 161 be enclosed in double quotes ("..."), with "\\" as escape character.
162 162 """
163 163
164 164 if text is None:
165 165 ui.status(_("reading DAG from stdin\n"))
166 166 text = ui.fin.read()
167 167
168 168 cl = repo.changelog
169 169 if len(cl) > 0:
170 170 raise error.Abort(_('repository is not empty'))
171 171
172 172 # determine number of revs in DAG
173 173 total = 0
174 174 for type, data in dagparser.parsedag(text):
175 175 if type == 'n':
176 176 total += 1
177 177
178 178 if mergeable_file:
179 179 linesperrev = 2
180 180 # make a file with k lines per rev
181 181 initialmergedlines = ['%d' % i
182 182 for i in pycompat.xrange(0, total * linesperrev)]
183 183 initialmergedlines.append("")
184 184
185 185 tags = []
186 186 progress = ui.makeprogress(_('building'), unit=_('revisions'),
187 187 total=total)
188 188 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
189 189 at = -1
190 190 atbranch = 'default'
191 191 nodeids = []
192 192 id = 0
193 193 progress.update(id)
194 194 for type, data in dagparser.parsedag(text):
195 195 if type == 'n':
196 196 ui.note(('node %s\n' % pycompat.bytestr(data)))
197 197 id, ps = data
198 198
199 199 files = []
200 200 filecontent = {}
201 201
202 202 p2 = None
203 203 if mergeable_file:
204 204 fn = "mf"
205 205 p1 = repo[ps[0]]
206 206 if len(ps) > 1:
207 207 p2 = repo[ps[1]]
208 208 pa = p1.ancestor(p2)
209 209 base, local, other = [x[fn].data() for x in (pa, p1,
210 210 p2)]
211 211 m3 = simplemerge.Merge3Text(base, local, other)
212 212 ml = [l.strip() for l in m3.merge_lines()]
213 213 ml.append("")
214 214 elif at > 0:
215 215 ml = p1[fn].data().split("\n")
216 216 else:
217 217 ml = initialmergedlines
218 218 ml[id * linesperrev] += " r%i" % id
219 219 mergedtext = "\n".join(ml)
220 220 files.append(fn)
221 221 filecontent[fn] = mergedtext
222 222
223 223 if overwritten_file:
224 224 fn = "of"
225 225 files.append(fn)
226 226 filecontent[fn] = "r%i\n" % id
227 227
228 228 if new_file:
229 229 fn = "nf%i" % id
230 230 files.append(fn)
231 231 filecontent[fn] = "r%i\n" % id
232 232 if len(ps) > 1:
233 233 if not p2:
234 234 p2 = repo[ps[1]]
235 235 for fn in p2:
236 236 if fn.startswith("nf"):
237 237 files.append(fn)
238 238 filecontent[fn] = p2[fn].data()
239 239
240 240 def fctxfn(repo, cx, path):
241 241 if path in filecontent:
242 242 return context.memfilectx(repo, cx, path,
243 243 filecontent[path])
244 244 return None
245 245
246 246 if len(ps) == 0 or ps[0] < 0:
247 247 pars = [None, None]
248 248 elif len(ps) == 1:
249 249 pars = [nodeids[ps[0]], None]
250 250 else:
251 251 pars = [nodeids[p] for p in ps]
252 252 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
253 253 date=(id, 0),
254 254 user="debugbuilddag",
255 255 extra={'branch': atbranch})
256 256 nodeid = repo.commitctx(cx)
257 257 nodeids.append(nodeid)
258 258 at = id
259 259 elif type == 'l':
260 260 id, name = data
261 261 ui.note(('tag %s\n' % name))
262 262 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
263 263 elif type == 'a':
264 264 ui.note(('branch %s\n' % data))
265 265 atbranch = data
266 266 progress.update(id)
267 267
268 268 if tags:
269 269 repo.vfs.write("localtags", "".join(tags))
270 270
271 271 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
272 272 indent_string = ' ' * indent
273 273 if all:
274 274 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
275 275 % indent_string)
276 276
277 277 def showchunks(named):
278 278 ui.write("\n%s%s\n" % (indent_string, named))
279 279 for deltadata in gen.deltaiter():
280 280 node, p1, p2, cs, deltabase, delta, flags = deltadata
281 281 ui.write("%s%s %s %s %s %s %d\n" %
282 282 (indent_string, hex(node), hex(p1), hex(p2),
283 283 hex(cs), hex(deltabase), len(delta)))
284 284
285 285 chunkdata = gen.changelogheader()
286 286 showchunks("changelog")
287 287 chunkdata = gen.manifestheader()
288 288 showchunks("manifest")
289 289 for chunkdata in iter(gen.filelogheader, {}):
290 290 fname = chunkdata['filename']
291 291 showchunks(fname)
292 292 else:
293 293 if isinstance(gen, bundle2.unbundle20):
294 294 raise error.Abort(_('use debugbundle2 for this file'))
295 295 chunkdata = gen.changelogheader()
296 296 for deltadata in gen.deltaiter():
297 297 node, p1, p2, cs, deltabase, delta, flags = deltadata
298 298 ui.write("%s%s\n" % (indent_string, hex(node)))
299 299
300 300 def _debugobsmarkers(ui, part, indent=0, **opts):
301 301 """display version and markers contained in 'data'"""
302 302 opts = pycompat.byteskwargs(opts)
303 303 data = part.read()
304 304 indent_string = ' ' * indent
305 305 try:
306 306 version, markers = obsolete._readmarkers(data)
307 307 except error.UnknownVersion as exc:
308 308 msg = "%sunsupported version: %s (%d bytes)\n"
309 309 msg %= indent_string, exc.version, len(data)
310 310 ui.write(msg)
311 311 else:
312 312 msg = "%sversion: %d (%d bytes)\n"
313 313 msg %= indent_string, version, len(data)
314 314 ui.write(msg)
315 315 fm = ui.formatter('debugobsolete', opts)
316 316 for rawmarker in sorted(markers):
317 317 m = obsutil.marker(None, rawmarker)
318 318 fm.startitem()
319 319 fm.plain(indent_string)
320 320 cmdutil.showmarker(fm, m)
321 321 fm.end()
322 322
323 323 def _debugphaseheads(ui, data, indent=0):
324 324 """display version and markers contained in 'data'"""
325 325 indent_string = ' ' * indent
326 326 headsbyphase = phases.binarydecode(data)
327 327 for phase in phases.allphases:
328 328 for head in headsbyphase[phase]:
329 329 ui.write(indent_string)
330 330 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
331 331
332 332 def _quasirepr(thing):
333 333 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
334 334 return '{%s}' % (
335 335 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
336 336 return pycompat.bytestr(repr(thing))
337 337
338 338 def _debugbundle2(ui, gen, all=None, **opts):
339 339 """lists the contents of a bundle2"""
340 340 if not isinstance(gen, bundle2.unbundle20):
341 341 raise error.Abort(_('not a bundle2 file'))
342 342 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
343 343 parttypes = opts.get(r'part_type', [])
344 344 for part in gen.iterparts():
345 345 if parttypes and part.type not in parttypes:
346 346 continue
347 347 msg = '%s -- %s (mandatory: %r)\n'
348 348 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
349 349 if part.type == 'changegroup':
350 350 version = part.params.get('version', '01')
351 351 cg = changegroup.getunbundler(version, part, 'UN')
352 352 if not ui.quiet:
353 353 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
354 354 if part.type == 'obsmarkers':
355 355 if not ui.quiet:
356 356 _debugobsmarkers(ui, part, indent=4, **opts)
357 357 if part.type == 'phase-heads':
358 358 if not ui.quiet:
359 359 _debugphaseheads(ui, part, indent=4)
360 360
361 361 @command('debugbundle',
362 362 [('a', 'all', None, _('show all details')),
363 363 ('', 'part-type', [], _('show only the named part type')),
364 364 ('', 'spec', None, _('print the bundlespec of the bundle'))],
365 365 _('FILE'),
366 366 norepo=True)
367 367 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
368 368 """lists the contents of a bundle"""
369 369 with hg.openpath(ui, bundlepath) as f:
370 370 if spec:
371 371 spec = exchange.getbundlespec(ui, f)
372 372 ui.write('%s\n' % spec)
373 373 return
374 374
375 375 gen = exchange.readbundle(ui, f, bundlepath)
376 376 if isinstance(gen, bundle2.unbundle20):
377 377 return _debugbundle2(ui, gen, all=all, **opts)
378 378 _debugchangegroup(ui, gen, all=all, **opts)
379 379
380 380 @command('debugcapabilities',
381 381 [], _('PATH'),
382 382 norepo=True)
383 383 def debugcapabilities(ui, path, **opts):
384 384 """lists the capabilities of a remote peer"""
385 385 opts = pycompat.byteskwargs(opts)
386 386 peer = hg.peer(ui, opts, path)
387 387 caps = peer.capabilities()
388 388 ui.write(('Main capabilities:\n'))
389 389 for c in sorted(caps):
390 390 ui.write((' %s\n') % c)
391 391 b2caps = bundle2.bundle2caps(peer)
392 392 if b2caps:
393 393 ui.write(('Bundle2 capabilities:\n'))
394 394 for key, values in sorted(b2caps.iteritems()):
395 395 ui.write((' %s\n') % key)
396 396 for v in values:
397 397 ui.write((' %s\n') % v)
398 398
399 399 @command('debugcheckstate', [], '')
400 400 def debugcheckstate(ui, repo):
401 401 """validate the correctness of the current dirstate"""
402 402 parent1, parent2 = repo.dirstate.parents()
403 403 m1 = repo[parent1].manifest()
404 404 m2 = repo[parent2].manifest()
405 405 errors = 0
406 406 for f in repo.dirstate:
407 407 state = repo.dirstate[f]
408 408 if state in "nr" and f not in m1:
409 409 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
410 410 errors += 1
411 411 if state in "a" and f in m1:
412 412 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
413 413 errors += 1
414 414 if state in "m" and f not in m1 and f not in m2:
415 415 ui.warn(_("%s in state %s, but not in either manifest\n") %
416 416 (f, state))
417 417 errors += 1
418 418 for f in m1:
419 419 state = repo.dirstate[f]
420 420 if state not in "nrm":
421 421 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
422 422 errors += 1
423 423 if errors:
424 424 error = _(".hg/dirstate inconsistent with current parent's manifest")
425 425 raise error.Abort(error)
426 426
427 427 @command('debugcolor',
428 428 [('', 'style', None, _('show all configured styles'))],
429 429 'hg debugcolor')
430 430 def debugcolor(ui, repo, **opts):
431 431 """show available color, effects or style"""
432 432 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
433 433 if opts.get(r'style'):
434 434 return _debugdisplaystyle(ui)
435 435 else:
436 436 return _debugdisplaycolor(ui)
437 437
438 438 def _debugdisplaycolor(ui):
439 439 ui = ui.copy()
440 440 ui._styles.clear()
441 441 for effect in color._activeeffects(ui).keys():
442 442 ui._styles[effect] = effect
443 443 if ui._terminfoparams:
444 444 for k, v in ui.configitems('color'):
445 445 if k.startswith('color.'):
446 446 ui._styles[k] = k[6:]
447 447 elif k.startswith('terminfo.'):
448 448 ui._styles[k] = k[9:]
449 449 ui.write(_('available colors:\n'))
450 450 # sort label with a '_' after the other to group '_background' entry.
451 451 items = sorted(ui._styles.items(),
452 452 key=lambda i: ('_' in i[0], i[0], i[1]))
453 453 for colorname, label in items:
454 454 ui.write(('%s\n') % colorname, label=label)
455 455
456 456 def _debugdisplaystyle(ui):
457 457 ui.write(_('available style:\n'))
458 458 if not ui._styles:
459 459 return
460 460 width = max(len(s) for s in ui._styles)
461 461 for label, effects in sorted(ui._styles.items()):
462 462 ui.write('%s' % label, label=label)
463 463 if effects:
464 464 # 50
465 465 ui.write(': ')
466 466 ui.write(' ' * (max(0, width - len(label))))
467 467 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
468 468 ui.write('\n')
469 469
470 470 @command('debugcreatestreamclonebundle', [], 'FILE')
471 471 def debugcreatestreamclonebundle(ui, repo, fname):
472 472 """create a stream clone bundle file
473 473
474 474 Stream bundles are special bundles that are essentially archives of
475 475 revlog files. They are commonly used for cloning very quickly.
476 476 """
477 477 # TODO we may want to turn this into an abort when this functionality
478 478 # is moved into `hg bundle`.
479 479 if phases.hassecret(repo):
480 480 ui.warn(_('(warning: stream clone bundle will contain secret '
481 481 'revisions)\n'))
482 482
483 483 requirements, gen = streamclone.generatebundlev1(repo)
484 484 changegroup.writechunks(ui, gen, fname)
485 485
486 486 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
487 487
488 488 @command('debugdag',
489 489 [('t', 'tags', None, _('use tags as labels')),
490 490 ('b', 'branches', None, _('annotate with branch names')),
491 491 ('', 'dots', None, _('use dots for runs')),
492 492 ('s', 'spaces', None, _('separate elements by spaces'))],
493 493 _('[OPTION]... [FILE [REV]...]'),
494 494 optionalrepo=True)
495 495 def debugdag(ui, repo, file_=None, *revs, **opts):
496 496 """format the changelog or an index DAG as a concise textual description
497 497
498 498 If you pass a revlog index, the revlog's DAG is emitted. If you list
499 499 revision numbers, they get labeled in the output as rN.
500 500
501 501 Otherwise, the changelog DAG of the current repo is emitted.
502 502 """
503 503 spaces = opts.get(r'spaces')
504 504 dots = opts.get(r'dots')
505 505 if file_:
506 506 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
507 507 file_)
508 508 revs = set((int(r) for r in revs))
509 509 def events():
510 510 for r in rlog:
511 511 yield 'n', (r, list(p for p in rlog.parentrevs(r)
512 512 if p != -1))
513 513 if r in revs:
514 514 yield 'l', (r, "r%i" % r)
515 515 elif repo:
516 516 cl = repo.changelog
517 517 tags = opts.get(r'tags')
518 518 branches = opts.get(r'branches')
519 519 if tags:
520 520 labels = {}
521 521 for l, n in repo.tags().items():
522 522 labels.setdefault(cl.rev(n), []).append(l)
523 523 def events():
524 524 b = "default"
525 525 for r in cl:
526 526 if branches:
527 527 newb = cl.read(cl.node(r))[5]['branch']
528 528 if newb != b:
529 529 yield 'a', newb
530 530 b = newb
531 531 yield 'n', (r, list(p for p in cl.parentrevs(r)
532 532 if p != -1))
533 533 if tags:
534 534 ls = labels.get(r)
535 535 if ls:
536 536 for l in ls:
537 537 yield 'l', (r, l)
538 538 else:
539 539 raise error.Abort(_('need repo for changelog dag'))
540 540
541 541 for line in dagparser.dagtextlines(events(),
542 542 addspaces=spaces,
543 543 wraplabels=True,
544 544 wrapannotations=True,
545 545 wrapnonlinear=dots,
546 546 usedots=dots,
547 547 maxlinewidth=70):
548 548 ui.write(line)
549 549 ui.write("\n")
550 550
551 551 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
552 552 def debugdata(ui, repo, file_, rev=None, **opts):
553 553 """dump the contents of a data file revision"""
554 554 opts = pycompat.byteskwargs(opts)
555 555 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
556 556 if rev is not None:
557 557 raise error.CommandError('debugdata', _('invalid arguments'))
558 558 file_, rev = None, file_
559 559 elif rev is None:
560 560 raise error.CommandError('debugdata', _('invalid arguments'))
561 561 r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
562 562 try:
563 563 ui.write(r.revision(r.lookup(rev), raw=True))
564 564 except KeyError:
565 565 raise error.Abort(_('invalid revision identifier %s') % rev)
566 566
567 567 @command('debugdate',
568 568 [('e', 'extended', None, _('try extended date formats'))],
569 569 _('[-e] DATE [RANGE]'),
570 570 norepo=True, optionalrepo=True)
571 571 def debugdate(ui, date, range=None, **opts):
572 572 """parse and display a date"""
573 573 if opts[r"extended"]:
574 574 d = dateutil.parsedate(date, util.extendeddateformats)
575 575 else:
576 576 d = dateutil.parsedate(date)
577 577 ui.write(("internal: %d %d\n") % d)
578 578 ui.write(("standard: %s\n") % dateutil.datestr(d))
579 579 if range:
580 580 m = dateutil.matchdate(range)
581 581 ui.write(("match: %s\n") % m(d[0]))
582 582
583 583 @command('debugdeltachain',
584 584 cmdutil.debugrevlogopts + cmdutil.formatteropts,
585 585 _('-c|-m|FILE'),
586 586 optionalrepo=True)
587 587 def debugdeltachain(ui, repo, file_=None, **opts):
588 588 """dump information about delta chains in a revlog
589 589
590 590 Output can be templatized. Available template keywords are:
591 591
592 592 :``rev``: revision number
593 593 :``chainid``: delta chain identifier (numbered by unique base)
594 594 :``chainlen``: delta chain length to this revision
595 595 :``prevrev``: previous revision in delta chain
596 596 :``deltatype``: role of delta / how it was computed
597 597 :``compsize``: compressed size of revision
598 598 :``uncompsize``: uncompressed size of revision
599 599 :``chainsize``: total size of compressed revisions in chain
600 600 :``chainratio``: total chain size divided by uncompressed revision size
601 601 (new delta chains typically start at ratio 2.00)
602 602 :``lindist``: linear distance from base revision in delta chain to end
603 603 of this revision
604 604 :``extradist``: total size of revisions not part of this delta chain from
605 605 base of delta chain to end of this revision; a measurement
606 606 of how much extra data we need to read/seek across to read
607 607 the delta chain for this revision
608 608 :``extraratio``: extradist divided by chainsize; another representation of
609 609 how much unrelated data is needed to load this delta chain
610 610
611 611 If the repository is configured to use the sparse read, additional keywords
612 612 are available:
613 613
614 614 :``readsize``: total size of data read from the disk for a revision
615 615 (sum of the sizes of all the blocks)
616 616 :``largestblock``: size of the largest block of data read from the disk
617 617 :``readdensity``: density of useful bytes in the data read from the disk
618 618 :``srchunks``: in how many data hunks the whole revision would be read
619 619
620 620 The sparse read can be enabled with experimental.sparse-read = True
621 621 """
622 622 opts = pycompat.byteskwargs(opts)
623 623 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
624 624 index = r.index
625 625 start = r.start
626 626 length = r.length
627 627 generaldelta = r.version & revlog.FLAG_GENERALDELTA
628 628 withsparseread = getattr(r, '_withsparseread', False)
629 629
630 630 def revinfo(rev):
631 631 e = index[rev]
632 632 compsize = e[1]
633 633 uncompsize = e[2]
634 634 chainsize = 0
635 635
636 636 if generaldelta:
637 637 if e[3] == e[5]:
638 638 deltatype = 'p1'
639 639 elif e[3] == e[6]:
640 640 deltatype = 'p2'
641 641 elif e[3] == rev - 1:
642 642 deltatype = 'prev'
643 643 elif e[3] == rev:
644 644 deltatype = 'base'
645 645 else:
646 646 deltatype = 'other'
647 647 else:
648 648 if e[3] == rev:
649 649 deltatype = 'base'
650 650 else:
651 651 deltatype = 'prev'
652 652
653 653 chain = r._deltachain(rev)[0]
654 654 for iterrev in chain:
655 655 e = index[iterrev]
656 656 chainsize += e[1]
657 657
658 658 return compsize, uncompsize, deltatype, chain, chainsize
659 659
660 660 fm = ui.formatter('debugdeltachain', opts)
661 661
662 662 fm.plain(' rev chain# chainlen prev delta '
663 663 'size rawsize chainsize ratio lindist extradist '
664 664 'extraratio')
665 665 if withsparseread:
666 666 fm.plain(' readsize largestblk rddensity srchunks')
667 667 fm.plain('\n')
668 668
669 669 chainbases = {}
670 670 for rev in r:
671 671 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
672 672 chainbase = chain[0]
673 673 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
674 674 basestart = start(chainbase)
675 675 revstart = start(rev)
676 676 lineardist = revstart + comp - basestart
677 677 extradist = lineardist - chainsize
678 678 try:
679 679 prevrev = chain[-2]
680 680 except IndexError:
681 681 prevrev = -1
682 682
683 683 if uncomp != 0:
684 684 chainratio = float(chainsize) / float(uncomp)
685 685 else:
686 686 chainratio = chainsize
687 687
688 688 if chainsize != 0:
689 689 extraratio = float(extradist) / float(chainsize)
690 690 else:
691 691 extraratio = extradist
692 692
693 693 fm.startitem()
694 694 fm.write('rev chainid chainlen prevrev deltatype compsize '
695 695 'uncompsize chainsize chainratio lindist extradist '
696 696 'extraratio',
697 697 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
698 698 rev, chainid, len(chain), prevrev, deltatype, comp,
699 699 uncomp, chainsize, chainratio, lineardist, extradist,
700 700 extraratio,
701 701 rev=rev, chainid=chainid, chainlen=len(chain),
702 702 prevrev=prevrev, deltatype=deltatype, compsize=comp,
703 703 uncompsize=uncomp, chainsize=chainsize,
704 704 chainratio=chainratio, lindist=lineardist,
705 705 extradist=extradist, extraratio=extraratio)
706 706 if withsparseread:
707 707 readsize = 0
708 708 largestblock = 0
709 709 srchunks = 0
710 710
711 711 for revschunk in deltautil.slicechunk(r, chain):
712 712 srchunks += 1
713 713 blkend = start(revschunk[-1]) + length(revschunk[-1])
714 714 blksize = blkend - start(revschunk[0])
715 715
716 716 readsize += blksize
717 717 if largestblock < blksize:
718 718 largestblock = blksize
719 719
720 720 if readsize:
721 721 readdensity = float(chainsize) / float(readsize)
722 722 else:
723 723 readdensity = 1
724 724
725 725 fm.write('readsize largestblock readdensity srchunks',
726 726 ' %10d %10d %9.5f %8d',
727 727 readsize, largestblock, readdensity, srchunks,
728 728 readsize=readsize, largestblock=largestblock,
729 729 readdensity=readdensity, srchunks=srchunks)
730 730
731 731 fm.plain('\n')
732 732
733 733 fm.end()
734 734
735 735 @command('debugdirstate|debugstate',
736 [('', 'nodates', None, _('do not display the saved mtime')),
737 ('', 'datesort', None, _('sort by saved mtime'))],
736 [('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')),
737 ('', 'dates', True, _('display the saved mtime')),
738 ('', 'datesort', None, _('sort by saved mtime'))],
738 739 _('[OPTION]...'))
739 740 def debugstate(ui, repo, **opts):
740 741 """show the contents of the current dirstate"""
741 742
742 nodates = opts.get(r'nodates')
743 nodates = not opts[r'dates']
744 if opts.get(r'nodates') is not None:
745 nodates = True
743 746 datesort = opts.get(r'datesort')
744 747
745 748 timestr = ""
746 749 if datesort:
747 750 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
748 751 else:
749 752 keyfunc = None # sort by filename
750 753 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
751 754 if ent[3] == -1:
752 755 timestr = 'unset '
753 756 elif nodates:
754 757 timestr = 'set '
755 758 else:
756 759 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
757 760 time.localtime(ent[3]))
758 761 timestr = encoding.strtolocal(timestr)
759 762 if ent[1] & 0o20000:
760 763 mode = 'lnk'
761 764 else:
762 765 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
763 766 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
764 767 for f in repo.dirstate.copies():
765 768 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
766 769
767 770 @command('debugdiscovery',
768 771 [('', 'old', None, _('use old-style discovery')),
769 772 ('', 'nonheads', None,
770 773 _('use old-style discovery with non-heads included')),
771 774 ('', 'rev', [], 'restrict discovery to this set of revs'),
772 775 ] + cmdutil.remoteopts,
773 776 _('[--rev REV] [OTHER]'))
774 777 def debugdiscovery(ui, repo, remoteurl="default", **opts):
775 778 """runs the changeset discovery protocol in isolation"""
776 779 opts = pycompat.byteskwargs(opts)
777 780 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
778 781 remote = hg.peer(repo, opts, remoteurl)
779 782 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
780 783
781 784 # make sure tests are repeatable
782 785 random.seed(12323)
783 786
784 787 def doit(pushedrevs, remoteheads, remote=remote):
785 788 if opts.get('old'):
786 789 if not util.safehasattr(remote, 'branches'):
787 790 # enable in-client legacy support
788 791 remote = localrepo.locallegacypeer(remote.local())
789 792 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
790 793 force=True)
791 794 common = set(common)
792 795 if not opts.get('nonheads'):
793 796 ui.write(("unpruned common: %s\n") %
794 797 " ".join(sorted(short(n) for n in common)))
795 798
796 799 clnode = repo.changelog.node
797 800 common = repo.revs('heads(::%ln)', common)
798 801 common = {clnode(r) for r in common}
799 802 else:
800 803 nodes = None
801 804 if pushedrevs:
802 805 revs = scmutil.revrange(repo, pushedrevs)
803 806 nodes = [repo[r].node() for r in revs]
804 807 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
805 808 ancestorsof=nodes)
806 809 common = set(common)
807 810 rheads = set(hds)
808 811 lheads = set(repo.heads())
809 812 ui.write(("common heads: %s\n") %
810 813 " ".join(sorted(short(n) for n in common)))
811 814 if lheads <= common:
812 815 ui.write(("local is subset\n"))
813 816 elif rheads <= common:
814 817 ui.write(("remote is subset\n"))
815 818
816 819 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
817 820 localrevs = opts['rev']
818 821 doit(localrevs, remoterevs)
819 822
820 823 _chunksize = 4 << 10
821 824
822 825 @command('debugdownload',
823 826 [
824 827 ('o', 'output', '', _('path')),
825 828 ],
826 829 optionalrepo=True)
827 830 def debugdownload(ui, repo, url, output=None, **opts):
828 831 """download a resource using Mercurial logic and config
829 832 """
830 833 fh = urlmod.open(ui, url, output)
831 834
832 835 dest = ui
833 836 if output:
834 837 dest = open(output, "wb", _chunksize)
835 838 try:
836 839 data = fh.read(_chunksize)
837 840 while data:
838 841 dest.write(data)
839 842 data = fh.read(_chunksize)
840 843 finally:
841 844 if output:
842 845 dest.close()
843 846
844 847 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
845 848 def debugextensions(ui, repo, **opts):
846 849 '''show information about active extensions'''
847 850 opts = pycompat.byteskwargs(opts)
848 851 exts = extensions.extensions(ui)
849 852 hgver = util.version()
850 853 fm = ui.formatter('debugextensions', opts)
851 854 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
852 855 isinternal = extensions.ismoduleinternal(extmod)
853 856 extsource = pycompat.fsencode(extmod.__file__)
854 857 if isinternal:
855 858 exttestedwith = [] # never expose magic string to users
856 859 else:
857 860 exttestedwith = getattr(extmod, 'testedwith', '').split()
858 861 extbuglink = getattr(extmod, 'buglink', None)
859 862
860 863 fm.startitem()
861 864
862 865 if ui.quiet or ui.verbose:
863 866 fm.write('name', '%s\n', extname)
864 867 else:
865 868 fm.write('name', '%s', extname)
866 869 if isinternal or hgver in exttestedwith:
867 870 fm.plain('\n')
868 871 elif not exttestedwith:
869 872 fm.plain(_(' (untested!)\n'))
870 873 else:
871 874 lasttestedversion = exttestedwith[-1]
872 875 fm.plain(' (%s!)\n' % lasttestedversion)
873 876
874 877 fm.condwrite(ui.verbose and extsource, 'source',
875 878 _(' location: %s\n'), extsource or "")
876 879
877 880 if ui.verbose:
878 881 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
879 882 fm.data(bundled=isinternal)
880 883
881 884 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
882 885 _(' tested with: %s\n'),
883 886 fm.formatlist(exttestedwith, name='ver'))
884 887
885 888 fm.condwrite(ui.verbose and extbuglink, 'buglink',
886 889 _(' bug reporting: %s\n'), extbuglink or "")
887 890
888 891 fm.end()
889 892
890 893 @command('debugfileset',
891 894 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
892 895 ('', 'all-files', False,
893 896 _('test files from all revisions and working directory')),
894 897 ('s', 'show-matcher', None,
895 898 _('print internal representation of matcher')),
896 899 ('p', 'show-stage', [],
897 900 _('print parsed tree at the given stage'), _('NAME'))],
898 901 _('[-r REV] [--all-files] [OPTION]... FILESPEC'))
899 902 def debugfileset(ui, repo, expr, **opts):
900 903 '''parse and apply a fileset specification'''
901 904 from . import fileset
902 905 fileset.symbols # force import of fileset so we have predicates to optimize
903 906 opts = pycompat.byteskwargs(opts)
904 907 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
905 908
906 909 stages = [
907 910 ('parsed', pycompat.identity),
908 911 ('analyzed', filesetlang.analyze),
909 912 ('optimized', filesetlang.optimize),
910 913 ]
911 914 stagenames = set(n for n, f in stages)
912 915
913 916 showalways = set()
914 917 if ui.verbose and not opts['show_stage']:
915 918 # show parsed tree by --verbose (deprecated)
916 919 showalways.add('parsed')
917 920 if opts['show_stage'] == ['all']:
918 921 showalways.update(stagenames)
919 922 else:
920 923 for n in opts['show_stage']:
921 924 if n not in stagenames:
922 925 raise error.Abort(_('invalid stage name: %s') % n)
923 926 showalways.update(opts['show_stage'])
924 927
925 928 tree = filesetlang.parse(expr)
926 929 for n, f in stages:
927 930 tree = f(tree)
928 931 if n in showalways:
929 932 if opts['show_stage'] or n != 'parsed':
930 933 ui.write(("* %s:\n") % n)
931 934 ui.write(filesetlang.prettyformat(tree), "\n")
932 935
933 936 files = set()
934 937 if opts['all_files']:
935 938 for r in repo:
936 939 c = repo[r]
937 940 files.update(c.files())
938 941 files.update(c.substate)
939 942 if opts['all_files'] or ctx.rev() is None:
940 943 wctx = repo[None]
941 944 files.update(repo.dirstate.walk(scmutil.matchall(repo),
942 945 subrepos=list(wctx.substate),
943 946 unknown=True, ignored=True))
944 947 files.update(wctx.substate)
945 948 else:
946 949 files.update(ctx.files())
947 950 files.update(ctx.substate)
948 951
949 952 m = ctx.matchfileset(expr)
950 953 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
951 954 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
952 955 for f in sorted(files):
953 956 if not m(f):
954 957 continue
955 958 ui.write("%s\n" % f)
956 959
957 960 @command('debugformat',
958 961 [] + cmdutil.formatteropts)
959 962 def debugformat(ui, repo, **opts):
960 963 """display format information about the current repository
961 964
962 965 Use --verbose to get extra information about current config value and
963 966 Mercurial default."""
964 967 opts = pycompat.byteskwargs(opts)
965 968 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
966 969 maxvariantlength = max(len('format-variant'), maxvariantlength)
967 970
968 971 def makeformatname(name):
969 972 return '%s:' + (' ' * (maxvariantlength - len(name)))
970 973
971 974 fm = ui.formatter('debugformat', opts)
972 975 if fm.isplain():
973 976 def formatvalue(value):
974 977 if util.safehasattr(value, 'startswith'):
975 978 return value
976 979 if value:
977 980 return 'yes'
978 981 else:
979 982 return 'no'
980 983 else:
981 984 formatvalue = pycompat.identity
982 985
983 986 fm.plain('format-variant')
984 987 fm.plain(' ' * (maxvariantlength - len('format-variant')))
985 988 fm.plain(' repo')
986 989 if ui.verbose:
987 990 fm.plain(' config default')
988 991 fm.plain('\n')
989 992 for fv in upgrade.allformatvariant:
990 993 fm.startitem()
991 994 repovalue = fv.fromrepo(repo)
992 995 configvalue = fv.fromconfig(repo)
993 996
994 997 if repovalue != configvalue:
995 998 namelabel = 'formatvariant.name.mismatchconfig'
996 999 repolabel = 'formatvariant.repo.mismatchconfig'
997 1000 elif repovalue != fv.default:
998 1001 namelabel = 'formatvariant.name.mismatchdefault'
999 1002 repolabel = 'formatvariant.repo.mismatchdefault'
1000 1003 else:
1001 1004 namelabel = 'formatvariant.name.uptodate'
1002 1005 repolabel = 'formatvariant.repo.uptodate'
1003 1006
1004 1007 fm.write('name', makeformatname(fv.name), fv.name,
1005 1008 label=namelabel)
1006 1009 fm.write('repo', ' %3s', formatvalue(repovalue),
1007 1010 label=repolabel)
1008 1011 if fv.default != configvalue:
1009 1012 configlabel = 'formatvariant.config.special'
1010 1013 else:
1011 1014 configlabel = 'formatvariant.config.default'
1012 1015 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
1013 1016 label=configlabel)
1014 1017 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
1015 1018 label='formatvariant.default')
1016 1019 fm.plain('\n')
1017 1020 fm.end()
1018 1021
1019 1022 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1020 1023 def debugfsinfo(ui, path="."):
1021 1024 """show information detected about current filesystem"""
1022 1025 ui.write(('path: %s\n') % path)
1023 1026 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
1024 1027 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1025 1028 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
1026 1029 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1027 1030 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1028 1031 casesensitive = '(unknown)'
1029 1032 try:
1030 1033 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
1031 1034 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
1032 1035 except OSError:
1033 1036 pass
1034 1037 ui.write(('case-sensitive: %s\n') % casesensitive)
1035 1038
1036 1039 @command('debuggetbundle',
1037 1040 [('H', 'head', [], _('id of head node'), _('ID')),
1038 1041 ('C', 'common', [], _('id of common node'), _('ID')),
1039 1042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1040 1043 _('REPO FILE [-H|-C ID]...'),
1041 1044 norepo=True)
1042 1045 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1043 1046 """retrieves a bundle from a repo
1044 1047
1045 1048 Every ID must be a full-length hex node id string. Saves the bundle to the
1046 1049 given file.
1047 1050 """
1048 1051 opts = pycompat.byteskwargs(opts)
1049 1052 repo = hg.peer(ui, opts, repopath)
1050 1053 if not repo.capable('getbundle'):
1051 1054 raise error.Abort("getbundle() not supported by target repository")
1052 1055 args = {}
1053 1056 if common:
1054 1057 args[r'common'] = [bin(s) for s in common]
1055 1058 if head:
1056 1059 args[r'heads'] = [bin(s) for s in head]
1057 1060 # TODO: get desired bundlecaps from command line.
1058 1061 args[r'bundlecaps'] = None
1059 1062 bundle = repo.getbundle('debug', **args)
1060 1063
1061 1064 bundletype = opts.get('type', 'bzip2').lower()
1062 1065 btypes = {'none': 'HG10UN',
1063 1066 'bzip2': 'HG10BZ',
1064 1067 'gzip': 'HG10GZ',
1065 1068 'bundle2': 'HG20'}
1066 1069 bundletype = btypes.get(bundletype)
1067 1070 if bundletype not in bundle2.bundletypes:
1068 1071 raise error.Abort(_('unknown bundle type specified with --type'))
1069 1072 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1070 1073
1071 1074 @command('debugignore', [], '[FILE]')
1072 1075 def debugignore(ui, repo, *files, **opts):
1073 1076 """display the combined ignore pattern and information about ignored files
1074 1077
1075 1078 With no argument display the combined ignore pattern.
1076 1079
1077 1080 Given space separated file names, shows if the given file is ignored and
1078 1081 if so, show the ignore rule (file and line number) that matched it.
1079 1082 """
1080 1083 ignore = repo.dirstate._ignore
1081 1084 if not files:
1082 1085 # Show all the patterns
1083 1086 ui.write("%s\n" % pycompat.byterepr(ignore))
1084 1087 else:
1085 1088 m = scmutil.match(repo[None], pats=files)
1086 1089 for f in m.files():
1087 1090 nf = util.normpath(f)
1088 1091 ignored = None
1089 1092 ignoredata = None
1090 1093 if nf != '.':
1091 1094 if ignore(nf):
1092 1095 ignored = nf
1093 1096 ignoredata = repo.dirstate._ignorefileandline(nf)
1094 1097 else:
1095 1098 for p in util.finddirs(nf):
1096 1099 if ignore(p):
1097 1100 ignored = p
1098 1101 ignoredata = repo.dirstate._ignorefileandline(p)
1099 1102 break
1100 1103 if ignored:
1101 1104 if ignored == nf:
1102 1105 ui.write(_("%s is ignored\n") % m.uipath(f))
1103 1106 else:
1104 1107 ui.write(_("%s is ignored because of "
1105 1108 "containing folder %s\n")
1106 1109 % (m.uipath(f), ignored))
1107 1110 ignorefile, lineno, line = ignoredata
1108 1111 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1109 1112 % (ignorefile, lineno, line))
1110 1113 else:
1111 1114 ui.write(_("%s is not ignored\n") % m.uipath(f))
1112 1115
1113 1116 @command('debugindex', cmdutil.debugrevlogopts + cmdutil.formatteropts,
1114 1117 _('-c|-m|FILE'))
1115 1118 def debugindex(ui, repo, file_=None, **opts):
1116 1119 """dump index data for a storage primitive"""
1117 1120 opts = pycompat.byteskwargs(opts)
1118 1121 store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
1119 1122
1120 1123 if ui.debugflag:
1121 1124 shortfn = hex
1122 1125 else:
1123 1126 shortfn = short
1124 1127
1125 1128 idlen = 12
1126 1129 for i in store:
1127 1130 idlen = len(shortfn(store.node(i)))
1128 1131 break
1129 1132
1130 1133 fm = ui.formatter('debugindex', opts)
1131 1134 fm.plain(b' rev linkrev %s %s p2\n' % (
1132 1135 b'nodeid'.ljust(idlen),
1133 1136 b'p1'.ljust(idlen)))
1134 1137
1135 1138 for rev in store:
1136 1139 node = store.node(rev)
1137 1140 parents = store.parents(node)
1138 1141
1139 1142 fm.startitem()
1140 1143 fm.write(b'rev', b'%6d ', rev)
1141 1144 fm.write(b'linkrev', '%7d ', store.linkrev(rev))
1142 1145 fm.write(b'node', '%s ', shortfn(node))
1143 1146 fm.write(b'p1', '%s ', shortfn(parents[0]))
1144 1147 fm.write(b'p2', '%s', shortfn(parents[1]))
1145 1148 fm.plain(b'\n')
1146 1149
1147 1150 fm.end()
1148 1151
1149 1152 @command('debugindexdot', cmdutil.debugrevlogopts,
1150 1153 _('-c|-m|FILE'), optionalrepo=True)
1151 1154 def debugindexdot(ui, repo, file_=None, **opts):
1152 1155 """dump an index DAG as a graphviz dot file"""
1153 1156 opts = pycompat.byteskwargs(opts)
1154 1157 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
1155 1158 ui.write(("digraph G {\n"))
1156 1159 for i in r:
1157 1160 node = r.node(i)
1158 1161 pp = r.parents(node)
1159 1162 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1160 1163 if pp[1] != nullid:
1161 1164 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1162 1165 ui.write("}\n")
1163 1166
1164 1167 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1165 1168 def debuginstall(ui, **opts):
1166 1169 '''test Mercurial installation
1167 1170
1168 1171 Returns 0 on success.
1169 1172 '''
1170 1173 opts = pycompat.byteskwargs(opts)
1171 1174
1172 1175 def writetemp(contents):
1173 1176 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
1174 1177 f = os.fdopen(fd, r"wb")
1175 1178 f.write(contents)
1176 1179 f.close()
1177 1180 return name
1178 1181
1179 1182 problems = 0
1180 1183
1181 1184 fm = ui.formatter('debuginstall', opts)
1182 1185 fm.startitem()
1183 1186
1184 1187 # encoding
1185 1188 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1186 1189 err = None
1187 1190 try:
1188 1191 codecs.lookup(pycompat.sysstr(encoding.encoding))
1189 1192 except LookupError as inst:
1190 1193 err = stringutil.forcebytestr(inst)
1191 1194 problems += 1
1192 1195 fm.condwrite(err, 'encodingerror', _(" %s\n"
1193 1196 " (check that your locale is properly set)\n"), err)
1194 1197
1195 1198 # Python
1196 1199 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1197 1200 pycompat.sysexecutable)
1198 1201 fm.write('pythonver', _("checking Python version (%s)\n"),
1199 1202 ("%d.%d.%d" % sys.version_info[:3]))
1200 1203 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1201 1204 os.path.dirname(pycompat.fsencode(os.__file__)))
1202 1205
1203 1206 security = set(sslutil.supportedprotocols)
1204 1207 if sslutil.hassni:
1205 1208 security.add('sni')
1206 1209
1207 1210 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1208 1211 fm.formatlist(sorted(security), name='protocol',
1209 1212 fmt='%s', sep=','))
1210 1213
1211 1214 # These are warnings, not errors. So don't increment problem count. This
1212 1215 # may change in the future.
1213 1216 if 'tls1.2' not in security:
1214 1217 fm.plain(_(' TLS 1.2 not supported by Python install; '
1215 1218 'network connections lack modern security\n'))
1216 1219 if 'sni' not in security:
1217 1220 fm.plain(_(' SNI not supported by Python install; may have '
1218 1221 'connectivity issues with some servers\n'))
1219 1222
1220 1223 # TODO print CA cert info
1221 1224
1222 1225 # hg version
1223 1226 hgver = util.version()
1224 1227 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1225 1228 hgver.split('+')[0])
1226 1229 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1227 1230 '+'.join(hgver.split('+')[1:]))
1228 1231
1229 1232 # compiled modules
1230 1233 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1231 1234 policy.policy)
1232 1235 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1233 1236 os.path.dirname(pycompat.fsencode(__file__)))
1234 1237
1235 1238 if policy.policy in ('c', 'allow'):
1236 1239 err = None
1237 1240 try:
1238 1241 from .cext import (
1239 1242 base85,
1240 1243 bdiff,
1241 1244 mpatch,
1242 1245 osutil,
1243 1246 )
1244 1247 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1245 1248 except Exception as inst:
1246 1249 err = stringutil.forcebytestr(inst)
1247 1250 problems += 1
1248 1251 fm.condwrite(err, 'extensionserror', " %s\n", err)
1249 1252
1250 1253 compengines = util.compengines._engines.values()
1251 1254 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1252 1255 fm.formatlist(sorted(e.name() for e in compengines),
1253 1256 name='compengine', fmt='%s', sep=', '))
1254 1257 fm.write('compenginesavail', _('checking available compression engines '
1255 1258 '(%s)\n'),
1256 1259 fm.formatlist(sorted(e.name() for e in compengines
1257 1260 if e.available()),
1258 1261 name='compengine', fmt='%s', sep=', '))
1259 1262 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1260 1263 fm.write('compenginesserver', _('checking available compression engines '
1261 1264 'for wire protocol (%s)\n'),
1262 1265 fm.formatlist([e.name() for e in wirecompengines
1263 1266 if e.wireprotosupport()],
1264 1267 name='compengine', fmt='%s', sep=', '))
1265 1268 re2 = 'missing'
1266 1269 if util._re2:
1267 1270 re2 = 'available'
1268 1271 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1269 1272 fm.data(re2=bool(util._re2))
1270 1273
1271 1274 # templates
1272 1275 p = templater.templatepaths()
1273 1276 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1274 1277 fm.condwrite(not p, '', _(" no template directories found\n"))
1275 1278 if p:
1276 1279 m = templater.templatepath("map-cmdline.default")
1277 1280 if m:
1278 1281 # template found, check if it is working
1279 1282 err = None
1280 1283 try:
1281 1284 templater.templater.frommapfile(m)
1282 1285 except Exception as inst:
1283 1286 err = stringutil.forcebytestr(inst)
1284 1287 p = None
1285 1288 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1286 1289 else:
1287 1290 p = None
1288 1291 fm.condwrite(p, 'defaulttemplate',
1289 1292 _("checking default template (%s)\n"), m)
1290 1293 fm.condwrite(not m, 'defaulttemplatenotfound',
1291 1294 _(" template '%s' not found\n"), "default")
1292 1295 if not p:
1293 1296 problems += 1
1294 1297 fm.condwrite(not p, '',
1295 1298 _(" (templates seem to have been installed incorrectly)\n"))
1296 1299
1297 1300 # editor
1298 1301 editor = ui.geteditor()
1299 1302 editor = util.expandpath(editor)
1300 1303 editorbin = procutil.shellsplit(editor)[0]
1301 1304 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1302 1305 cmdpath = procutil.findexe(editorbin)
1303 1306 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1304 1307 _(" No commit editor set and can't find %s in PATH\n"
1305 1308 " (specify a commit editor in your configuration"
1306 1309 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1307 1310 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1308 1311 _(" Can't find editor '%s' in PATH\n"
1309 1312 " (specify a commit editor in your configuration"
1310 1313 " file)\n"), not cmdpath and editorbin)
1311 1314 if not cmdpath and editor != 'vi':
1312 1315 problems += 1
1313 1316
1314 1317 # check username
1315 1318 username = None
1316 1319 err = None
1317 1320 try:
1318 1321 username = ui.username()
1319 1322 except error.Abort as e:
1320 1323 err = stringutil.forcebytestr(e)
1321 1324 problems += 1
1322 1325
1323 1326 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1324 1327 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1325 1328 " (specify a username in your configuration file)\n"), err)
1326 1329
1327 1330 fm.condwrite(not problems, '',
1328 1331 _("no problems detected\n"))
1329 1332 if not problems:
1330 1333 fm.data(problems=problems)
1331 1334 fm.condwrite(problems, 'problems',
1332 1335 _("%d problems detected,"
1333 1336 " please check your install!\n"), problems)
1334 1337 fm.end()
1335 1338
1336 1339 return problems
1337 1340
1338 1341 @command('debugknown', [], _('REPO ID...'), norepo=True)
1339 1342 def debugknown(ui, repopath, *ids, **opts):
1340 1343 """test whether node ids are known to a repo
1341 1344
1342 1345 Every ID must be a full-length hex node id string. Returns a list of 0s
1343 1346 and 1s indicating unknown/known.
1344 1347 """
1345 1348 opts = pycompat.byteskwargs(opts)
1346 1349 repo = hg.peer(ui, opts, repopath)
1347 1350 if not repo.capable('known'):
1348 1351 raise error.Abort("known() not supported by target repository")
1349 1352 flags = repo.known([bin(s) for s in ids])
1350 1353 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1351 1354
1352 1355 @command('debuglabelcomplete', [], _('LABEL...'))
1353 1356 def debuglabelcomplete(ui, repo, *args):
1354 1357 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1355 1358 debugnamecomplete(ui, repo, *args)
1356 1359
1357 1360 @command('debuglocks',
1358 1361 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1359 1362 ('W', 'force-wlock', None,
1360 1363 _('free the working state lock (DANGEROUS)')),
1361 1364 ('s', 'set-lock', None, _('set the store lock until stopped')),
1362 1365 ('S', 'set-wlock', None,
1363 1366 _('set the working state lock until stopped'))],
1364 1367 _('[OPTION]...'))
1365 1368 def debuglocks(ui, repo, **opts):
1366 1369 """show or modify state of locks
1367 1370
1368 1371 By default, this command will show which locks are held. This
1369 1372 includes the user and process holding the lock, the amount of time
1370 1373 the lock has been held, and the machine name where the process is
1371 1374 running if it's not local.
1372 1375
1373 1376 Locks protect the integrity of Mercurial's data, so should be
1374 1377 treated with care. System crashes or other interruptions may cause
1375 1378 locks to not be properly released, though Mercurial will usually
1376 1379 detect and remove such stale locks automatically.
1377 1380
1378 1381 However, detecting stale locks may not always be possible (for
1379 1382 instance, on a shared filesystem). Removing locks may also be
1380 1383 blocked by filesystem permissions.
1381 1384
1382 1385 Setting a lock will prevent other commands from changing the data.
1383 1386 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1384 1387 The set locks are removed when the command exits.
1385 1388
1386 1389 Returns 0 if no locks are held.
1387 1390
1388 1391 """
1389 1392
1390 1393 if opts.get(r'force_lock'):
1391 1394 repo.svfs.unlink('lock')
1392 1395 if opts.get(r'force_wlock'):
1393 1396 repo.vfs.unlink('wlock')
1394 1397 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1395 1398 return 0
1396 1399
1397 1400 locks = []
1398 1401 try:
1399 1402 if opts.get(r'set_wlock'):
1400 1403 try:
1401 1404 locks.append(repo.wlock(False))
1402 1405 except error.LockHeld:
1403 1406 raise error.Abort(_('wlock is already held'))
1404 1407 if opts.get(r'set_lock'):
1405 1408 try:
1406 1409 locks.append(repo.lock(False))
1407 1410 except error.LockHeld:
1408 1411 raise error.Abort(_('lock is already held'))
1409 1412 if len(locks):
1410 1413 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1411 1414 return 0
1412 1415 finally:
1413 1416 release(*locks)
1414 1417
1415 1418 now = time.time()
1416 1419 held = 0
1417 1420
1418 1421 def report(vfs, name, method):
1419 1422 # this causes stale locks to get reaped for more accurate reporting
1420 1423 try:
1421 1424 l = method(False)
1422 1425 except error.LockHeld:
1423 1426 l = None
1424 1427
1425 1428 if l:
1426 1429 l.release()
1427 1430 else:
1428 1431 try:
1429 1432 st = vfs.lstat(name)
1430 1433 age = now - st[stat.ST_MTIME]
1431 1434 user = util.username(st.st_uid)
1432 1435 locker = vfs.readlock(name)
1433 1436 if ":" in locker:
1434 1437 host, pid = locker.split(':')
1435 1438 if host == socket.gethostname():
1436 1439 locker = 'user %s, process %s' % (user, pid)
1437 1440 else:
1438 1441 locker = 'user %s, process %s, host %s' \
1439 1442 % (user, pid, host)
1440 1443 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1441 1444 return 1
1442 1445 except OSError as e:
1443 1446 if e.errno != errno.ENOENT:
1444 1447 raise
1445 1448
1446 1449 ui.write(("%-6s free\n") % (name + ":"))
1447 1450 return 0
1448 1451
1449 1452 held += report(repo.svfs, "lock", repo.lock)
1450 1453 held += report(repo.vfs, "wlock", repo.wlock)
1451 1454
1452 1455 return held
1453 1456
1454 1457 @command('debugmanifestfulltextcache', [
1455 1458 ('', 'clear', False, _('clear the cache')),
1456 1459 ('a', 'add', '', _('add the given manifest node to the cache'),
1457 1460 _('NODE'))
1458 1461 ], '')
1459 1462 def debugmanifestfulltextcache(ui, repo, add=None, **opts):
1460 1463 """show, clear or amend the contents of the manifest fulltext cache"""
1461 1464 with repo.lock():
1462 1465 r = repo.manifestlog.getstorage(b'')
1463 1466 try:
1464 1467 cache = r._fulltextcache
1465 1468 except AttributeError:
1466 1469 ui.warn(_(
1467 1470 "Current revlog implementation doesn't appear to have a "
1468 1471 'manifest fulltext cache\n'))
1469 1472 return
1470 1473
1471 1474 if opts.get(r'clear'):
1472 1475 cache.clear()
1473 1476
1474 1477 if add:
1475 1478 try:
1476 1479 manifest = repo.manifestlog[r.lookup(add)]
1477 1480 except error.LookupError as e:
1478 1481 raise error.Abort(e, hint="Check your manifest node id")
1479 1482 manifest.read() # stores revisision in cache too
1480 1483
1481 1484 if not len(cache):
1482 1485 ui.write(_('Cache empty'))
1483 1486 else:
1484 1487 ui.write(
1485 1488 _('Cache contains %d manifest entries, in order of most to '
1486 1489 'least recent:\n') % (len(cache),))
1487 1490 totalsize = 0
1488 1491 for nodeid in cache:
1489 1492 # Use cache.get to not update the LRU order
1490 1493 data = cache.get(nodeid)
1491 1494 size = len(data)
1492 1495 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1493 1496 ui.write(_('id: %s, size %s\n') % (
1494 1497 hex(nodeid), util.bytecount(size)))
1495 1498 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1496 1499 ui.write(
1497 1500 _('Total cache data size %s, on-disk %s\n') % (
1498 1501 util.bytecount(totalsize), util.bytecount(ondisk))
1499 1502 )
1500 1503
1501 1504 @command('debugmergestate', [], '')
1502 1505 def debugmergestate(ui, repo, *args):
1503 1506 """print merge state
1504 1507
1505 1508 Use --verbose to print out information about whether v1 or v2 merge state
1506 1509 was chosen."""
1507 1510 def _hashornull(h):
1508 1511 if h == nullhex:
1509 1512 return 'null'
1510 1513 else:
1511 1514 return h
1512 1515
1513 1516 def printrecords(version):
1514 1517 ui.write(('* version %d records\n') % version)
1515 1518 if version == 1:
1516 1519 records = v1records
1517 1520 else:
1518 1521 records = v2records
1519 1522
1520 1523 for rtype, record in records:
1521 1524 # pretty print some record types
1522 1525 if rtype == 'L':
1523 1526 ui.write(('local: %s\n') % record)
1524 1527 elif rtype == 'O':
1525 1528 ui.write(('other: %s\n') % record)
1526 1529 elif rtype == 'm':
1527 1530 driver, mdstate = record.split('\0', 1)
1528 1531 ui.write(('merge driver: %s (state "%s")\n')
1529 1532 % (driver, mdstate))
1530 1533 elif rtype in 'FDC':
1531 1534 r = record.split('\0')
1532 1535 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1533 1536 if version == 1:
1534 1537 onode = 'not stored in v1 format'
1535 1538 flags = r[7]
1536 1539 else:
1537 1540 onode, flags = r[7:9]
1538 1541 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1539 1542 % (f, rtype, state, _hashornull(hash)))
1540 1543 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1541 1544 ui.write((' ancestor path: %s (node %s)\n')
1542 1545 % (afile, _hashornull(anode)))
1543 1546 ui.write((' other path: %s (node %s)\n')
1544 1547 % (ofile, _hashornull(onode)))
1545 1548 elif rtype == 'f':
1546 1549 filename, rawextras = record.split('\0', 1)
1547 1550 extras = rawextras.split('\0')
1548 1551 i = 0
1549 1552 extrastrings = []
1550 1553 while i < len(extras):
1551 1554 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1552 1555 i += 2
1553 1556
1554 1557 ui.write(('file extras: %s (%s)\n')
1555 1558 % (filename, ', '.join(extrastrings)))
1556 1559 elif rtype == 'l':
1557 1560 labels = record.split('\0', 2)
1558 1561 labels = [l for l in labels if len(l) > 0]
1559 1562 ui.write(('labels:\n'))
1560 1563 ui.write((' local: %s\n' % labels[0]))
1561 1564 ui.write((' other: %s\n' % labels[1]))
1562 1565 if len(labels) > 2:
1563 1566 ui.write((' base: %s\n' % labels[2]))
1564 1567 else:
1565 1568 ui.write(('unrecognized entry: %s\t%s\n')
1566 1569 % (rtype, record.replace('\0', '\t')))
1567 1570
1568 1571 # Avoid mergestate.read() since it may raise an exception for unsupported
1569 1572 # merge state records. We shouldn't be doing this, but this is OK since this
1570 1573 # command is pretty low-level.
1571 1574 ms = mergemod.mergestate(repo)
1572 1575
1573 1576 # sort so that reasonable information is on top
1574 1577 v1records = ms._readrecordsv1()
1575 1578 v2records = ms._readrecordsv2()
1576 1579 order = 'LOml'
1577 1580 def key(r):
1578 1581 idx = order.find(r[0])
1579 1582 if idx == -1:
1580 1583 return (1, r[1])
1581 1584 else:
1582 1585 return (0, idx)
1583 1586 v1records.sort(key=key)
1584 1587 v2records.sort(key=key)
1585 1588
1586 1589 if not v1records and not v2records:
1587 1590 ui.write(('no merge state found\n'))
1588 1591 elif not v2records:
1589 1592 ui.note(('no version 2 merge state\n'))
1590 1593 printrecords(1)
1591 1594 elif ms._v1v2match(v1records, v2records):
1592 1595 ui.note(('v1 and v2 states match: using v2\n'))
1593 1596 printrecords(2)
1594 1597 else:
1595 1598 ui.note(('v1 and v2 states mismatch: using v1\n'))
1596 1599 printrecords(1)
1597 1600 if ui.verbose:
1598 1601 printrecords(2)
1599 1602
1600 1603 @command('debugnamecomplete', [], _('NAME...'))
1601 1604 def debugnamecomplete(ui, repo, *args):
1602 1605 '''complete "names" - tags, open branch names, bookmark names'''
1603 1606
1604 1607 names = set()
1605 1608 # since we previously only listed open branches, we will handle that
1606 1609 # specially (after this for loop)
1607 1610 for name, ns in repo.names.iteritems():
1608 1611 if name != 'branches':
1609 1612 names.update(ns.listnames(repo))
1610 1613 names.update(tag for (tag, heads, tip, closed)
1611 1614 in repo.branchmap().iterbranches() if not closed)
1612 1615 completions = set()
1613 1616 if not args:
1614 1617 args = ['']
1615 1618 for a in args:
1616 1619 completions.update(n for n in names if n.startswith(a))
1617 1620 ui.write('\n'.join(sorted(completions)))
1618 1621 ui.write('\n')
1619 1622
1620 1623 @command('debugobsolete',
1621 1624 [('', 'flags', 0, _('markers flag')),
1622 1625 ('', 'record-parents', False,
1623 1626 _('record parent information for the precursor')),
1624 1627 ('r', 'rev', [], _('display markers relevant to REV')),
1625 1628 ('', 'exclusive', False, _('restrict display to markers only '
1626 1629 'relevant to REV')),
1627 1630 ('', 'index', False, _('display index of the marker')),
1628 1631 ('', 'delete', [], _('delete markers specified by indices')),
1629 1632 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1630 1633 _('[OBSOLETED [REPLACEMENT ...]]'))
1631 1634 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1632 1635 """create arbitrary obsolete marker
1633 1636
1634 1637 With no arguments, displays the list of obsolescence markers."""
1635 1638
1636 1639 opts = pycompat.byteskwargs(opts)
1637 1640
1638 1641 def parsenodeid(s):
1639 1642 try:
1640 1643 # We do not use revsingle/revrange functions here to accept
1641 1644 # arbitrary node identifiers, possibly not present in the
1642 1645 # local repository.
1643 1646 n = bin(s)
1644 1647 if len(n) != len(nullid):
1645 1648 raise TypeError()
1646 1649 return n
1647 1650 except TypeError:
1648 1651 raise error.Abort('changeset references must be full hexadecimal '
1649 1652 'node identifiers')
1650 1653
1651 1654 if opts.get('delete'):
1652 1655 indices = []
1653 1656 for v in opts.get('delete'):
1654 1657 try:
1655 1658 indices.append(int(v))
1656 1659 except ValueError:
1657 1660 raise error.Abort(_('invalid index value: %r') % v,
1658 1661 hint=_('use integers for indices'))
1659 1662
1660 1663 if repo.currenttransaction():
1661 1664 raise error.Abort(_('cannot delete obsmarkers in the middle '
1662 1665 'of transaction.'))
1663 1666
1664 1667 with repo.lock():
1665 1668 n = repair.deleteobsmarkers(repo.obsstore, indices)
1666 1669 ui.write(_('deleted %i obsolescence markers\n') % n)
1667 1670
1668 1671 return
1669 1672
1670 1673 if precursor is not None:
1671 1674 if opts['rev']:
1672 1675 raise error.Abort('cannot select revision when creating marker')
1673 1676 metadata = {}
1674 1677 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
1675 1678 succs = tuple(parsenodeid(succ) for succ in successors)
1676 1679 l = repo.lock()
1677 1680 try:
1678 1681 tr = repo.transaction('debugobsolete')
1679 1682 try:
1680 1683 date = opts.get('date')
1681 1684 if date:
1682 1685 date = dateutil.parsedate(date)
1683 1686 else:
1684 1687 date = None
1685 1688 prec = parsenodeid(precursor)
1686 1689 parents = None
1687 1690 if opts['record_parents']:
1688 1691 if prec not in repo.unfiltered():
1689 1692 raise error.Abort('cannot used --record-parents on '
1690 1693 'unknown changesets')
1691 1694 parents = repo.unfiltered()[prec].parents()
1692 1695 parents = tuple(p.node() for p in parents)
1693 1696 repo.obsstore.create(tr, prec, succs, opts['flags'],
1694 1697 parents=parents, date=date,
1695 1698 metadata=metadata, ui=ui)
1696 1699 tr.close()
1697 1700 except ValueError as exc:
1698 1701 raise error.Abort(_('bad obsmarker input: %s') %
1699 1702 pycompat.bytestr(exc))
1700 1703 finally:
1701 1704 tr.release()
1702 1705 finally:
1703 1706 l.release()
1704 1707 else:
1705 1708 if opts['rev']:
1706 1709 revs = scmutil.revrange(repo, opts['rev'])
1707 1710 nodes = [repo[r].node() for r in revs]
1708 1711 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1709 1712 exclusive=opts['exclusive']))
1710 1713 markers.sort(key=lambda x: x._data)
1711 1714 else:
1712 1715 markers = obsutil.getmarkers(repo)
1713 1716
1714 1717 markerstoiter = markers
1715 1718 isrelevant = lambda m: True
1716 1719 if opts.get('rev') and opts.get('index'):
1717 1720 markerstoiter = obsutil.getmarkers(repo)
1718 1721 markerset = set(markers)
1719 1722 isrelevant = lambda m: m in markerset
1720 1723
1721 1724 fm = ui.formatter('debugobsolete', opts)
1722 1725 for i, m in enumerate(markerstoiter):
1723 1726 if not isrelevant(m):
1724 1727 # marker can be irrelevant when we're iterating over a set
1725 1728 # of markers (markerstoiter) which is bigger than the set
1726 1729 # of markers we want to display (markers)
1727 1730 # this can happen if both --index and --rev options are
1728 1731 # provided and thus we need to iterate over all of the markers
1729 1732 # to get the correct indices, but only display the ones that
1730 1733 # are relevant to --rev value
1731 1734 continue
1732 1735 fm.startitem()
1733 1736 ind = i if opts.get('index') else None
1734 1737 cmdutil.showmarker(fm, m, index=ind)
1735 1738 fm.end()
1736 1739
1737 1740 @command('debugpathcomplete',
1738 1741 [('f', 'full', None, _('complete an entire path')),
1739 1742 ('n', 'normal', None, _('show only normal files')),
1740 1743 ('a', 'added', None, _('show only added files')),
1741 1744 ('r', 'removed', None, _('show only removed files'))],
1742 1745 _('FILESPEC...'))
1743 1746 def debugpathcomplete(ui, repo, *specs, **opts):
1744 1747 '''complete part or all of a tracked path
1745 1748
1746 1749 This command supports shells that offer path name completion. It
1747 1750 currently completes only files already known to the dirstate.
1748 1751
1749 1752 Completion extends only to the next path segment unless
1750 1753 --full is specified, in which case entire paths are used.'''
1751 1754
1752 1755 def complete(path, acceptable):
1753 1756 dirstate = repo.dirstate
1754 1757 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1755 1758 rootdir = repo.root + pycompat.ossep
1756 1759 if spec != repo.root and not spec.startswith(rootdir):
1757 1760 return [], []
1758 1761 if os.path.isdir(spec):
1759 1762 spec += '/'
1760 1763 spec = spec[len(rootdir):]
1761 1764 fixpaths = pycompat.ossep != '/'
1762 1765 if fixpaths:
1763 1766 spec = spec.replace(pycompat.ossep, '/')
1764 1767 speclen = len(spec)
1765 1768 fullpaths = opts[r'full']
1766 1769 files, dirs = set(), set()
1767 1770 adddir, addfile = dirs.add, files.add
1768 1771 for f, st in dirstate.iteritems():
1769 1772 if f.startswith(spec) and st[0] in acceptable:
1770 1773 if fixpaths:
1771 1774 f = f.replace('/', pycompat.ossep)
1772 1775 if fullpaths:
1773 1776 addfile(f)
1774 1777 continue
1775 1778 s = f.find(pycompat.ossep, speclen)
1776 1779 if s >= 0:
1777 1780 adddir(f[:s])
1778 1781 else:
1779 1782 addfile(f)
1780 1783 return files, dirs
1781 1784
1782 1785 acceptable = ''
1783 1786 if opts[r'normal']:
1784 1787 acceptable += 'nm'
1785 1788 if opts[r'added']:
1786 1789 acceptable += 'a'
1787 1790 if opts[r'removed']:
1788 1791 acceptable += 'r'
1789 1792 cwd = repo.getcwd()
1790 1793 if not specs:
1791 1794 specs = ['.']
1792 1795
1793 1796 files, dirs = set(), set()
1794 1797 for spec in specs:
1795 1798 f, d = complete(spec, acceptable or 'nmar')
1796 1799 files.update(f)
1797 1800 dirs.update(d)
1798 1801 files.update(dirs)
1799 1802 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1800 1803 ui.write('\n')
1801 1804
1802 1805 @command('debugpeer', [], _('PATH'), norepo=True)
1803 1806 def debugpeer(ui, path):
1804 1807 """establish a connection to a peer repository"""
1805 1808 # Always enable peer request logging. Requires --debug to display
1806 1809 # though.
1807 1810 overrides = {
1808 1811 ('devel', 'debug.peer-request'): True,
1809 1812 }
1810 1813
1811 1814 with ui.configoverride(overrides):
1812 1815 peer = hg.peer(ui, {}, path)
1813 1816
1814 1817 local = peer.local() is not None
1815 1818 canpush = peer.canpush()
1816 1819
1817 1820 ui.write(_('url: %s\n') % peer.url())
1818 1821 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1819 1822 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1820 1823
1821 1824 @command('debugpickmergetool',
1822 1825 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1823 1826 ('', 'changedelete', None, _('emulate merging change and delete')),
1824 1827 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1825 1828 _('[PATTERN]...'),
1826 1829 inferrepo=True)
1827 1830 def debugpickmergetool(ui, repo, *pats, **opts):
1828 1831 """examine which merge tool is chosen for specified file
1829 1832
1830 1833 As described in :hg:`help merge-tools`, Mercurial examines
1831 1834 configurations below in this order to decide which merge tool is
1832 1835 chosen for specified file.
1833 1836
1834 1837 1. ``--tool`` option
1835 1838 2. ``HGMERGE`` environment variable
1836 1839 3. configurations in ``merge-patterns`` section
1837 1840 4. configuration of ``ui.merge``
1838 1841 5. configurations in ``merge-tools`` section
1839 1842 6. ``hgmerge`` tool (for historical reason only)
1840 1843 7. default tool for fallback (``:merge`` or ``:prompt``)
1841 1844
1842 1845 This command writes out examination result in the style below::
1843 1846
1844 1847 FILE = MERGETOOL
1845 1848
1846 1849 By default, all files known in the first parent context of the
1847 1850 working directory are examined. Use file patterns and/or -I/-X
1848 1851 options to limit target files. -r/--rev is also useful to examine
1849 1852 files in another context without actual updating to it.
1850 1853
1851 1854 With --debug, this command shows warning messages while matching
1852 1855 against ``merge-patterns`` and so on, too. It is recommended to
1853 1856 use this option with explicit file patterns and/or -I/-X options,
1854 1857 because this option increases amount of output per file according
1855 1858 to configurations in hgrc.
1856 1859
1857 1860 With -v/--verbose, this command shows configurations below at
1858 1861 first (only if specified).
1859 1862
1860 1863 - ``--tool`` option
1861 1864 - ``HGMERGE`` environment variable
1862 1865 - configuration of ``ui.merge``
1863 1866
1864 1867 If merge tool is chosen before matching against
1865 1868 ``merge-patterns``, this command can't show any helpful
1866 1869 information, even with --debug. In such case, information above is
1867 1870 useful to know why a merge tool is chosen.
1868 1871 """
1869 1872 opts = pycompat.byteskwargs(opts)
1870 1873 overrides = {}
1871 1874 if opts['tool']:
1872 1875 overrides[('ui', 'forcemerge')] = opts['tool']
1873 1876 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1874 1877
1875 1878 with ui.configoverride(overrides, 'debugmergepatterns'):
1876 1879 hgmerge = encoding.environ.get("HGMERGE")
1877 1880 if hgmerge is not None:
1878 1881 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1879 1882 uimerge = ui.config("ui", "merge")
1880 1883 if uimerge:
1881 1884 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1882 1885
1883 1886 ctx = scmutil.revsingle(repo, opts.get('rev'))
1884 1887 m = scmutil.match(ctx, pats, opts)
1885 1888 changedelete = opts['changedelete']
1886 1889 for path in ctx.walk(m):
1887 1890 fctx = ctx[path]
1888 1891 try:
1889 1892 if not ui.debugflag:
1890 1893 ui.pushbuffer(error=True)
1891 1894 tool, toolpath = filemerge._picktool(repo, ui, path,
1892 1895 fctx.isbinary(),
1893 1896 'l' in fctx.flags(),
1894 1897 changedelete)
1895 1898 finally:
1896 1899 if not ui.debugflag:
1897 1900 ui.popbuffer()
1898 1901 ui.write(('%s = %s\n') % (path, tool))
1899 1902
1900 1903 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1901 1904 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1902 1905 '''access the pushkey key/value protocol
1903 1906
1904 1907 With two args, list the keys in the given namespace.
1905 1908
1906 1909 With five args, set a key to new if it currently is set to old.
1907 1910 Reports success or failure.
1908 1911 '''
1909 1912
1910 1913 target = hg.peer(ui, {}, repopath)
1911 1914 if keyinfo:
1912 1915 key, old, new = keyinfo
1913 1916 with target.commandexecutor() as e:
1914 1917 r = e.callcommand('pushkey', {
1915 1918 'namespace': namespace,
1916 1919 'key': key,
1917 1920 'old': old,
1918 1921 'new': new,
1919 1922 }).result()
1920 1923
1921 1924 ui.status(pycompat.bytestr(r) + '\n')
1922 1925 return not r
1923 1926 else:
1924 1927 for k, v in sorted(target.listkeys(namespace).iteritems()):
1925 1928 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1926 1929 stringutil.escapestr(v)))
1927 1930
1928 1931 @command('debugpvec', [], _('A B'))
1929 1932 def debugpvec(ui, repo, a, b=None):
1930 1933 ca = scmutil.revsingle(repo, a)
1931 1934 cb = scmutil.revsingle(repo, b)
1932 1935 pa = pvec.ctxpvec(ca)
1933 1936 pb = pvec.ctxpvec(cb)
1934 1937 if pa == pb:
1935 1938 rel = "="
1936 1939 elif pa > pb:
1937 1940 rel = ">"
1938 1941 elif pa < pb:
1939 1942 rel = "<"
1940 1943 elif pa | pb:
1941 1944 rel = "|"
1942 1945 ui.write(_("a: %s\n") % pa)
1943 1946 ui.write(_("b: %s\n") % pb)
1944 1947 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1945 1948 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1946 1949 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1947 1950 pa.distance(pb), rel))
1948 1951
1949 1952 @command('debugrebuilddirstate|debugrebuildstate',
1950 1953 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1951 1954 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1952 1955 'the working copy parent')),
1953 1956 ],
1954 1957 _('[-r REV]'))
1955 1958 def debugrebuilddirstate(ui, repo, rev, **opts):
1956 1959 """rebuild the dirstate as it would look like for the given revision
1957 1960
1958 1961 If no revision is specified the first current parent will be used.
1959 1962
1960 1963 The dirstate will be set to the files of the given revision.
1961 1964 The actual working directory content or existing dirstate
1962 1965 information such as adds or removes is not considered.
1963 1966
1964 1967 ``minimal`` will only rebuild the dirstate status for files that claim to be
1965 1968 tracked but are not in the parent manifest, or that exist in the parent
1966 1969 manifest but are not in the dirstate. It will not change adds, removes, or
1967 1970 modified files that are in the working copy parent.
1968 1971
1969 1972 One use of this command is to make the next :hg:`status` invocation
1970 1973 check the actual file content.
1971 1974 """
1972 1975 ctx = scmutil.revsingle(repo, rev)
1973 1976 with repo.wlock():
1974 1977 dirstate = repo.dirstate
1975 1978 changedfiles = None
1976 1979 # See command doc for what minimal does.
1977 1980 if opts.get(r'minimal'):
1978 1981 manifestfiles = set(ctx.manifest().keys())
1979 1982 dirstatefiles = set(dirstate)
1980 1983 manifestonly = manifestfiles - dirstatefiles
1981 1984 dsonly = dirstatefiles - manifestfiles
1982 1985 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1983 1986 changedfiles = manifestonly | dsnotadded
1984 1987
1985 1988 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1986 1989
1987 1990 @command('debugrebuildfncache', [], '')
1988 1991 def debugrebuildfncache(ui, repo):
1989 1992 """rebuild the fncache file"""
1990 1993 repair.rebuildfncache(ui, repo)
1991 1994
1992 1995 @command('debugrename',
1993 1996 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1994 1997 _('[-r REV] FILE'))
1995 1998 def debugrename(ui, repo, file1, *pats, **opts):
1996 1999 """dump rename information"""
1997 2000
1998 2001 opts = pycompat.byteskwargs(opts)
1999 2002 ctx = scmutil.revsingle(repo, opts.get('rev'))
2000 2003 m = scmutil.match(ctx, (file1,) + pats, opts)
2001 2004 for abs in ctx.walk(m):
2002 2005 fctx = ctx[abs]
2003 2006 o = fctx.filelog().renamed(fctx.filenode())
2004 2007 rel = m.rel(abs)
2005 2008 if o:
2006 2009 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2007 2010 else:
2008 2011 ui.write(_("%s not renamed\n") % rel)
2009 2012
2010 2013 @command('debugrevlog', cmdutil.debugrevlogopts +
2011 2014 [('d', 'dump', False, _('dump index data'))],
2012 2015 _('-c|-m|FILE'),
2013 2016 optionalrepo=True)
2014 2017 def debugrevlog(ui, repo, file_=None, **opts):
2015 2018 """show data and statistics about a revlog"""
2016 2019 opts = pycompat.byteskwargs(opts)
2017 2020 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2018 2021
2019 2022 if opts.get("dump"):
2020 2023 numrevs = len(r)
2021 2024 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2022 2025 " rawsize totalsize compression heads chainlen\n"))
2023 2026 ts = 0
2024 2027 heads = set()
2025 2028
2026 2029 for rev in pycompat.xrange(numrevs):
2027 2030 dbase = r.deltaparent(rev)
2028 2031 if dbase == -1:
2029 2032 dbase = rev
2030 2033 cbase = r.chainbase(rev)
2031 2034 clen = r.chainlen(rev)
2032 2035 p1, p2 = r.parentrevs(rev)
2033 2036 rs = r.rawsize(rev)
2034 2037 ts = ts + rs
2035 2038 heads -= set(r.parentrevs(rev))
2036 2039 heads.add(rev)
2037 2040 try:
2038 2041 compression = ts / r.end(rev)
2039 2042 except ZeroDivisionError:
2040 2043 compression = 0
2041 2044 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2042 2045 "%11d %5d %8d\n" %
2043 2046 (rev, p1, p2, r.start(rev), r.end(rev),
2044 2047 r.start(dbase), r.start(cbase),
2045 2048 r.start(p1), r.start(p2),
2046 2049 rs, ts, compression, len(heads), clen))
2047 2050 return 0
2048 2051
2049 2052 v = r.version
2050 2053 format = v & 0xFFFF
2051 2054 flags = []
2052 2055 gdelta = False
2053 2056 if v & revlog.FLAG_INLINE_DATA:
2054 2057 flags.append('inline')
2055 2058 if v & revlog.FLAG_GENERALDELTA:
2056 2059 gdelta = True
2057 2060 flags.append('generaldelta')
2058 2061 if not flags:
2059 2062 flags = ['(none)']
2060 2063
2061 2064 ### tracks merge vs single parent
2062 2065 nummerges = 0
2063 2066
2064 2067 ### tracks ways the "delta" are build
2065 2068 # nodelta
2066 2069 numempty = 0
2067 2070 numemptytext = 0
2068 2071 numemptydelta = 0
2069 2072 # full file content
2070 2073 numfull = 0
2071 2074 # intermediate snapshot against a prior snapshot
2072 2075 numsemi = 0
2073 2076 # snapshot count per depth
2074 2077 numsnapdepth = collections.defaultdict(lambda: 0)
2075 2078 # delta against previous revision
2076 2079 numprev = 0
2077 2080 # delta against first or second parent (not prev)
2078 2081 nump1 = 0
2079 2082 nump2 = 0
2080 2083 # delta against neither prev nor parents
2081 2084 numother = 0
2082 2085 # delta against prev that are also first or second parent
2083 2086 # (details of `numprev`)
2084 2087 nump1prev = 0
2085 2088 nump2prev = 0
2086 2089
2087 2090 # data about delta chain of each revs
2088 2091 chainlengths = []
2089 2092 chainbases = []
2090 2093 chainspans = []
2091 2094
2092 2095 # data about each revision
2093 2096 datasize = [None, 0, 0]
2094 2097 fullsize = [None, 0, 0]
2095 2098 semisize = [None, 0, 0]
2096 2099 # snapshot count per depth
2097 2100 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2098 2101 deltasize = [None, 0, 0]
2099 2102 chunktypecounts = {}
2100 2103 chunktypesizes = {}
2101 2104
2102 2105 def addsize(size, l):
2103 2106 if l[0] is None or size < l[0]:
2104 2107 l[0] = size
2105 2108 if size > l[1]:
2106 2109 l[1] = size
2107 2110 l[2] += size
2108 2111
2109 2112 numrevs = len(r)
2110 2113 for rev in pycompat.xrange(numrevs):
2111 2114 p1, p2 = r.parentrevs(rev)
2112 2115 delta = r.deltaparent(rev)
2113 2116 if format > 0:
2114 2117 addsize(r.rawsize(rev), datasize)
2115 2118 if p2 != nullrev:
2116 2119 nummerges += 1
2117 2120 size = r.length(rev)
2118 2121 if delta == nullrev:
2119 2122 chainlengths.append(0)
2120 2123 chainbases.append(r.start(rev))
2121 2124 chainspans.append(size)
2122 2125 if size == 0:
2123 2126 numempty += 1
2124 2127 numemptytext += 1
2125 2128 else:
2126 2129 numfull += 1
2127 2130 numsnapdepth[0] += 1
2128 2131 addsize(size, fullsize)
2129 2132 addsize(size, snapsizedepth[0])
2130 2133 else:
2131 2134 chainlengths.append(chainlengths[delta] + 1)
2132 2135 baseaddr = chainbases[delta]
2133 2136 revaddr = r.start(rev)
2134 2137 chainbases.append(baseaddr)
2135 2138 chainspans.append((revaddr - baseaddr) + size)
2136 2139 if size == 0:
2137 2140 numempty += 1
2138 2141 numemptydelta += 1
2139 2142 elif r.issnapshot(rev):
2140 2143 addsize(size, semisize)
2141 2144 numsemi += 1
2142 2145 depth = r.snapshotdepth(rev)
2143 2146 numsnapdepth[depth] += 1
2144 2147 addsize(size, snapsizedepth[depth])
2145 2148 else:
2146 2149 addsize(size, deltasize)
2147 2150 if delta == rev - 1:
2148 2151 numprev += 1
2149 2152 if delta == p1:
2150 2153 nump1prev += 1
2151 2154 elif delta == p2:
2152 2155 nump2prev += 1
2153 2156 elif delta == p1:
2154 2157 nump1 += 1
2155 2158 elif delta == p2:
2156 2159 nump2 += 1
2157 2160 elif delta != nullrev:
2158 2161 numother += 1
2159 2162
2160 2163 # Obtain data on the raw chunks in the revlog.
2161 2164 if util.safehasattr(r, '_getsegmentforrevs'):
2162 2165 segment = r._getsegmentforrevs(rev, rev)[1]
2163 2166 else:
2164 2167 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
2165 2168 if segment:
2166 2169 chunktype = bytes(segment[0:1])
2167 2170 else:
2168 2171 chunktype = 'empty'
2169 2172
2170 2173 if chunktype not in chunktypecounts:
2171 2174 chunktypecounts[chunktype] = 0
2172 2175 chunktypesizes[chunktype] = 0
2173 2176
2174 2177 chunktypecounts[chunktype] += 1
2175 2178 chunktypesizes[chunktype] += size
2176 2179
2177 2180 # Adjust size min value for empty cases
2178 2181 for size in (datasize, fullsize, semisize, deltasize):
2179 2182 if size[0] is None:
2180 2183 size[0] = 0
2181 2184
2182 2185 numdeltas = numrevs - numfull - numempty - numsemi
2183 2186 numoprev = numprev - nump1prev - nump2prev
2184 2187 totalrawsize = datasize[2]
2185 2188 datasize[2] /= numrevs
2186 2189 fulltotal = fullsize[2]
2187 2190 fullsize[2] /= numfull
2188 2191 semitotal = semisize[2]
2189 2192 snaptotal = {}
2190 2193 if 0 < numsemi:
2191 2194 semisize[2] /= numsemi
2192 2195 for depth in snapsizedepth:
2193 2196 snaptotal[depth] = snapsizedepth[depth][2]
2194 2197 snapsizedepth[depth][2] /= numsnapdepth[depth]
2195 2198
2196 2199 deltatotal = deltasize[2]
2197 2200 if numdeltas > 0:
2198 2201 deltasize[2] /= numdeltas
2199 2202 totalsize = fulltotal + semitotal + deltatotal
2200 2203 avgchainlen = sum(chainlengths) / numrevs
2201 2204 maxchainlen = max(chainlengths)
2202 2205 maxchainspan = max(chainspans)
2203 2206 compratio = 1
2204 2207 if totalsize:
2205 2208 compratio = totalrawsize / totalsize
2206 2209
2207 2210 basedfmtstr = '%%%dd\n'
2208 2211 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2209 2212
2210 2213 def dfmtstr(max):
2211 2214 return basedfmtstr % len(str(max))
2212 2215 def pcfmtstr(max, padding=0):
2213 2216 return basepcfmtstr % (len(str(max)), ' ' * padding)
2214 2217
2215 2218 def pcfmt(value, total):
2216 2219 if total:
2217 2220 return (value, 100 * float(value) / total)
2218 2221 else:
2219 2222 return value, 100.0
2220 2223
2221 2224 ui.write(('format : %d\n') % format)
2222 2225 ui.write(('flags : %s\n') % ', '.join(flags))
2223 2226
2224 2227 ui.write('\n')
2225 2228 fmt = pcfmtstr(totalsize)
2226 2229 fmt2 = dfmtstr(totalsize)
2227 2230 ui.write(('revisions : ') + fmt2 % numrevs)
2228 2231 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2229 2232 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2230 2233 ui.write(('revisions : ') + fmt2 % numrevs)
2231 2234 ui.write((' empty : ') + fmt % pcfmt(numempty, numrevs))
2232 2235 ui.write((' text : ')
2233 2236 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta))
2234 2237 ui.write((' delta : ')
2235 2238 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta))
2236 2239 ui.write((' snapshot : ') + fmt % pcfmt(numfull + numsemi, numrevs))
2237 2240 for depth in sorted(numsnapdepth):
2238 2241 ui.write((' lvl-%-3d : ' % depth)
2239 2242 + fmt % pcfmt(numsnapdepth[depth], numrevs))
2240 2243 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2241 2244 ui.write(('revision size : ') + fmt2 % totalsize)
2242 2245 ui.write((' snapshot : ')
2243 2246 + fmt % pcfmt(fulltotal + semitotal, totalsize))
2244 2247 for depth in sorted(numsnapdepth):
2245 2248 ui.write((' lvl-%-3d : ' % depth)
2246 2249 + fmt % pcfmt(snaptotal[depth], totalsize))
2247 2250 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2248 2251
2249 2252 def fmtchunktype(chunktype):
2250 2253 if chunktype == 'empty':
2251 2254 return ' %s : ' % chunktype
2252 2255 elif chunktype in pycompat.bytestr(string.ascii_letters):
2253 2256 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2254 2257 else:
2255 2258 return ' 0x%s : ' % hex(chunktype)
2256 2259
2257 2260 ui.write('\n')
2258 2261 ui.write(('chunks : ') + fmt2 % numrevs)
2259 2262 for chunktype in sorted(chunktypecounts):
2260 2263 ui.write(fmtchunktype(chunktype))
2261 2264 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2262 2265 ui.write(('chunks size : ') + fmt2 % totalsize)
2263 2266 for chunktype in sorted(chunktypecounts):
2264 2267 ui.write(fmtchunktype(chunktype))
2265 2268 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2266 2269
2267 2270 ui.write('\n')
2268 2271 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2269 2272 ui.write(('avg chain length : ') + fmt % avgchainlen)
2270 2273 ui.write(('max chain length : ') + fmt % maxchainlen)
2271 2274 ui.write(('max chain reach : ') + fmt % maxchainspan)
2272 2275 ui.write(('compression ratio : ') + fmt % compratio)
2273 2276
2274 2277 if format > 0:
2275 2278 ui.write('\n')
2276 2279 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2277 2280 % tuple(datasize))
2278 2281 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2279 2282 % tuple(fullsize))
2280 2283 ui.write(('inter-snapshot size (min/max/avg) : %d / %d / %d\n')
2281 2284 % tuple(semisize))
2282 2285 for depth in sorted(snapsizedepth):
2283 2286 if depth == 0:
2284 2287 continue
2285 2288 ui.write((' level-%-3d (min/max/avg) : %d / %d / %d\n')
2286 2289 % ((depth,) + tuple(snapsizedepth[depth])))
2287 2290 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2288 2291 % tuple(deltasize))
2289 2292
2290 2293 if numdeltas > 0:
2291 2294 ui.write('\n')
2292 2295 fmt = pcfmtstr(numdeltas)
2293 2296 fmt2 = pcfmtstr(numdeltas, 4)
2294 2297 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2295 2298 if numprev > 0:
2296 2299 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2297 2300 numprev))
2298 2301 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2299 2302 numprev))
2300 2303 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2301 2304 numprev))
2302 2305 if gdelta:
2303 2306 ui.write(('deltas against p1 : ')
2304 2307 + fmt % pcfmt(nump1, numdeltas))
2305 2308 ui.write(('deltas against p2 : ')
2306 2309 + fmt % pcfmt(nump2, numdeltas))
2307 2310 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2308 2311 numdeltas))
2309 2312
2310 2313 @command('debugrevlogindex', cmdutil.debugrevlogopts +
2311 2314 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2312 2315 _('[-f FORMAT] -c|-m|FILE'),
2313 2316 optionalrepo=True)
2314 2317 def debugrevlogindex(ui, repo, file_=None, **opts):
2315 2318 """dump the contents of a revlog index"""
2316 2319 opts = pycompat.byteskwargs(opts)
2317 2320 r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
2318 2321 format = opts.get('format', 0)
2319 2322 if format not in (0, 1):
2320 2323 raise error.Abort(_("unknown format %d") % format)
2321 2324
2322 2325 if ui.debugflag:
2323 2326 shortfn = hex
2324 2327 else:
2325 2328 shortfn = short
2326 2329
2327 2330 # There might not be anything in r, so have a sane default
2328 2331 idlen = 12
2329 2332 for i in r:
2330 2333 idlen = len(shortfn(r.node(i)))
2331 2334 break
2332 2335
2333 2336 if format == 0:
2334 2337 if ui.verbose:
2335 2338 ui.write((" rev offset length linkrev"
2336 2339 " %s %s p2\n") % ("nodeid".ljust(idlen),
2337 2340 "p1".ljust(idlen)))
2338 2341 else:
2339 2342 ui.write((" rev linkrev %s %s p2\n") % (
2340 2343 "nodeid".ljust(idlen), "p1".ljust(idlen)))
2341 2344 elif format == 1:
2342 2345 if ui.verbose:
2343 2346 ui.write((" rev flag offset length size link p1"
2344 2347 " p2 %s\n") % "nodeid".rjust(idlen))
2345 2348 else:
2346 2349 ui.write((" rev flag size link p1 p2 %s\n") %
2347 2350 "nodeid".rjust(idlen))
2348 2351
2349 2352 for i in r:
2350 2353 node = r.node(i)
2351 2354 if format == 0:
2352 2355 try:
2353 2356 pp = r.parents(node)
2354 2357 except Exception:
2355 2358 pp = [nullid, nullid]
2356 2359 if ui.verbose:
2357 2360 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
2358 2361 i, r.start(i), r.length(i), r.linkrev(i),
2359 2362 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2360 2363 else:
2361 2364 ui.write("% 6d % 7d %s %s %s\n" % (
2362 2365 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
2363 2366 shortfn(pp[1])))
2364 2367 elif format == 1:
2365 2368 pr = r.parentrevs(i)
2366 2369 if ui.verbose:
2367 2370 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
2368 2371 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2369 2372 r.linkrev(i), pr[0], pr[1], shortfn(node)))
2370 2373 else:
2371 2374 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
2372 2375 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
2373 2376 shortfn(node)))
2374 2377
2375 2378 @command('debugrevspec',
2376 2379 [('', 'optimize', None,
2377 2380 _('print parsed tree after optimizing (DEPRECATED)')),
2378 2381 ('', 'show-revs', True, _('print list of result revisions (default)')),
2379 2382 ('s', 'show-set', None, _('print internal representation of result set')),
2380 2383 ('p', 'show-stage', [],
2381 2384 _('print parsed tree at the given stage'), _('NAME')),
2382 2385 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2383 2386 ('', 'verify-optimized', False, _('verify optimized result')),
2384 2387 ],
2385 2388 ('REVSPEC'))
2386 2389 def debugrevspec(ui, repo, expr, **opts):
2387 2390 """parse and apply a revision specification
2388 2391
2389 2392 Use -p/--show-stage option to print the parsed tree at the given stages.
2390 2393 Use -p all to print tree at every stage.
2391 2394
2392 2395 Use --no-show-revs option with -s or -p to print only the set
2393 2396 representation or the parsed tree respectively.
2394 2397
2395 2398 Use --verify-optimized to compare the optimized result with the unoptimized
2396 2399 one. Returns 1 if the optimized result differs.
2397 2400 """
2398 2401 opts = pycompat.byteskwargs(opts)
2399 2402 aliases = ui.configitems('revsetalias')
2400 2403 stages = [
2401 2404 ('parsed', lambda tree: tree),
2402 2405 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2403 2406 ui.warn)),
2404 2407 ('concatenated', revsetlang.foldconcat),
2405 2408 ('analyzed', revsetlang.analyze),
2406 2409 ('optimized', revsetlang.optimize),
2407 2410 ]
2408 2411 if opts['no_optimized']:
2409 2412 stages = stages[:-1]
2410 2413 if opts['verify_optimized'] and opts['no_optimized']:
2411 2414 raise error.Abort(_('cannot use --verify-optimized with '
2412 2415 '--no-optimized'))
2413 2416 stagenames = set(n for n, f in stages)
2414 2417
2415 2418 showalways = set()
2416 2419 showchanged = set()
2417 2420 if ui.verbose and not opts['show_stage']:
2418 2421 # show parsed tree by --verbose (deprecated)
2419 2422 showalways.add('parsed')
2420 2423 showchanged.update(['expanded', 'concatenated'])
2421 2424 if opts['optimize']:
2422 2425 showalways.add('optimized')
2423 2426 if opts['show_stage'] and opts['optimize']:
2424 2427 raise error.Abort(_('cannot use --optimize with --show-stage'))
2425 2428 if opts['show_stage'] == ['all']:
2426 2429 showalways.update(stagenames)
2427 2430 else:
2428 2431 for n in opts['show_stage']:
2429 2432 if n not in stagenames:
2430 2433 raise error.Abort(_('invalid stage name: %s') % n)
2431 2434 showalways.update(opts['show_stage'])
2432 2435
2433 2436 treebystage = {}
2434 2437 printedtree = None
2435 2438 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2436 2439 for n, f in stages:
2437 2440 treebystage[n] = tree = f(tree)
2438 2441 if n in showalways or (n in showchanged and tree != printedtree):
2439 2442 if opts['show_stage'] or n != 'parsed':
2440 2443 ui.write(("* %s:\n") % n)
2441 2444 ui.write(revsetlang.prettyformat(tree), "\n")
2442 2445 printedtree = tree
2443 2446
2444 2447 if opts['verify_optimized']:
2445 2448 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2446 2449 brevs = revset.makematcher(treebystage['optimized'])(repo)
2447 2450 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2448 2451 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2449 2452 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2450 2453 arevs = list(arevs)
2451 2454 brevs = list(brevs)
2452 2455 if arevs == brevs:
2453 2456 return 0
2454 2457 ui.write(('--- analyzed\n'), label='diff.file_a')
2455 2458 ui.write(('+++ optimized\n'), label='diff.file_b')
2456 2459 sm = difflib.SequenceMatcher(None, arevs, brevs)
2457 2460 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2458 2461 if tag in ('delete', 'replace'):
2459 2462 for c in arevs[alo:ahi]:
2460 2463 ui.write('-%s\n' % c, label='diff.deleted')
2461 2464 if tag in ('insert', 'replace'):
2462 2465 for c in brevs[blo:bhi]:
2463 2466 ui.write('+%s\n' % c, label='diff.inserted')
2464 2467 if tag == 'equal':
2465 2468 for c in arevs[alo:ahi]:
2466 2469 ui.write(' %s\n' % c)
2467 2470 return 1
2468 2471
2469 2472 func = revset.makematcher(tree)
2470 2473 revs = func(repo)
2471 2474 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2472 2475 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2473 2476 if not opts['show_revs']:
2474 2477 return
2475 2478 for c in revs:
2476 2479 ui.write("%d\n" % c)
2477 2480
2478 2481 @command('debugserve', [
2479 2482 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2480 2483 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2481 2484 ('', 'logiofile', '', _('file to log server I/O to')),
2482 2485 ], '')
2483 2486 def debugserve(ui, repo, **opts):
2484 2487 """run a server with advanced settings
2485 2488
2486 2489 This command is similar to :hg:`serve`. It exists partially as a
2487 2490 workaround to the fact that ``hg serve --stdio`` must have specific
2488 2491 arguments for security reasons.
2489 2492 """
2490 2493 opts = pycompat.byteskwargs(opts)
2491 2494
2492 2495 if not opts['sshstdio']:
2493 2496 raise error.Abort(_('only --sshstdio is currently supported'))
2494 2497
2495 2498 logfh = None
2496 2499
2497 2500 if opts['logiofd'] and opts['logiofile']:
2498 2501 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2499 2502
2500 2503 if opts['logiofd']:
2501 2504 # Line buffered because output is line based.
2502 2505 try:
2503 2506 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2504 2507 except OSError as e:
2505 2508 if e.errno != errno.ESPIPE:
2506 2509 raise
2507 2510 # can't seek a pipe, so `ab` mode fails on py3
2508 2511 logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
2509 2512 elif opts['logiofile']:
2510 2513 logfh = open(opts['logiofile'], 'ab', 1)
2511 2514
2512 2515 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2513 2516 s.serve_forever()
2514 2517
2515 2518 @command('debugsetparents', [], _('REV1 [REV2]'))
2516 2519 def debugsetparents(ui, repo, rev1, rev2=None):
2517 2520 """manually set the parents of the current working directory
2518 2521
2519 2522 This is useful for writing repository conversion tools, but should
2520 2523 be used with care. For example, neither the working directory nor the
2521 2524 dirstate is updated, so file status may be incorrect after running this
2522 2525 command.
2523 2526
2524 2527 Returns 0 on success.
2525 2528 """
2526 2529
2527 2530 node1 = scmutil.revsingle(repo, rev1).node()
2528 2531 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2529 2532
2530 2533 with repo.wlock():
2531 2534 repo.setparents(node1, node2)
2532 2535
2533 2536 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2534 2537 def debugssl(ui, repo, source=None, **opts):
2535 2538 '''test a secure connection to a server
2536 2539
2537 2540 This builds the certificate chain for the server on Windows, installing the
2538 2541 missing intermediates and trusted root via Windows Update if necessary. It
2539 2542 does nothing on other platforms.
2540 2543
2541 2544 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2542 2545 that server is used. See :hg:`help urls` for more information.
2543 2546
2544 2547 If the update succeeds, retry the original operation. Otherwise, the cause
2545 2548 of the SSL error is likely another issue.
2546 2549 '''
2547 2550 if not pycompat.iswindows:
2548 2551 raise error.Abort(_('certificate chain building is only possible on '
2549 2552 'Windows'))
2550 2553
2551 2554 if not source:
2552 2555 if not repo:
2553 2556 raise error.Abort(_("there is no Mercurial repository here, and no "
2554 2557 "server specified"))
2555 2558 source = "default"
2556 2559
2557 2560 source, branches = hg.parseurl(ui.expandpath(source))
2558 2561 url = util.url(source)
2559 2562 addr = None
2560 2563
2561 2564 defaultport = {'https': 443, 'ssh': 22}
2562 2565 if url.scheme in defaultport:
2563 2566 try:
2564 2567 addr = (url.host, int(url.port or defaultport[url.scheme]))
2565 2568 except ValueError:
2566 2569 raise error.Abort(_("malformed port number in URL"))
2567 2570 else:
2568 2571 raise error.Abort(_("only https and ssh connections are supported"))
2569 2572
2570 2573 from . import win32
2571 2574
2572 2575 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2573 2576 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2574 2577
2575 2578 try:
2576 2579 s.connect(addr)
2577 2580 cert = s.getpeercert(True)
2578 2581
2579 2582 ui.status(_('checking the certificate chain for %s\n') % url.host)
2580 2583
2581 2584 complete = win32.checkcertificatechain(cert, build=False)
2582 2585
2583 2586 if not complete:
2584 2587 ui.status(_('certificate chain is incomplete, updating... '))
2585 2588
2586 2589 if not win32.checkcertificatechain(cert):
2587 2590 ui.status(_('failed.\n'))
2588 2591 else:
2589 2592 ui.status(_('done.\n'))
2590 2593 else:
2591 2594 ui.status(_('full certificate chain is available\n'))
2592 2595 finally:
2593 2596 s.close()
2594 2597
2595 2598 @command('debugsub',
2596 2599 [('r', 'rev', '',
2597 2600 _('revision to check'), _('REV'))],
2598 2601 _('[-r REV] [REV]'))
2599 2602 def debugsub(ui, repo, rev=None):
2600 2603 ctx = scmutil.revsingle(repo, rev, None)
2601 2604 for k, v in sorted(ctx.substate.items()):
2602 2605 ui.write(('path %s\n') % k)
2603 2606 ui.write((' source %s\n') % v[0])
2604 2607 ui.write((' revision %s\n') % v[1])
2605 2608
2606 2609 @command('debugsuccessorssets',
2607 2610 [('', 'closest', False, _('return closest successors sets only'))],
2608 2611 _('[REV]'))
2609 2612 def debugsuccessorssets(ui, repo, *revs, **opts):
2610 2613 """show set of successors for revision
2611 2614
2612 2615 A successors set of changeset A is a consistent group of revisions that
2613 2616 succeed A. It contains non-obsolete changesets only unless closests
2614 2617 successors set is set.
2615 2618
2616 2619 In most cases a changeset A has a single successors set containing a single
2617 2620 successor (changeset A replaced by A').
2618 2621
2619 2622 A changeset that is made obsolete with no successors are called "pruned".
2620 2623 Such changesets have no successors sets at all.
2621 2624
2622 2625 A changeset that has been "split" will have a successors set containing
2623 2626 more than one successor.
2624 2627
2625 2628 A changeset that has been rewritten in multiple different ways is called
2626 2629 "divergent". Such changesets have multiple successor sets (each of which
2627 2630 may also be split, i.e. have multiple successors).
2628 2631
2629 2632 Results are displayed as follows::
2630 2633
2631 2634 <rev1>
2632 2635 <successors-1A>
2633 2636 <rev2>
2634 2637 <successors-2A>
2635 2638 <successors-2B1> <successors-2B2> <successors-2B3>
2636 2639
2637 2640 Here rev2 has two possible (i.e. divergent) successors sets. The first
2638 2641 holds one element, whereas the second holds three (i.e. the changeset has
2639 2642 been split).
2640 2643 """
2641 2644 # passed to successorssets caching computation from one call to another
2642 2645 cache = {}
2643 2646 ctx2str = bytes
2644 2647 node2str = short
2645 2648 for rev in scmutil.revrange(repo, revs):
2646 2649 ctx = repo[rev]
2647 2650 ui.write('%s\n'% ctx2str(ctx))
2648 2651 for succsset in obsutil.successorssets(repo, ctx.node(),
2649 2652 closest=opts[r'closest'],
2650 2653 cache=cache):
2651 2654 if succsset:
2652 2655 ui.write(' ')
2653 2656 ui.write(node2str(succsset[0]))
2654 2657 for node in succsset[1:]:
2655 2658 ui.write(' ')
2656 2659 ui.write(node2str(node))
2657 2660 ui.write('\n')
2658 2661
2659 2662 @command('debugtemplate',
2660 2663 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2661 2664 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2662 2665 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2663 2666 optionalrepo=True)
2664 2667 def debugtemplate(ui, repo, tmpl, **opts):
2665 2668 """parse and apply a template
2666 2669
2667 2670 If -r/--rev is given, the template is processed as a log template and
2668 2671 applied to the given changesets. Otherwise, it is processed as a generic
2669 2672 template.
2670 2673
2671 2674 Use --verbose to print the parsed tree.
2672 2675 """
2673 2676 revs = None
2674 2677 if opts[r'rev']:
2675 2678 if repo is None:
2676 2679 raise error.RepoError(_('there is no Mercurial repository here '
2677 2680 '(.hg not found)'))
2678 2681 revs = scmutil.revrange(repo, opts[r'rev'])
2679 2682
2680 2683 props = {}
2681 2684 for d in opts[r'define']:
2682 2685 try:
2683 2686 k, v = (e.strip() for e in d.split('=', 1))
2684 2687 if not k or k == 'ui':
2685 2688 raise ValueError
2686 2689 props[k] = v
2687 2690 except ValueError:
2688 2691 raise error.Abort(_('malformed keyword definition: %s') % d)
2689 2692
2690 2693 if ui.verbose:
2691 2694 aliases = ui.configitems('templatealias')
2692 2695 tree = templater.parse(tmpl)
2693 2696 ui.note(templater.prettyformat(tree), '\n')
2694 2697 newtree = templater.expandaliases(tree, aliases)
2695 2698 if newtree != tree:
2696 2699 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2697 2700
2698 2701 if revs is None:
2699 2702 tres = formatter.templateresources(ui, repo)
2700 2703 t = formatter.maketemplater(ui, tmpl, resources=tres)
2701 2704 if ui.verbose:
2702 2705 kwds, funcs = t.symbolsuseddefault()
2703 2706 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2704 2707 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2705 2708 ui.write(t.renderdefault(props))
2706 2709 else:
2707 2710 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2708 2711 if ui.verbose:
2709 2712 kwds, funcs = displayer.t.symbolsuseddefault()
2710 2713 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2711 2714 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2712 2715 for r in revs:
2713 2716 displayer.show(repo[r], **pycompat.strkwargs(props))
2714 2717 displayer.close()
2715 2718
2716 2719 @command('debuguigetpass', [
2717 2720 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2718 2721 ], _('[-p TEXT]'), norepo=True)
2719 2722 def debuguigetpass(ui, prompt=''):
2720 2723 """show prompt to type password"""
2721 2724 r = ui.getpass(prompt)
2722 2725 ui.write(('respose: %s\n') % r)
2723 2726
2724 2727 @command('debuguiprompt', [
2725 2728 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2726 2729 ], _('[-p TEXT]'), norepo=True)
2727 2730 def debuguiprompt(ui, prompt=''):
2728 2731 """show plain prompt"""
2729 2732 r = ui.prompt(prompt)
2730 2733 ui.write(('response: %s\n') % r)
2731 2734
2732 2735 @command('debugupdatecaches', [])
2733 2736 def debugupdatecaches(ui, repo, *pats, **opts):
2734 2737 """warm all known caches in the repository"""
2735 2738 with repo.wlock(), repo.lock():
2736 2739 repo.updatecaches(full=True)
2737 2740
2738 2741 @command('debugupgraderepo', [
2739 2742 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2740 2743 ('', 'run', False, _('performs an upgrade')),
2741 2744 ])
2742 2745 def debugupgraderepo(ui, repo, run=False, optimize=None):
2743 2746 """upgrade a repository to use different features
2744 2747
2745 2748 If no arguments are specified, the repository is evaluated for upgrade
2746 2749 and a list of problems and potential optimizations is printed.
2747 2750
2748 2751 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2749 2752 can be influenced via additional arguments. More details will be provided
2750 2753 by the command output when run without ``--run``.
2751 2754
2752 2755 During the upgrade, the repository will be locked and no writes will be
2753 2756 allowed.
2754 2757
2755 2758 At the end of the upgrade, the repository may not be readable while new
2756 2759 repository data is swapped in. This window will be as long as it takes to
2757 2760 rename some directories inside the ``.hg`` directory. On most machines, this
2758 2761 should complete almost instantaneously and the chances of a consumer being
2759 2762 unable to access the repository should be low.
2760 2763 """
2761 2764 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2762 2765
2763 2766 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2764 2767 inferrepo=True)
2765 2768 def debugwalk(ui, repo, *pats, **opts):
2766 2769 """show how files match on given patterns"""
2767 2770 opts = pycompat.byteskwargs(opts)
2768 2771 m = scmutil.match(repo[None], pats, opts)
2769 2772 if ui.verbose:
2770 2773 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
2771 2774 items = list(repo[None].walk(m))
2772 2775 if not items:
2773 2776 return
2774 2777 f = lambda fn: fn
2775 2778 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2776 2779 f = lambda fn: util.normpath(fn)
2777 2780 fmt = 'f %%-%ds %%-%ds %%s' % (
2778 2781 max([len(abs) for abs in items]),
2779 2782 max([len(m.rel(abs)) for abs in items]))
2780 2783 for abs in items:
2781 2784 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2782 2785 ui.write("%s\n" % line.rstrip())
2783 2786
2784 2787 @command('debugwhyunstable', [], _('REV'))
2785 2788 def debugwhyunstable(ui, repo, rev):
2786 2789 """explain instabilities of a changeset"""
2787 2790 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2788 2791 dnodes = ''
2789 2792 if entry.get('divergentnodes'):
2790 2793 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2791 2794 for ctx in entry['divergentnodes']) + ' '
2792 2795 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2793 2796 entry['reason'], entry['node']))
2794 2797
2795 2798 @command('debugwireargs',
2796 2799 [('', 'three', '', 'three'),
2797 2800 ('', 'four', '', 'four'),
2798 2801 ('', 'five', '', 'five'),
2799 2802 ] + cmdutil.remoteopts,
2800 2803 _('REPO [OPTIONS]... [ONE [TWO]]'),
2801 2804 norepo=True)
2802 2805 def debugwireargs(ui, repopath, *vals, **opts):
2803 2806 opts = pycompat.byteskwargs(opts)
2804 2807 repo = hg.peer(ui, opts, repopath)
2805 2808 for opt in cmdutil.remoteopts:
2806 2809 del opts[opt[1]]
2807 2810 args = {}
2808 2811 for k, v in opts.iteritems():
2809 2812 if v:
2810 2813 args[k] = v
2811 2814 args = pycompat.strkwargs(args)
2812 2815 # run twice to check that we don't mess up the stream for the next command
2813 2816 res1 = repo.debugwireargs(*vals, **args)
2814 2817 res2 = repo.debugwireargs(*vals, **args)
2815 2818 ui.write("%s\n" % res1)
2816 2819 if res1 != res2:
2817 2820 ui.warn("%s\n" % res2)
2818 2821
2819 2822 def _parsewirelangblocks(fh):
2820 2823 activeaction = None
2821 2824 blocklines = []
2822 2825
2823 2826 for line in fh:
2824 2827 line = line.rstrip()
2825 2828 if not line:
2826 2829 continue
2827 2830
2828 2831 if line.startswith(b'#'):
2829 2832 continue
2830 2833
2831 2834 if not line.startswith(b' '):
2832 2835 # New block. Flush previous one.
2833 2836 if activeaction:
2834 2837 yield activeaction, blocklines
2835 2838
2836 2839 activeaction = line
2837 2840 blocklines = []
2838 2841 continue
2839 2842
2840 2843 # Else we start with an indent.
2841 2844
2842 2845 if not activeaction:
2843 2846 raise error.Abort(_('indented line outside of block'))
2844 2847
2845 2848 blocklines.append(line)
2846 2849
2847 2850 # Flush last block.
2848 2851 if activeaction:
2849 2852 yield activeaction, blocklines
2850 2853
2851 2854 @command('debugwireproto',
2852 2855 [
2853 2856 ('', 'localssh', False, _('start an SSH server for this repo')),
2854 2857 ('', 'peer', '', _('construct a specific version of the peer')),
2855 2858 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2856 2859 ('', 'nologhandshake', False,
2857 2860 _('do not log I/O related to the peer handshake')),
2858 2861 ] + cmdutil.remoteopts,
2859 2862 _('[PATH]'),
2860 2863 optionalrepo=True)
2861 2864 def debugwireproto(ui, repo, path=None, **opts):
2862 2865 """send wire protocol commands to a server
2863 2866
2864 2867 This command can be used to issue wire protocol commands to remote
2865 2868 peers and to debug the raw data being exchanged.
2866 2869
2867 2870 ``--localssh`` will start an SSH server against the current repository
2868 2871 and connect to that. By default, the connection will perform a handshake
2869 2872 and establish an appropriate peer instance.
2870 2873
2871 2874 ``--peer`` can be used to bypass the handshake protocol and construct a
2872 2875 peer instance using the specified class type. Valid values are ``raw``,
2873 2876 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2874 2877 raw data payloads and don't support higher-level command actions.
2875 2878
2876 2879 ``--noreadstderr`` can be used to disable automatic reading from stderr
2877 2880 of the peer (for SSH connections only). Disabling automatic reading of
2878 2881 stderr is useful for making output more deterministic.
2879 2882
2880 2883 Commands are issued via a mini language which is specified via stdin.
2881 2884 The language consists of individual actions to perform. An action is
2882 2885 defined by a block. A block is defined as a line with no leading
2883 2886 space followed by 0 or more lines with leading space. Blocks are
2884 2887 effectively a high-level command with additional metadata.
2885 2888
2886 2889 Lines beginning with ``#`` are ignored.
2887 2890
2888 2891 The following sections denote available actions.
2889 2892
2890 2893 raw
2891 2894 ---
2892 2895
2893 2896 Send raw data to the server.
2894 2897
2895 2898 The block payload contains the raw data to send as one atomic send
2896 2899 operation. The data may not actually be delivered in a single system
2897 2900 call: it depends on the abilities of the transport being used.
2898 2901
2899 2902 Each line in the block is de-indented and concatenated. Then, that
2900 2903 value is evaluated as a Python b'' literal. This allows the use of
2901 2904 backslash escaping, etc.
2902 2905
2903 2906 raw+
2904 2907 ----
2905 2908
2906 2909 Behaves like ``raw`` except flushes output afterwards.
2907 2910
2908 2911 command <X>
2909 2912 -----------
2910 2913
2911 2914 Send a request to run a named command, whose name follows the ``command``
2912 2915 string.
2913 2916
2914 2917 Arguments to the command are defined as lines in this block. The format of
2915 2918 each line is ``<key> <value>``. e.g.::
2916 2919
2917 2920 command listkeys
2918 2921 namespace bookmarks
2919 2922
2920 2923 If the value begins with ``eval:``, it will be interpreted as a Python
2921 2924 literal expression. Otherwise values are interpreted as Python b'' literals.
2922 2925 This allows sending complex types and encoding special byte sequences via
2923 2926 backslash escaping.
2924 2927
2925 2928 The following arguments have special meaning:
2926 2929
2927 2930 ``PUSHFILE``
2928 2931 When defined, the *push* mechanism of the peer will be used instead
2929 2932 of the static request-response mechanism and the content of the
2930 2933 file specified in the value of this argument will be sent as the
2931 2934 command payload.
2932 2935
2933 2936 This can be used to submit a local bundle file to the remote.
2934 2937
2935 2938 batchbegin
2936 2939 ----------
2937 2940
2938 2941 Instruct the peer to begin a batched send.
2939 2942
2940 2943 All ``command`` blocks are queued for execution until the next
2941 2944 ``batchsubmit`` block.
2942 2945
2943 2946 batchsubmit
2944 2947 -----------
2945 2948
2946 2949 Submit previously queued ``command`` blocks as a batch request.
2947 2950
2948 2951 This action MUST be paired with a ``batchbegin`` action.
2949 2952
2950 2953 httprequest <method> <path>
2951 2954 ---------------------------
2952 2955
2953 2956 (HTTP peer only)
2954 2957
2955 2958 Send an HTTP request to the peer.
2956 2959
2957 2960 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2958 2961
2959 2962 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2960 2963 headers to add to the request. e.g. ``Accept: foo``.
2961 2964
2962 2965 The following arguments are special:
2963 2966
2964 2967 ``BODYFILE``
2965 2968 The content of the file defined as the value to this argument will be
2966 2969 transferred verbatim as the HTTP request body.
2967 2970
2968 2971 ``frame <type> <flags> <payload>``
2969 2972 Send a unified protocol frame as part of the request body.
2970 2973
2971 2974 All frames will be collected and sent as the body to the HTTP
2972 2975 request.
2973 2976
2974 2977 close
2975 2978 -----
2976 2979
2977 2980 Close the connection to the server.
2978 2981
2979 2982 flush
2980 2983 -----
2981 2984
2982 2985 Flush data written to the server.
2983 2986
2984 2987 readavailable
2985 2988 -------------
2986 2989
2987 2990 Close the write end of the connection and read all available data from
2988 2991 the server.
2989 2992
2990 2993 If the connection to the server encompasses multiple pipes, we poll both
2991 2994 pipes and read available data.
2992 2995
2993 2996 readline
2994 2997 --------
2995 2998
2996 2999 Read a line of output from the server. If there are multiple output
2997 3000 pipes, reads only the main pipe.
2998 3001
2999 3002 ereadline
3000 3003 ---------
3001 3004
3002 3005 Like ``readline``, but read from the stderr pipe, if available.
3003 3006
3004 3007 read <X>
3005 3008 --------
3006 3009
3007 3010 ``read()`` N bytes from the server's main output pipe.
3008 3011
3009 3012 eread <X>
3010 3013 ---------
3011 3014
3012 3015 ``read()`` N bytes from the server's stderr pipe, if available.
3013 3016
3014 3017 Specifying Unified Frame-Based Protocol Frames
3015 3018 ----------------------------------------------
3016 3019
3017 3020 It is possible to emit a *Unified Frame-Based Protocol* by using special
3018 3021 syntax.
3019 3022
3020 3023 A frame is composed as a type, flags, and payload. These can be parsed
3021 3024 from a string of the form:
3022 3025
3023 3026 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
3024 3027
3025 3028 ``request-id`` and ``stream-id`` are integers defining the request and
3026 3029 stream identifiers.
3027 3030
3028 3031 ``type`` can be an integer value for the frame type or the string name
3029 3032 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
3030 3033 ``command-name``.
3031 3034
3032 3035 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
3033 3036 components. Each component (and there can be just one) can be an integer
3034 3037 or a flag name for stream flags or frame flags, respectively. Values are
3035 3038 resolved to integers and then bitwise OR'd together.
3036 3039
3037 3040 ``payload`` represents the raw frame payload. If it begins with
3038 3041 ``cbor:``, the following string is evaluated as Python code and the
3039 3042 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
3040 3043 as a Python byte string literal.
3041 3044 """
3042 3045 opts = pycompat.byteskwargs(opts)
3043 3046
3044 3047 if opts['localssh'] and not repo:
3045 3048 raise error.Abort(_('--localssh requires a repository'))
3046 3049
3047 3050 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
3048 3051 raise error.Abort(_('invalid value for --peer'),
3049 3052 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
3050 3053
3051 3054 if path and opts['localssh']:
3052 3055 raise error.Abort(_('cannot specify --localssh with an explicit '
3053 3056 'path'))
3054 3057
3055 3058 if ui.interactive():
3056 3059 ui.write(_('(waiting for commands on stdin)\n'))
3057 3060
3058 3061 blocks = list(_parsewirelangblocks(ui.fin))
3059 3062
3060 3063 proc = None
3061 3064 stdin = None
3062 3065 stdout = None
3063 3066 stderr = None
3064 3067 opener = None
3065 3068
3066 3069 if opts['localssh']:
3067 3070 # We start the SSH server in its own process so there is process
3068 3071 # separation. This prevents a whole class of potential bugs around
3069 3072 # shared state from interfering with server operation.
3070 3073 args = procutil.hgcmd() + [
3071 3074 '-R', repo.root,
3072 3075 'debugserve', '--sshstdio',
3073 3076 ]
3074 3077 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
3075 3078 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
3076 3079 bufsize=0)
3077 3080
3078 3081 stdin = proc.stdin
3079 3082 stdout = proc.stdout
3080 3083 stderr = proc.stderr
3081 3084
3082 3085 # We turn the pipes into observers so we can log I/O.
3083 3086 if ui.verbose or opts['peer'] == 'raw':
3084 3087 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
3085 3088 logdata=True)
3086 3089 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
3087 3090 logdata=True)
3088 3091 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
3089 3092 logdata=True)
3090 3093
3091 3094 # --localssh also implies the peer connection settings.
3092 3095
3093 3096 url = 'ssh://localserver'
3094 3097 autoreadstderr = not opts['noreadstderr']
3095 3098
3096 3099 if opts['peer'] == 'ssh1':
3097 3100 ui.write(_('creating ssh peer for wire protocol version 1\n'))
3098 3101 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
3099 3102 None, autoreadstderr=autoreadstderr)
3100 3103 elif opts['peer'] == 'ssh2':
3101 3104 ui.write(_('creating ssh peer for wire protocol version 2\n'))
3102 3105 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
3103 3106 None, autoreadstderr=autoreadstderr)
3104 3107 elif opts['peer'] == 'raw':
3105 3108 ui.write(_('using raw connection to peer\n'))
3106 3109 peer = None
3107 3110 else:
3108 3111 ui.write(_('creating ssh peer from handshake results\n'))
3109 3112 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
3110 3113 autoreadstderr=autoreadstderr)
3111 3114
3112 3115 elif path:
3113 3116 # We bypass hg.peer() so we can proxy the sockets.
3114 3117 # TODO consider not doing this because we skip
3115 3118 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
3116 3119 u = util.url(path)
3117 3120 if u.scheme != 'http':
3118 3121 raise error.Abort(_('only http:// paths are currently supported'))
3119 3122
3120 3123 url, authinfo = u.authinfo()
3121 3124 openerargs = {
3122 3125 r'useragent': b'Mercurial debugwireproto',
3123 3126 }
3124 3127
3125 3128 # Turn pipes/sockets into observers so we can log I/O.
3126 3129 if ui.verbose:
3127 3130 openerargs.update({
3128 3131 r'loggingfh': ui,
3129 3132 r'loggingname': b's',
3130 3133 r'loggingopts': {
3131 3134 r'logdata': True,
3132 3135 r'logdataapis': False,
3133 3136 },
3134 3137 })
3135 3138
3136 3139 if ui.debugflag:
3137 3140 openerargs[r'loggingopts'][r'logdataapis'] = True
3138 3141
3139 3142 # Don't send default headers when in raw mode. This allows us to
3140 3143 # bypass most of the behavior of our URL handling code so we can
3141 3144 # have near complete control over what's sent on the wire.
3142 3145 if opts['peer'] == 'raw':
3143 3146 openerargs[r'sendaccept'] = False
3144 3147
3145 3148 opener = urlmod.opener(ui, authinfo, **openerargs)
3146 3149
3147 3150 if opts['peer'] == 'http2':
3148 3151 ui.write(_('creating http peer for wire protocol version 2\n'))
3149 3152 # We go through makepeer() because we need an API descriptor for
3150 3153 # the peer instance to be useful.
3151 3154 with ui.configoverride({
3152 3155 ('experimental', 'httppeer.advertise-v2'): True}):
3153 3156 if opts['nologhandshake']:
3154 3157 ui.pushbuffer()
3155 3158
3156 3159 peer = httppeer.makepeer(ui, path, opener=opener)
3157 3160
3158 3161 if opts['nologhandshake']:
3159 3162 ui.popbuffer()
3160 3163
3161 3164 if not isinstance(peer, httppeer.httpv2peer):
3162 3165 raise error.Abort(_('could not instantiate HTTP peer for '
3163 3166 'wire protocol version 2'),
3164 3167 hint=_('the server may not have the feature '
3165 3168 'enabled or is not allowing this '
3166 3169 'client version'))
3167 3170
3168 3171 elif opts['peer'] == 'raw':
3169 3172 ui.write(_('using raw connection to peer\n'))
3170 3173 peer = None
3171 3174 elif opts['peer']:
3172 3175 raise error.Abort(_('--peer %s not supported with HTTP peers') %
3173 3176 opts['peer'])
3174 3177 else:
3175 3178 peer = httppeer.makepeer(ui, path, opener=opener)
3176 3179
3177 3180 # We /could/ populate stdin/stdout with sock.makefile()...
3178 3181 else:
3179 3182 raise error.Abort(_('unsupported connection configuration'))
3180 3183
3181 3184 batchedcommands = None
3182 3185
3183 3186 # Now perform actions based on the parsed wire language instructions.
3184 3187 for action, lines in blocks:
3185 3188 if action in ('raw', 'raw+'):
3186 3189 if not stdin:
3187 3190 raise error.Abort(_('cannot call raw/raw+ on this peer'))
3188 3191
3189 3192 # Concatenate the data together.
3190 3193 data = ''.join(l.lstrip() for l in lines)
3191 3194 data = stringutil.unescapestr(data)
3192 3195 stdin.write(data)
3193 3196
3194 3197 if action == 'raw+':
3195 3198 stdin.flush()
3196 3199 elif action == 'flush':
3197 3200 if not stdin:
3198 3201 raise error.Abort(_('cannot call flush on this peer'))
3199 3202 stdin.flush()
3200 3203 elif action.startswith('command'):
3201 3204 if not peer:
3202 3205 raise error.Abort(_('cannot send commands unless peer instance '
3203 3206 'is available'))
3204 3207
3205 3208 command = action.split(' ', 1)[1]
3206 3209
3207 3210 args = {}
3208 3211 for line in lines:
3209 3212 # We need to allow empty values.
3210 3213 fields = line.lstrip().split(' ', 1)
3211 3214 if len(fields) == 1:
3212 3215 key = fields[0]
3213 3216 value = ''
3214 3217 else:
3215 3218 key, value = fields
3216 3219
3217 3220 if value.startswith('eval:'):
3218 3221 value = stringutil.evalpythonliteral(value[5:])
3219 3222 else:
3220 3223 value = stringutil.unescapestr(value)
3221 3224
3222 3225 args[key] = value
3223 3226
3224 3227 if batchedcommands is not None:
3225 3228 batchedcommands.append((command, args))
3226 3229 continue
3227 3230
3228 3231 ui.status(_('sending %s command\n') % command)
3229 3232
3230 3233 if 'PUSHFILE' in args:
3231 3234 with open(args['PUSHFILE'], r'rb') as fh:
3232 3235 del args['PUSHFILE']
3233 3236 res, output = peer._callpush(command, fh,
3234 3237 **pycompat.strkwargs(args))
3235 3238 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3236 3239 ui.status(_('remote output: %s\n') %
3237 3240 stringutil.escapestr(output))
3238 3241 else:
3239 3242 with peer.commandexecutor() as e:
3240 3243 res = e.callcommand(command, args).result()
3241 3244
3242 3245 if isinstance(res, wireprotov2peer.commandresponse):
3243 3246 val = res.objects()
3244 3247 ui.status(_('response: %s\n') %
3245 3248 stringutil.pprint(val, bprefix=True, indent=2))
3246 3249 else:
3247 3250 ui.status(_('response: %s\n') %
3248 3251 stringutil.pprint(res, bprefix=True, indent=2))
3249 3252
3250 3253 elif action == 'batchbegin':
3251 3254 if batchedcommands is not None:
3252 3255 raise error.Abort(_('nested batchbegin not allowed'))
3253 3256
3254 3257 batchedcommands = []
3255 3258 elif action == 'batchsubmit':
3256 3259 # There is a batching API we could go through. But it would be
3257 3260 # difficult to normalize requests into function calls. It is easier
3258 3261 # to bypass this layer and normalize to commands + args.
3259 3262 ui.status(_('sending batch with %d sub-commands\n') %
3260 3263 len(batchedcommands))
3261 3264 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3262 3265 ui.status(_('response #%d: %s\n') %
3263 3266 (i, stringutil.escapestr(chunk)))
3264 3267
3265 3268 batchedcommands = None
3266 3269
3267 3270 elif action.startswith('httprequest '):
3268 3271 if not opener:
3269 3272 raise error.Abort(_('cannot use httprequest without an HTTP '
3270 3273 'peer'))
3271 3274
3272 3275 request = action.split(' ', 2)
3273 3276 if len(request) != 3:
3274 3277 raise error.Abort(_('invalid httprequest: expected format is '
3275 3278 '"httprequest <method> <path>'))
3276 3279
3277 3280 method, httppath = request[1:]
3278 3281 headers = {}
3279 3282 body = None
3280 3283 frames = []
3281 3284 for line in lines:
3282 3285 line = line.lstrip()
3283 3286 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3284 3287 if m:
3285 3288 headers[m.group(1)] = m.group(2)
3286 3289 continue
3287 3290
3288 3291 if line.startswith(b'BODYFILE '):
3289 3292 with open(line.split(b' ', 1), 'rb') as fh:
3290 3293 body = fh.read()
3291 3294 elif line.startswith(b'frame '):
3292 3295 frame = wireprotoframing.makeframefromhumanstring(
3293 3296 line[len(b'frame '):])
3294 3297
3295 3298 frames.append(frame)
3296 3299 else:
3297 3300 raise error.Abort(_('unknown argument to httprequest: %s') %
3298 3301 line)
3299 3302
3300 3303 url = path + httppath
3301 3304
3302 3305 if frames:
3303 3306 body = b''.join(bytes(f) for f in frames)
3304 3307
3305 3308 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3306 3309
3307 3310 # urllib.Request insists on using has_data() as a proxy for
3308 3311 # determining the request method. Override that to use our
3309 3312 # explicitly requested method.
3310 3313 req.get_method = lambda: pycompat.sysstr(method)
3311 3314
3312 3315 try:
3313 3316 res = opener.open(req)
3314 3317 body = res.read()
3315 3318 except util.urlerr.urlerror as e:
3316 3319 # read() method must be called, but only exists in Python 2
3317 3320 getattr(e, 'read', lambda: None)()
3318 3321 continue
3319 3322
3320 3323 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3321 3324 ui.write(_('cbor> %s\n') %
3322 3325 stringutil.pprint(cborutil.decodeall(body)[0],
3323 3326 bprefix=True,
3324 3327 indent=2))
3325 3328
3326 3329 elif action == 'close':
3327 3330 peer.close()
3328 3331 elif action == 'readavailable':
3329 3332 if not stdout or not stderr:
3330 3333 raise error.Abort(_('readavailable not available on this peer'))
3331 3334
3332 3335 stdin.close()
3333 3336 stdout.read()
3334 3337 stderr.read()
3335 3338
3336 3339 elif action == 'readline':
3337 3340 if not stdout:
3338 3341 raise error.Abort(_('readline not available on this peer'))
3339 3342 stdout.readline()
3340 3343 elif action == 'ereadline':
3341 3344 if not stderr:
3342 3345 raise error.Abort(_('ereadline not available on this peer'))
3343 3346 stderr.readline()
3344 3347 elif action.startswith('read '):
3345 3348 count = int(action.split(' ', 1)[1])
3346 3349 if not stdout:
3347 3350 raise error.Abort(_('read not available on this peer'))
3348 3351 stdout.read(count)
3349 3352 elif action.startswith('eread '):
3350 3353 count = int(action.split(' ', 1)[1])
3351 3354 if not stderr:
3352 3355 raise error.Abort(_('eread not available on this peer'))
3353 3356 stderr.read(count)
3354 3357 else:
3355 3358 raise error.Abort(_('unknown action: %s') % action)
3356 3359
3357 3360 if batchedcommands is not None:
3358 3361 raise error.Abort(_('unclosed "batchbegin" request'))
3359 3362
3360 3363 if peer:
3361 3364 peer.close()
3362 3365
3363 3366 if proc:
3364 3367 proc.kill()
@@ -1,763 +1,763 b''
1 1 $ hg init basic
2 2 $ cd basic
3 3
4 4 should complain
5 5
6 6 $ hg backout
7 7 abort: please specify a revision to backout
8 8 [255]
9 9 $ hg backout -r 0 0
10 10 abort: please specify just one revision
11 11 [255]
12 12
13 13 basic operation
14 14 (this also tests that editor is invoked if the commit message is not
15 15 specified explicitly)
16 16
17 17 $ echo a > a
18 18 $ hg commit -d '0 0' -A -m a
19 19 adding a
20 20 $ echo b >> a
21 21 $ hg commit -d '1 0' -m b
22 22
23 23 $ hg status --rev tip --rev "tip^1"
24 24 M a
25 25 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true
26 26 reverting a
27 27 Backed out changeset a820f4f40a57
28 28
29 29
30 30 HG: Enter commit message. Lines beginning with 'HG:' are removed.
31 31 HG: Leave message empty to abort commit.
32 32 HG: --
33 33 HG: user: test
34 34 HG: branch 'default'
35 35 HG: changed a
36 36 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
37 37 $ cat a
38 38 a
39 39 $ hg summary
40 40 parent: 2:2929462c3dff tip
41 41 Backed out changeset a820f4f40a57
42 42 branch: default
43 43 commit: (clean)
44 44 update: (current)
45 45 phases: 3 draft
46 46
47 47 commit option
48 48
49 49 $ cd ..
50 50 $ hg init commit
51 51 $ cd commit
52 52
53 53 $ echo tomatoes > a
54 54 $ hg add a
55 55 $ hg commit -d '0 0' -m tomatoes
56 56
57 57 $ echo chair > b
58 58 $ hg add b
59 59 $ hg commit -d '1 0' -m chair
60 60
61 61 $ echo grapes >> a
62 62 $ hg commit -d '2 0' -m grapes
63 63
64 64 $ hg backout -d '4 0' 1 --tool=:fail
65 65 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
66 66 changeset 3:1c2161e97c0a backs out changeset 1:22cb4f70d813
67 67 $ hg summary
68 68 parent: 3:1c2161e97c0a tip
69 69 Backed out changeset 22cb4f70d813
70 70 branch: default
71 71 commit: (clean)
72 72 update: (current)
73 73 phases: 4 draft
74 74
75 75 $ echo ypples > a
76 76 $ hg commit -d '5 0' -m ypples
77 77
78 78 $ hg backout -d '6 0' 2 --tool=:fail
79 79 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
80 80 use 'hg resolve' to retry unresolved file merges
81 81 [1]
82 82 $ hg summary
83 83 parent: 4:ed99997b793d tip
84 84 ypples
85 85 branch: default
86 86 commit: 1 unresolved (clean)
87 87 update: (current)
88 88 phases: 5 draft
89 89
90 90 file that was removed is recreated
91 91 (this also tests that editor is not invoked if the commit message is
92 92 specified explicitly)
93 93
94 94 $ cd ..
95 95 $ hg init remove
96 96 $ cd remove
97 97
98 98 $ echo content > a
99 99 $ hg commit -d '0 0' -A -m a
100 100 adding a
101 101
102 102 $ hg rm a
103 103 $ hg commit -d '1 0' -m b
104 104
105 105 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true -m "Backed out changeset 76862dcce372"
106 106 adding a
107 107 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
108 108 $ cat a
109 109 content
110 110 $ hg summary
111 111 parent: 2:de31bdc76c0d tip
112 112 Backed out changeset 76862dcce372
113 113 branch: default
114 114 commit: (clean)
115 115 update: (current)
116 116 phases: 3 draft
117 117
118 118 backout of backout is as if nothing happened
119 119
120 120 $ hg backout -d '3 0' --merge tip --tool=true
121 121 removing a
122 122 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
123 123 $ test -f a
124 124 [1]
125 125 $ hg summary
126 126 parent: 3:7f6d0f120113 tip
127 127 Backed out changeset de31bdc76c0d
128 128 branch: default
129 129 commit: (clean)
130 130 update: (current)
131 131 phases: 4 draft
132 132
133 133 Test that 'hg rollback' restores dirstate just before opening
134 134 transaction: in-memory dirstate changes should be written into
135 135 '.hg/journal.dirstate' as expected.
136 136
137 137 $ echo 'removed soon' > b
138 138 $ hg commit -A -d '4 0' -m 'prepare for subsequent removing'
139 139 adding b
140 140 $ echo 'newly added' > c
141 141 $ hg add c
142 142 $ hg remove b
143 143 $ hg commit -d '5 0' -m 'prepare for subsequent backout'
144 144 $ touch -t 200001010000 c
145 145 $ hg status -A
146 146 C c
147 $ hg debugstate --nodates
147 $ hg debugstate --no-dates
148 148 n 644 12 set c
149 149 $ hg backout -d '6 0' -m 'to be rollback-ed soon' -r .
150 150 removing c
151 151 adding b
152 152 changeset 6:4bfec048029d backs out changeset 5:fac0b729a654
153 153 $ hg rollback -q
154 154 $ hg status -A
155 155 A b
156 156 R c
157 $ hg debugstate --nodates
157 $ hg debugstate --no-dates
158 158 a 0 -1 unset b
159 159 r 0 0 set c
160 160
161 161 across branch
162 162
163 163 $ cd ..
164 164 $ hg init branch
165 165 $ cd branch
166 166 $ echo a > a
167 167 $ hg ci -Am0
168 168 adding a
169 169 $ echo b > b
170 170 $ hg ci -Am1
171 171 adding b
172 172 $ hg co -C 0
173 173 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
174 174 $ hg summary
175 175 parent: 0:f7b1eb17ad24
176 176 0
177 177 branch: default
178 178 commit: (clean)
179 179 update: 1 new changesets (update)
180 180 phases: 2 draft
181 181
182 182 should fail
183 183
184 184 $ hg backout 1
185 185 abort: cannot backout change that is not an ancestor
186 186 [255]
187 187 $ echo c > c
188 188 $ hg ci -Am2
189 189 adding c
190 190 created new head
191 191 $ hg summary
192 192 parent: 2:db815d6d32e6 tip
193 193 2
194 194 branch: default
195 195 commit: (clean)
196 196 update: 1 new changesets, 2 branch heads (merge)
197 197 phases: 3 draft
198 198
199 199 should fail
200 200
201 201 $ hg backout 1
202 202 abort: cannot backout change that is not an ancestor
203 203 [255]
204 204 $ hg summary
205 205 parent: 2:db815d6d32e6 tip
206 206 2
207 207 branch: default
208 208 commit: (clean)
209 209 update: 1 new changesets, 2 branch heads (merge)
210 210 phases: 3 draft
211 211
212 212 backout with merge
213 213
214 214 $ cd ..
215 215 $ hg init merge
216 216 $ cd merge
217 217
218 218 $ echo line 1 > a
219 219 $ echo line 2 >> a
220 220 $ hg commit -d '0 0' -A -m a
221 221 adding a
222 222 $ hg summary
223 223 parent: 0:59395513a13a tip
224 224 a
225 225 branch: default
226 226 commit: (clean)
227 227 update: (current)
228 228 phases: 1 draft
229 229
230 230 remove line 1
231 231
232 232 $ echo line 2 > a
233 233 $ hg commit -d '1 0' -m b
234 234
235 235 $ echo line 3 >> a
236 236 $ hg commit -d '2 0' -m c
237 237
238 238 $ hg backout --merge -d '3 0' 1 --tool=true
239 239 reverting a
240 240 created new head
241 241 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
242 242 merging with changeset 3:26b8ccb9ad91
243 243 merging a
244 244 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
245 245 (branch merge, don't forget to commit)
246 246 $ hg commit -d '4 0' -m d
247 247 $ hg summary
248 248 parent: 4:c7df5e0b9c09 tip
249 249 d
250 250 branch: default
251 251 commit: (clean)
252 252 update: (current)
253 253 phases: 5 draft
254 254
255 255 check line 1 is back
256 256
257 257 $ cat a
258 258 line 1
259 259 line 2
260 260 line 3
261 261
262 262 Test visibility of in-memory dirstate changes outside transaction to
263 263 external hook process
264 264
265 265 $ cat > $TESTTMP/checkvisibility.sh <<EOF
266 266 > echo "==== \$1:"
267 267 > hg parents --template "{rev}:{node|short}\n"
268 268 > echo "===="
269 269 > EOF
270 270
271 271 "hg backout --merge REV1" at REV2 below implies steps below:
272 272
273 273 (1) update to REV1 (REV2 => REV1)
274 274 (2) revert by REV1^1
275 275 (3) commit backing out revision (REV3)
276 276 (4) update to REV2 (REV3 => REV2)
277 277 (5) merge with REV3 (REV2 => REV2, REV3)
278 278
279 279 == test visibility to external preupdate hook
280 280
281 281 $ hg update -q -C 2
282 282 $ hg --config extensions.strip= strip 3
283 283 saved backup bundle to * (glob)
284 284
285 285 $ cat >> .hg/hgrc <<EOF
286 286 > [hooks]
287 287 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
288 288 > EOF
289 289
290 290 ("-m" is needed to avoid writing dirstate changes out at other than
291 291 invocation of the hook to be examined)
292 292
293 293 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
294 294 ==== preupdate:
295 295 2:6ea3f2a197a2
296 296 ====
297 297 reverting a
298 298 created new head
299 299 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
300 300 ==== preupdate:
301 301 3:d92a3f57f067
302 302 ====
303 303 merging with changeset 3:d92a3f57f067
304 304 ==== preupdate:
305 305 2:6ea3f2a197a2
306 306 ====
307 307 merging a
308 308 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
309 309 (branch merge, don't forget to commit)
310 310
311 311 $ cat >> .hg/hgrc <<EOF
312 312 > [hooks]
313 313 > preupdate.visibility =
314 314 > EOF
315 315
316 316 == test visibility to external update hook
317 317
318 318 $ hg update -q -C 2
319 319 $ hg --config extensions.strip= strip 3
320 320 saved backup bundle to * (glob)
321 321
322 322 $ cat >> .hg/hgrc <<EOF
323 323 > [hooks]
324 324 > update.visibility = sh $TESTTMP/checkvisibility.sh update
325 325 > EOF
326 326
327 327 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
328 328 ==== update:
329 329 1:5a50a024c182
330 330 ====
331 331 reverting a
332 332 created new head
333 333 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
334 334 ==== update:
335 335 2:6ea3f2a197a2
336 336 ====
337 337 merging with changeset 3:d92a3f57f067
338 338 merging a
339 339 ==== update:
340 340 2:6ea3f2a197a2
341 341 3:d92a3f57f067
342 342 ====
343 343 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
344 344 (branch merge, don't forget to commit)
345 345
346 346 $ cat >> .hg/hgrc <<EOF
347 347 > [hooks]
348 348 > update.visibility =
349 349 > EOF
350 350
351 351 $ cd ..
352 352
353 353 backout should not back out subsequent changesets
354 354
355 355 $ hg init onecs
356 356 $ cd onecs
357 357 $ echo 1 > a
358 358 $ hg commit -d '0 0' -A -m a
359 359 adding a
360 360 $ echo 2 >> a
361 361 $ hg commit -d '1 0' -m b
362 362 $ echo 1 > b
363 363 $ hg commit -d '2 0' -A -m c
364 364 adding b
365 365 $ hg summary
366 366 parent: 2:882396649954 tip
367 367 c
368 368 branch: default
369 369 commit: (clean)
370 370 update: (current)
371 371 phases: 3 draft
372 372
373 373 without --merge
374 374 $ hg backout --no-commit -d '3 0' 1 --tool=true
375 375 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 376 changeset 22bca4c721e5 backed out, don't forget to commit.
377 377 $ hg locate b
378 378 b
379 379 $ hg update -C tip
380 380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 381 $ hg locate b
382 382 b
383 383 $ hg summary
384 384 parent: 2:882396649954 tip
385 385 c
386 386 branch: default
387 387 commit: (clean)
388 388 update: (current)
389 389 phases: 3 draft
390 390
391 391 with --merge
392 392 $ hg backout --merge -d '3 0' 1 --tool=true
393 393 reverting a
394 394 created new head
395 395 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
396 396 merging with changeset 3:3202beb76721
397 397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 398 (branch merge, don't forget to commit)
399 399 $ hg locate b
400 400 b
401 401 $ hg update -C tip
402 402 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
403 403 $ hg locate b
404 404 [1]
405 405
406 406 $ cd ..
407 407 $ hg init m
408 408 $ cd m
409 409 $ echo a > a
410 410 $ hg commit -d '0 0' -A -m a
411 411 adding a
412 412 $ echo b > b
413 413 $ hg commit -d '1 0' -A -m b
414 414 adding b
415 415 $ echo c > c
416 416 $ hg commit -d '2 0' -A -m b
417 417 adding c
418 418 $ hg update 1
419 419 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
420 420 $ echo d > d
421 421 $ hg commit -d '3 0' -A -m c
422 422 adding d
423 423 created new head
424 424 $ hg merge 2
425 425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 426 (branch merge, don't forget to commit)
427 427 $ hg commit -d '4 0' -A -m d
428 428 $ hg summary
429 429 parent: 4:b2f3bb92043e tip
430 430 d
431 431 branch: default
432 432 commit: (clean)
433 433 update: (current)
434 434 phases: 5 draft
435 435
436 436 backout of merge should fail
437 437
438 438 $ hg backout 4
439 439 abort: cannot backout a merge changeset
440 440 [255]
441 441
442 442 backout of merge with bad parent should fail
443 443
444 444 $ hg backout --parent 0 4
445 445 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
446 446 [255]
447 447
448 448 backout of non-merge with parent should fail
449 449
450 450 $ hg backout --parent 0 3
451 451 abort: cannot use --parent on non-merge changeset
452 452 [255]
453 453
454 454 backout with valid parent should be ok
455 455
456 456 $ hg backout -d '5 0' --parent 2 4 --tool=true
457 457 removing d
458 458 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
459 459 $ hg summary
460 460 parent: 5:10e5328c8435 tip
461 461 Backed out changeset b2f3bb92043e
462 462 branch: default
463 463 commit: (clean)
464 464 update: (current)
465 465 phases: 6 draft
466 466
467 467 $ hg rollback
468 468 repository tip rolled back to revision 4 (undo commit)
469 469 working directory now based on revision 4
470 470 $ hg update -C
471 471 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 472 $ hg summary
473 473 parent: 4:b2f3bb92043e tip
474 474 d
475 475 branch: default
476 476 commit: (clean)
477 477 update: (current)
478 478 phases: 5 draft
479 479
480 480 $ hg backout -d '6 0' --parent 3 4 --tool=true
481 481 removing c
482 482 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
483 483 $ hg summary
484 484 parent: 5:033590168430 tip
485 485 Backed out changeset b2f3bb92043e
486 486 branch: default
487 487 commit: (clean)
488 488 update: (current)
489 489 phases: 6 draft
490 490
491 491 $ cd ..
492 492
493 493 named branches
494 494
495 495 $ hg init named_branches
496 496 $ cd named_branches
497 497
498 498 $ echo default > default
499 499 $ hg ci -d '0 0' -Am default
500 500 adding default
501 501 $ hg branch branch1
502 502 marked working directory as branch branch1
503 503 (branches are permanent and global, did you want a bookmark?)
504 504 $ echo branch1 > file1
505 505 $ hg ci -d '1 0' -Am file1
506 506 adding file1
507 507 $ hg branch branch2
508 508 marked working directory as branch branch2
509 509 $ echo branch2 > file2
510 510 $ hg ci -d '2 0' -Am file2
511 511 adding file2
512 512
513 513 without --merge
514 514 $ hg backout --no-commit -r 1 --tool=true
515 515 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
516 516 changeset bf1602f437f3 backed out, don't forget to commit.
517 517 $ hg branch
518 518 branch2
519 519 $ hg status -A
520 520 R file1
521 521 C default
522 522 C file2
523 523 $ hg summary
524 524 parent: 2:45bbcd363bf0 tip
525 525 file2
526 526 branch: branch2
527 527 commit: 1 removed
528 528 update: (current)
529 529 phases: 3 draft
530 530
531 531 with --merge
532 532 (this also tests that editor is invoked if '--edit' is specified
533 533 explicitly regardless of '--message')
534 534
535 535 $ hg update -qC
536 536 $ HGEDITOR=cat hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true --edit
537 537 removing file1
538 538 backout on branch1
539 539
540 540
541 541 HG: Enter commit message. Lines beginning with 'HG:' are removed.
542 542 HG: Leave message empty to abort commit.
543 543 HG: --
544 544 HG: user: test
545 545 HG: branch 'branch2'
546 546 HG: removed file1
547 547 created new head
548 548 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
549 549 merging with changeset 3:d4e8f6db59fb
550 550 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
551 551 (branch merge, don't forget to commit)
552 552 $ hg summary
553 553 parent: 2:45bbcd363bf0
554 554 file2
555 555 parent: 3:d4e8f6db59fb tip
556 556 backout on branch1
557 557 branch: branch2
558 558 commit: 1 removed (merge)
559 559 update: (current)
560 560 phases: 4 draft
561 561 $ hg update -q -C 2
562 562
563 563 on branch2 with branch1 not merged, so file1 should still exist:
564 564
565 565 $ hg id
566 566 45bbcd363bf0 (branch2)
567 567 $ hg st -A
568 568 C default
569 569 C file1
570 570 C file2
571 571 $ hg summary
572 572 parent: 2:45bbcd363bf0
573 573 file2
574 574 branch: branch2
575 575 commit: (clean)
576 576 update: 1 new changesets, 2 branch heads (merge)
577 577 phases: 4 draft
578 578
579 579 on branch2 with branch1 merged, so file1 should be gone:
580 580
581 581 $ hg merge
582 582 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
583 583 (branch merge, don't forget to commit)
584 584 $ hg ci -d '4 0' -m 'merge backout of branch1'
585 585 $ hg id
586 586 22149cdde76d (branch2) tip
587 587 $ hg st -A
588 588 C default
589 589 C file2
590 590 $ hg summary
591 591 parent: 4:22149cdde76d tip
592 592 merge backout of branch1
593 593 branch: branch2
594 594 commit: (clean)
595 595 update: (current)
596 596 phases: 5 draft
597 597
598 598 on branch1, so no file1 and file2:
599 599
600 600 $ hg co -C branch1
601 601 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
602 602 $ hg id
603 603 bf1602f437f3 (branch1)
604 604 $ hg st -A
605 605 C default
606 606 C file1
607 607 $ hg summary
608 608 parent: 1:bf1602f437f3
609 609 file1
610 610 branch: branch1
611 611 commit: (clean)
612 612 update: (current)
613 613 phases: 5 draft
614 614
615 615 $ cd ..
616 616
617 617 backout of empty changeset (issue4190)
618 618
619 619 $ hg init emptycommit
620 620 $ cd emptycommit
621 621
622 622 $ touch file1
623 623 $ hg ci -Aqm file1
624 624 $ hg branch -q branch1
625 625 $ hg ci -qm branch1
626 626 $ hg backout -v 1
627 627 resolving manifests
628 628 nothing changed
629 629 [1]
630 630
631 631 $ cd ..
632 632
633 633
634 634 Test usage of `hg resolve` in case of conflict
635 635 (issue4163)
636 636
637 637 $ hg init issue4163
638 638 $ cd issue4163
639 639 $ touch foo
640 640 $ hg add foo
641 641 $ cat > foo << EOF
642 642 > one
643 643 > two
644 644 > three
645 645 > four
646 646 > five
647 647 > six
648 648 > seven
649 649 > height
650 650 > nine
651 651 > ten
652 652 > EOF
653 653 $ hg ci -m 'initial'
654 654 $ cat > foo << EOF
655 655 > one
656 656 > two
657 657 > THREE
658 658 > four
659 659 > five
660 660 > six
661 661 > seven
662 662 > height
663 663 > nine
664 664 > ten
665 665 > EOF
666 666 $ hg ci -m 'capital three'
667 667 $ cat > foo << EOF
668 668 > one
669 669 > two
670 670 > THREE
671 671 > four
672 672 > five
673 673 > six
674 674 > seven
675 675 > height
676 676 > nine
677 677 > TEN
678 678 > EOF
679 679 $ hg ci -m 'capital ten'
680 680 $ hg backout -r 'desc("capital three")' --tool internal:fail
681 681 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
682 682 use 'hg resolve' to retry unresolved file merges
683 683 [1]
684 684 $ hg status
685 685 $ hg debugmergestate
686 686 * version 2 records
687 687 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
688 688 other: a30dd8addae3ce71b8667868478542bc417439e6
689 689 file extras: foo (ancestorlinknode = 91360952243723bd5b1138d5f26bd8c8564cb553)
690 690 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
691 691 local path: foo (flags "")
692 692 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
693 693 other path: foo (node f50039b486d6fa1a90ae51778388cad161f425ee)
694 694 $ mv .hg/merge/state2 .hg/merge/state2-moved
695 695 $ hg debugmergestate
696 696 * version 1 records
697 697 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
698 698 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
699 699 local path: foo (flags "")
700 700 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
701 701 other path: foo (node not stored in v1 format)
702 702 $ mv .hg/merge/state2-moved .hg/merge/state2
703 703 $ hg resolve -l # still unresolved
704 704 U foo
705 705 $ hg summary
706 706 parent: 2:b71750c4b0fd tip
707 707 capital ten
708 708 branch: default
709 709 commit: 1 unresolved (clean)
710 710 update: (current)
711 711 phases: 3 draft
712 712 $ hg resolve --all --debug
713 713 picked tool ':merge' for foo (binary False symlink False changedelete False)
714 714 merging foo
715 715 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
716 716 premerge successful
717 717 (no more unresolved files)
718 718 continue: hg commit
719 719 $ hg status
720 720 M foo
721 721 ? foo.orig
722 722 $ hg resolve -l
723 723 R foo
724 724 $ hg summary
725 725 parent: 2:b71750c4b0fd tip
726 726 capital ten
727 727 branch: default
728 728 commit: 1 modified, 1 unknown
729 729 update: (current)
730 730 phases: 3 draft
731 731 $ cat foo
732 732 one
733 733 two
734 734 three
735 735 four
736 736 five
737 737 six
738 738 seven
739 739 height
740 740 nine
741 741 TEN
742 742
743 743 --no-commit shouldn't commit
744 744
745 745 $ hg init a
746 746 $ cd a
747 747 $ for i in 1 2 3; do
748 748 > touch $i
749 749 > hg ci -Am $i
750 750 > done
751 751 adding 1
752 752 adding 2
753 753 adding 3
754 754 $ hg backout --no-commit .
755 755 removing 3
756 756 changeset cccc23d9d68f backed out, don't forget to commit.
757 757 $ hg revert -aq
758 758
759 759 --no-commit can't be used with --merge
760 760
761 761 $ hg backout --merge --no-commit 2
762 762 abort: cannot use --merge with --no-commit
763 763 [255]
@@ -1,406 +1,406 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcapabilities
76 76 debugcheckstate
77 77 debugcolor
78 78 debugcommands
79 79 debugcomplete
80 80 debugconfig
81 81 debugcreatestreamclonebundle
82 82 debugdag
83 83 debugdata
84 84 debugdate
85 85 debugdeltachain
86 86 debugdirstate
87 87 debugdiscovery
88 88 debugdownload
89 89 debugextensions
90 90 debugfileset
91 91 debugformat
92 92 debugfsinfo
93 93 debuggetbundle
94 94 debugignore
95 95 debugindex
96 96 debugindexdot
97 97 debuginstall
98 98 debugknown
99 99 debuglabelcomplete
100 100 debuglocks
101 101 debugmanifestfulltextcache
102 102 debugmergestate
103 103 debugnamecomplete
104 104 debugobsolete
105 105 debugpathcomplete
106 106 debugpeer
107 107 debugpickmergetool
108 108 debugpushkey
109 109 debugpvec
110 110 debugrebuilddirstate
111 111 debugrebuildfncache
112 112 debugrename
113 113 debugrevlog
114 114 debugrevlogindex
115 115 debugrevspec
116 116 debugserve
117 117 debugsetparents
118 118 debugssl
119 119 debugsub
120 120 debugsuccessorssets
121 121 debugtemplate
122 122 debuguigetpass
123 123 debuguiprompt
124 124 debugupdatecaches
125 125 debugupgraderepo
126 126 debugwalk
127 127 debugwhyunstable
128 128 debugwireargs
129 129 debugwireproto
130 130
131 131 Do not show the alias of a debug command if there are other candidates
132 132 (this should hide rawcommit)
133 133 $ hg debugcomplete r
134 134 recover
135 135 remove
136 136 rename
137 137 resolve
138 138 revert
139 139 rollback
140 140 root
141 141 Show the alias of a debug command if there are no other candidates
142 142 $ hg debugcomplete rawc
143 143
144 144
145 145 Show the global options
146 146 $ hg debugcomplete --options | sort
147 147 --color
148 148 --config
149 149 --cwd
150 150 --debug
151 151 --debugger
152 152 --encoding
153 153 --encodingmode
154 154 --help
155 155 --hidden
156 156 --noninteractive
157 157 --pager
158 158 --profile
159 159 --quiet
160 160 --repository
161 161 --time
162 162 --traceback
163 163 --verbose
164 164 --version
165 165 -R
166 166 -h
167 167 -q
168 168 -v
169 169 -y
170 170
171 171 Show the options for the "serve" command
172 172 $ hg debugcomplete --options serve | sort
173 173 --accesslog
174 174 --address
175 175 --certificate
176 176 --cmdserver
177 177 --color
178 178 --config
179 179 --cwd
180 180 --daemon
181 181 --daemon-postexec
182 182 --debug
183 183 --debugger
184 184 --encoding
185 185 --encodingmode
186 186 --errorlog
187 187 --help
188 188 --hidden
189 189 --ipv6
190 190 --name
191 191 --noninteractive
192 192 --pager
193 193 --pid-file
194 194 --port
195 195 --prefix
196 196 --print-url
197 197 --profile
198 198 --quiet
199 199 --repository
200 200 --stdio
201 201 --style
202 202 --subrepos
203 203 --templates
204 204 --time
205 205 --traceback
206 206 --verbose
207 207 --version
208 208 --web-conf
209 209 -6
210 210 -A
211 211 -E
212 212 -R
213 213 -S
214 214 -a
215 215 -d
216 216 -h
217 217 -n
218 218 -p
219 219 -q
220 220 -t
221 221 -v
222 222 -y
223 223
224 224 Show an error if we use --options with an ambiguous abbreviation
225 225 $ hg debugcomplete --options s
226 226 hg: command 's' is ambiguous:
227 227 serve showconfig status summary
228 228 [255]
229 229
230 230 Show all commands + options
231 231 $ hg debugcommands
232 232 add: include, exclude, subrepos, dry-run
233 233 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
234 234 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
235 235 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
236 236 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
237 237 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
238 238 forget: interactive, include, exclude, dry-run
239 239 init: ssh, remotecmd, insecure
240 240 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
241 241 merge: force, rev, preview, abort, tool
242 242 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
243 243 push: force, rev, bookmark, branch, new-branch, pushvars, ssh, remotecmd, insecure
244 244 remove: after, force, subrepos, include, exclude, dry-run
245 245 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
246 246 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
247 247 summary: remote
248 248 update: clean, check, merge, date, rev, tool
249 249 addremove: similarity, subrepos, include, exclude, dry-run
250 250 archive: no-decode, prefix, rev, type, subrepos, include, exclude
251 251 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
252 252 bisect: reset, good, bad, skip, extend, command, noupdate
253 253 bookmarks: force, rev, delete, rename, inactive, list, template
254 254 branch: force, clean, rev
255 255 branches: active, closed, template
256 256 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
257 257 cat: output, rev, decode, include, exclude, template
258 258 config: untrusted, edit, local, global, template
259 259 copy: after, force, include, exclude, dry-run
260 260 debugancestor:
261 261 debugapplystreamclonebundle:
262 262 debugbuilddag: mergeable-file, overwritten-file, new-file
263 263 debugbundle: all, part-type, spec
264 264 debugcapabilities:
265 265 debugcheckstate:
266 266 debugcolor: style
267 267 debugcommands:
268 268 debugcomplete: options
269 269 debugcreatestreamclonebundle:
270 270 debugdag: tags, branches, dots, spaces
271 271 debugdata: changelog, manifest, dir
272 272 debugdate: extended
273 273 debugdeltachain: changelog, manifest, dir, template
274 debugdirstate: nodates, datesort
274 debugdirstate: nodates, dates, datesort
275 275 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
276 276 debugdownload: output
277 277 debugextensions: template
278 278 debugfileset: rev, all-files, show-matcher, show-stage
279 279 debugformat: template
280 280 debugfsinfo:
281 281 debuggetbundle: head, common, type
282 282 debugignore:
283 283 debugindex: changelog, manifest, dir, template
284 284 debugindexdot: changelog, manifest, dir
285 285 debuginstall: template
286 286 debugknown:
287 287 debuglabelcomplete:
288 288 debuglocks: force-lock, force-wlock, set-lock, set-wlock
289 289 debugmanifestfulltextcache: clear, add
290 290 debugmergestate:
291 291 debugnamecomplete:
292 292 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
293 293 debugpathcomplete: full, normal, added, removed
294 294 debugpeer:
295 295 debugpickmergetool: rev, changedelete, include, exclude, tool
296 296 debugpushkey:
297 297 debugpvec:
298 298 debugrebuilddirstate: rev, minimal
299 299 debugrebuildfncache:
300 300 debugrename: rev
301 301 debugrevlog: changelog, manifest, dir, dump
302 302 debugrevlogindex: changelog, manifest, dir, format
303 303 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
304 304 debugserve: sshstdio, logiofd, logiofile
305 305 debugsetparents:
306 306 debugssl:
307 307 debugsub: rev
308 308 debugsuccessorssets: closest
309 309 debugtemplate: rev, define
310 310 debuguigetpass: prompt
311 311 debuguiprompt: prompt
312 312 debugupdatecaches:
313 313 debugupgraderepo: optimize, run
314 314 debugwalk: include, exclude
315 315 debugwhyunstable:
316 316 debugwireargs: three, four, five, ssh, remotecmd, insecure
317 317 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
318 318 files: rev, print0, include, exclude, template, subrepos
319 319 graft: rev, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
320 320 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
321 321 heads: rev, topo, active, closed, style, template
322 322 help: extension, command, keyword, system
323 323 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
324 324 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
325 325 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
326 326 locate: rev, print0, fullpath, include, exclude
327 327 manifest: rev, all, template
328 328 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
329 329 parents: rev, style, template
330 330 paths: template
331 331 phase: public, draft, secret, force, rev
332 332 recover:
333 333 rename: after, force, include, exclude, dry-run
334 334 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
335 335 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
336 336 rollback: dry-run, force
337 337 root:
338 338 tag: force, local, rev, remove, edit, message, date, user
339 339 tags: template
340 340 tip: patch, git, style, template
341 341 unbundle: update
342 342 verify:
343 343 version: template
344 344
345 345 $ hg init a
346 346 $ cd a
347 347 $ echo fee > fee
348 348 $ hg ci -q -Amfee
349 349 $ hg tag fee
350 350 $ mkdir fie
351 351 $ echo dead > fie/dead
352 352 $ echo live > fie/live
353 353 $ hg bookmark fo
354 354 $ hg branch -q fie
355 355 $ hg ci -q -Amfie
356 356 $ echo fo > fo
357 357 $ hg branch -qf default
358 358 $ hg ci -q -Amfo
359 359 $ echo Fum > Fum
360 360 $ hg ci -q -AmFum
361 361 $ hg bookmark Fum
362 362
363 363 Test debugpathcomplete
364 364
365 365 $ hg debugpathcomplete f
366 366 fee
367 367 fie
368 368 fo
369 369 $ hg debugpathcomplete -f f
370 370 fee
371 371 fie/dead
372 372 fie/live
373 373 fo
374 374
375 375 $ hg rm Fum
376 376 $ hg debugpathcomplete -r F
377 377 Fum
378 378
379 379 Test debugnamecomplete
380 380
381 381 $ hg debugnamecomplete
382 382 Fum
383 383 default
384 384 fee
385 385 fie
386 386 fo
387 387 tip
388 388 $ hg debugnamecomplete f
389 389 fee
390 390 fie
391 391 fo
392 392
393 393 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
394 394 used for completions in some shells.
395 395
396 396 $ hg debuglabelcomplete
397 397 Fum
398 398 default
399 399 fee
400 400 fie
401 401 fo
402 402 tip
403 403 $ hg debuglabelcomplete f
404 404 fee
405 405 fie
406 406 fo
@@ -1,146 +1,146 b''
1 1 This test makes sure that we don't mark a file as merged with its ancestor
2 2 when we do a merge.
3 3
4 4 $ cat <<EOF > merge
5 5 > from __future__ import print_function
6 6 > import sys, os
7 7 > print("merging for", os.path.basename(sys.argv[1]))
8 8 > EOF
9 9 $ HGMERGE="$PYTHON ../merge"; export HGMERGE
10 10
11 11 Creating base:
12 12
13 13 $ hg init a
14 14 $ cd a
15 15 $ echo 1 > foo
16 16 $ echo 1 > bar
17 17 $ echo 1 > baz
18 18 $ echo 1 > quux
19 19 $ hg add foo bar baz quux
20 20 $ hg commit -m "base"
21 21
22 22 $ cd ..
23 23 $ hg clone a b
24 24 updating to branch default
25 25 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 26
27 27 Creating branch a:
28 28
29 29 $ cd a
30 30 $ echo 2a > foo
31 31 $ echo 2a > bar
32 32 $ hg commit -m "branch a"
33 33
34 34 Creating branch b:
35 35
36 36 $ cd ..
37 37 $ cd b
38 38 $ echo 2b > foo
39 39 $ echo 2b > baz
40 40 $ hg commit -m "branch b"
41 41
42 42 We shouldn't have anything but n state here:
43 43
44 $ hg debugstate --nodates | grep -v "^n"
44 $ hg debugstate --no-dates | grep -v "^n"
45 45 [1]
46 46
47 47 Merging:
48 48
49 49 $ hg pull ../a
50 50 pulling from ../a
51 51 searching for changes
52 52 adding changesets
53 53 adding manifests
54 54 adding file changes
55 55 added 1 changesets with 2 changes to 2 files (+1 heads)
56 56 new changesets bdd988058d16
57 57 (run 'hg heads' to see heads, 'hg merge' to merge)
58 58
59 59 $ hg merge -v
60 60 resolving manifests
61 61 getting bar
62 62 merging foo
63 63 merging for foo
64 64 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
65 65 (branch merge, don't forget to commit)
66 66
67 67 $ echo 2m > foo
68 68 $ echo 2b > baz
69 69 $ echo new > quux
70 70
71 71 $ hg ci -m "merge"
72 72
73 73 main: we should have a merge here:
74 74
75 75 $ hg debugindex --changelog
76 76 rev linkrev nodeid p1 p2
77 77 0 0 cdca01651b96 000000000000 000000000000
78 78 1 1 f6718a9cb7f3 cdca01651b96 000000000000
79 79 2 2 bdd988058d16 cdca01651b96 000000000000
80 80 3 3 d8a521142a3c f6718a9cb7f3 bdd988058d16
81 81
82 82 log should show foo and quux changed:
83 83
84 84 $ hg log -v -r tip
85 85 changeset: 3:d8a521142a3c
86 86 tag: tip
87 87 parent: 1:f6718a9cb7f3
88 88 parent: 2:bdd988058d16
89 89 user: test
90 90 date: Thu Jan 01 00:00:00 1970 +0000
91 91 files: foo quux
92 92 description:
93 93 merge
94 94
95 95
96 96
97 97 foo: we should have a merge here:
98 98
99 99 $ hg debugindex foo
100 100 rev linkrev nodeid p1 p2
101 101 0 0 b8e02f643373 000000000000 000000000000
102 102 1 1 2ffeddde1b65 b8e02f643373 000000000000
103 103 2 2 33d1fb69067a b8e02f643373 000000000000
104 104 3 3 aa27919ee430 2ffeddde1b65 33d1fb69067a
105 105
106 106 bar: we should not have a merge here:
107 107
108 108 $ hg debugindex bar
109 109 rev linkrev nodeid p1 p2
110 110 0 0 b8e02f643373 000000000000 000000000000
111 111 1 2 33d1fb69067a b8e02f643373 000000000000
112 112
113 113 baz: we should not have a merge here:
114 114
115 115 $ hg debugindex baz
116 116 rev linkrev nodeid p1 p2
117 117 0 0 b8e02f643373 000000000000 000000000000
118 118 1 1 2ffeddde1b65 b8e02f643373 000000000000
119 119
120 120 quux: we should not have a merge here:
121 121
122 122 $ hg debugindex quux
123 123 rev linkrev nodeid p1 p2
124 124 0 0 b8e02f643373 000000000000 000000000000
125 125 1 3 6128c0f33108 b8e02f643373 000000000000
126 126
127 127 Manifest entries should match tips of all files:
128 128
129 129 $ hg manifest --debug
130 130 33d1fb69067a0139622a3fa3b7ba1cdb1367972e 644 bar
131 131 2ffeddde1b65b4827f6746174a145474129fa2ce 644 baz
132 132 aa27919ee4303cfd575e1fb932dd64d75aa08be4 644 foo
133 133 6128c0f33108e8cfbb4e0824d13ae48b466d7280 644 quux
134 134
135 135 Everything should be clean now:
136 136
137 137 $ hg status
138 138
139 139 $ hg verify
140 140 checking changesets
141 141 checking manifests
142 142 crosschecking files in changesets and manifests
143 143 checking files
144 144 checked 4 changesets with 10 changes to 4 files
145 145
146 146 $ cd ..
@@ -1,795 +1,795 b''
1 1 #require no-reposimplestore
2 2
3 3 This file focuses mainly on updating largefiles in the working
4 4 directory (and ".hg/largefiles/dirstate")
5 5
6 6 $ cat >> $HGRCPATH <<EOF
7 7 > [ui]
8 8 > merge = internal:fail
9 9 > [extensions]
10 10 > largefiles =
11 11 > [extdiff]
12 12 > # for portability:
13 13 > pdiff = sh "$RUNTESTDIR/pdiff"
14 14 > EOF
15 15
16 16 $ hg init repo
17 17 $ cd repo
18 18
19 19 $ echo large1 > large1
20 20 $ echo large2 > large2
21 21 $ hg add --large large1 large2
22 22 $ echo normal1 > normal1
23 23 $ hg add normal1
24 24 $ hg commit -m '#0'
25 25 $ echo 'large1 in #1' > large1
26 26 $ echo 'normal1 in #1' > normal1
27 27 $ hg commit -m '#1'
28 28 $ hg pdiff -r '.^' --config extensions.extdiff=
29 29 diff -Nru repo.0d9d9b8dc9a3/.hglf/large1 repo/.hglf/large1
30 30 --- repo.0d9d9b8dc9a3/.hglf/large1 * (glob)
31 31 +++ repo/.hglf/large1 * (glob)
32 32 @@ -1* +1* @@ (glob)
33 33 -4669e532d5b2c093a78eca010077e708a071bb64
34 34 +58e24f733a964da346e2407a2bee99d9001184f5
35 35 diff -Nru repo.0d9d9b8dc9a3/normal1 repo/normal1
36 36 --- repo.0d9d9b8dc9a3/normal1 * (glob)
37 37 +++ repo/normal1 * (glob)
38 38 @@ -1* +1* @@ (glob)
39 39 -normal1
40 40 +normal1 in #1
41 41 [1]
42 42 $ hg update -q -C 0
43 43 $ echo 'large2 in #2' > large2
44 44 $ hg commit -m '#2'
45 45 created new head
46 46
47 47 Test that update also updates the lfdirstate of 'unsure' largefiles after
48 48 hashing them:
49 49
50 50 The previous operations will usually have left us with largefiles with a mtime
51 51 within the same second as the dirstate was written.
52 52 The lfdirstate entries will thus have been written with an invalidated/unset
53 53 mtime to make sure further changes within the same second is detected.
54 54 We will however occasionally be "lucky" and get a tick between writing
55 55 largefiles and writing dirstate so we get valid lfdirstate timestamps. The
56 56 following verification is thus disabled but can be verified manually.
57 57
58 58 #if false
59 59 $ hg debugdirstate --large --nodate
60 60 n 644 7 unset large1
61 61 n 644 13 unset large2
62 62 #endif
63 63
64 64 Wait to make sure we get a tick so the mtime of the largefiles become valid.
65 65
66 66 $ sleep 1
67 67
68 68 A linear merge will update standins before performing the actual merge. It will
69 69 do a lfdirstate status walk and find 'unset'/'unsure' files, hash them, and
70 70 update the corresponding standins.
71 71 Verify that it actually marks the clean files as clean in lfdirstate so
72 72 we don't have to hash them again next time we update.
73 73
74 74 $ hg up
75 75 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76 updated to "f74e50bd9e55: #2"
77 77 1 other heads for branch "default"
78 78 $ hg debugdirstate --large --nodate
79 79 n 644 7 set large1
80 80 n 644 13 set large2
81 81
82 82 Test that lfdirstate keeps track of last modification of largefiles and
83 83 prevents unnecessary hashing of content - also after linear/noop update
84 84
85 85 $ sleep 1
86 86 $ hg st
87 87 $ hg debugdirstate --large --nodate
88 88 n 644 7 set large1
89 89 n 644 13 set large2
90 90 $ hg up
91 91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 92 updated to "f74e50bd9e55: #2"
93 93 1 other heads for branch "default"
94 94 $ hg debugdirstate --large --nodate
95 95 n 644 7 set large1
96 96 n 644 13 set large2
97 97
98 98 Test that "hg merge" updates largefiles from "other" correctly
99 99
100 100 (getting largefiles from "other" normally)
101 101
102 102 $ hg status -A large1
103 103 C large1
104 104 $ cat large1
105 105 large1
106 106 $ cat .hglf/large1
107 107 4669e532d5b2c093a78eca010077e708a071bb64
108 108 $ hg merge --config debug.dirstate.delaywrite=2
109 109 getting changed largefiles
110 110 1 largefiles updated, 0 removed
111 111 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 112 (branch merge, don't forget to commit)
113 113 $ hg status -A large1
114 114 M large1
115 115 $ cat large1
116 116 large1 in #1
117 117 $ cat .hglf/large1
118 118 58e24f733a964da346e2407a2bee99d9001184f5
119 119 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
120 120 -4669e532d5b2c093a78eca010077e708a071bb64
121 121 +58e24f733a964da346e2407a2bee99d9001184f5
122 122
123 123 (getting largefiles from "other" via conflict prompt)
124 124
125 125 $ hg update -q -C 2
126 126 $ echo 'large1 in #3' > large1
127 127 $ echo 'normal1 in #3' > normal1
128 128 $ hg commit -m '#3'
129 129 $ cat .hglf/large1
130 130 e5bb990443d6a92aaf7223813720f7566c9dd05b
131 131 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
132 132 > o
133 133 > EOF
134 134 largefile large1 has a merge conflict
135 135 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
136 136 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
137 137 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
138 138 merging normal1
139 139 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
140 140 getting changed largefiles
141 141 1 largefiles updated, 0 removed
142 142 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
143 143 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
144 144 [1]
145 145 $ hg status -A large1
146 146 M large1
147 147 $ cat large1
148 148 large1 in #1
149 149 $ cat .hglf/large1
150 150 58e24f733a964da346e2407a2bee99d9001184f5
151 151 $ rm normal1.orig
152 152
153 153 (merge non-existing largefiles from "other" via conflict prompt -
154 154 make sure the following commit doesn't abort in a confusing way when trying to
155 155 mark the non-existing file as normal in lfdirstate)
156 156
157 157 $ mv .hg/largefiles/58e24f733a964da346e2407a2bee99d9001184f5 .
158 158 $ hg update -q -C 3
159 159 $ hg merge --config largefiles.usercache=not --config debug.dirstate.delaywrite=2 --tool :local --config ui.interactive=True <<EOF
160 160 > o
161 161 > EOF
162 162 largefile large1 has a merge conflict
163 163 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
164 164 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
165 165 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
166 166 getting changed largefiles
167 167 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
168 168 0 largefiles updated, 0 removed
169 169 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
170 170 (branch merge, don't forget to commit)
171 171 $ hg commit -m '1-2-3 testing' --config largefiles.usercache=not
172 172 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from local store
173 173 $ hg up -C . --config largefiles.usercache=not
174 174 getting changed largefiles
175 175 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
176 176 0 largefiles updated, 0 removed
177 177 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 178 $ hg st large1
179 179 ! large1
180 180 $ hg rollback -q
181 181 $ mv 58e24f733a964da346e2407a2bee99d9001184f5 .hg/largefiles/
182 182
183 183 Test that "hg revert -r REV" updates largefiles from "REV" correctly
184 184
185 185 $ hg update -q -C 3
186 186 $ hg status -A large1
187 187 C large1
188 188 $ cat large1
189 189 large1 in #3
190 190 $ cat .hglf/large1
191 191 e5bb990443d6a92aaf7223813720f7566c9dd05b
192 192 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
193 193 -4669e532d5b2c093a78eca010077e708a071bb64
194 194 +58e24f733a964da346e2407a2bee99d9001184f5
195 195 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
196 196 $ hg status -A large1
197 197 M large1
198 198 $ cat large1
199 199 large1 in #1
200 200 $ cat .hglf/large1
201 201 58e24f733a964da346e2407a2bee99d9001184f5
202 202
203 203 Test that "hg rollback" restores status of largefiles correctly
204 204
205 205 $ hg update -C -q
206 206 $ hg remove large1
207 207 $ test -f .hglf/large1
208 208 [1]
209 209 $ hg forget large2
210 210 $ test -f .hglf/large2
211 211 [1]
212 212 $ echo largeX > largeX
213 213 $ hg add --large largeX
214 214 $ cat .hglf/largeX
215 215
216 216 $ hg commit -m 'will be rollback-ed soon'
217 217 $ echo largeY > largeY
218 218 $ hg add --large largeY
219 219
220 220 $ hg status -A large1
221 221 large1: $ENOENT$
222 222
223 223 $ hg status -A large2
224 224 ? large2
225 225 $ hg status -A largeX
226 226 C largeX
227 227 $ hg status -A largeY
228 228 A largeY
229 229 $ hg rollback
230 230 repository tip rolled back to revision 3 (undo commit)
231 231 working directory now based on revision 3
232 232 $ hg status -A large1
233 233 R large1
234 234 $ test -f .hglf/large1
235 235 [1]
236 236 $ hg status -A large2
237 237 R large2
238 238 $ test -f .hglf/large2
239 239 [1]
240 240 $ hg status -A largeX
241 241 A largeX
242 242 $ cat .hglf/largeX
243 243
244 244 $ hg status -A largeY
245 245 ? largeY
246 246 $ test -f .hglf/largeY
247 247 [1]
248 248 $ rm largeY
249 249
250 250 Test that "hg rollback" restores standins correctly
251 251
252 252 $ hg commit -m 'will be rollback-ed soon'
253 253 $ hg update -q -C 2
254 254 $ cat large1
255 255 large1
256 256 $ cat .hglf/large1
257 257 4669e532d5b2c093a78eca010077e708a071bb64
258 258 $ cat large2
259 259 large2 in #2
260 260 $ cat .hglf/large2
261 261 3cfce6277e7668985707b6887ce56f9f62f6ccd9
262 262
263 263 $ hg rollback -q -f
264 264 $ cat large1
265 265 large1
266 266 $ cat .hglf/large1
267 267 4669e532d5b2c093a78eca010077e708a071bb64
268 268 $ cat large2
269 269 large2 in #2
270 270 $ cat .hglf/large2
271 271 3cfce6277e7668985707b6887ce56f9f62f6ccd9
272 272
273 273 (rollback the parent of the working directory, when the parent of it
274 274 is not branch-tip)
275 275
276 276 $ hg update -q -C 1
277 277 $ cat .hglf/large1
278 278 58e24f733a964da346e2407a2bee99d9001184f5
279 279 $ cat .hglf/large2
280 280 1deebade43c8c498a3c8daddac0244dc55d1331d
281 281
282 282 $ echo normalX > normalX
283 283 $ hg add normalX
284 284 $ hg commit -m 'will be rollback-ed soon'
285 285 $ hg rollback -q
286 286
287 287 $ cat .hglf/large1
288 288 58e24f733a964da346e2407a2bee99d9001184f5
289 289 $ cat .hglf/large2
290 290 1deebade43c8c498a3c8daddac0244dc55d1331d
291 291 $ rm normalX
292 292
293 293 Test that "hg status" shows status of largefiles correctly just after
294 294 automated commit like rebase/transplant
295 295
296 296 $ cat >> .hg/hgrc <<EOF
297 297 > [extensions]
298 298 > rebase =
299 299 > strip =
300 300 > transplant =
301 301 > EOF
302 302 $ hg update -q -C 1
303 303 $ hg remove large1
304 304 $ echo largeX > largeX
305 305 $ hg add --large largeX
306 306 $ hg commit -m '#4'
307 307
308 308 $ hg rebase -s 1 -d 2 --keep
309 309 rebasing 1:72518492caa6 "#1"
310 310 rebasing 4:07d6153b5c04 "#4" (tip)
311 311
312 312 $ hg status -A large1
313 313 large1: $ENOENT$
314 314
315 315 $ hg status -A largeX
316 316 C largeX
317 317 $ hg strip -q 5
318 318
319 319 $ hg update -q -C 2
320 320 $ hg transplant -q 1 4
321 321
322 322 $ hg status -A large1
323 323 large1: $ENOENT$
324 324
325 325 $ hg status -A largeX
326 326 C largeX
327 327 $ hg strip -q 5
328 328
329 329 $ hg update -q -C 2
330 330 $ hg transplant -q --merge 1 --merge 4
331 331
332 332 $ hg status -A large1
333 333 large1: $ENOENT$
334 334
335 335 $ hg status -A largeX
336 336 C largeX
337 337 $ hg strip -q 5
338 338
339 339 Test that linear merge can detect modification (and conflict) correctly
340 340
341 341 (linear merge without conflict)
342 342
343 343 $ echo 'large2 for linear merge (no conflict)' > large2
344 344 $ hg update 3 --config debug.dirstate.delaywrite=2
345 345 getting changed largefiles
346 346 1 largefiles updated, 0 removed
347 347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 348 $ hg status -A large2
349 349 M large2
350 350 $ cat large2
351 351 large2 for linear merge (no conflict)
352 352 $ cat .hglf/large2
353 353 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
354 354
355 355 (linear merge with conflict, choosing "other")
356 356
357 357 $ hg update -q -C 2
358 358 $ echo 'large1 for linear merge (conflict)' > large1
359 359 $ hg update 3 --config ui.interactive=True <<EOF
360 360 > o
361 361 > EOF
362 362 largefile large1 has a merge conflict
363 363 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
364 364 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
365 365 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? o
366 366 getting changed largefiles
367 367 1 largefiles updated, 0 removed
368 368 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
369 369 $ hg status -A large1
370 370 C large1
371 371 $ cat large1
372 372 large1 in #3
373 373 $ cat .hglf/large1
374 374 e5bb990443d6a92aaf7223813720f7566c9dd05b
375 375
376 376 (linear merge with conflict, choosing "local")
377 377
378 378 $ hg update -q -C 2
379 379 $ echo 'large1 for linear merge (conflict)' > large1
380 380 $ hg update 3 --config debug.dirstate.delaywrite=2
381 381 largefile large1 has a merge conflict
382 382 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
383 383 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
384 384 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
385 385 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
386 386 $ hg status -A large1
387 387 M large1
388 388 $ cat large1
389 389 large1 for linear merge (conflict)
390 390 $ cat .hglf/large1
391 391 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
392 392
393 393 Test a linear merge to a revision containing same-name normal file
394 394
395 395 $ hg update -q -C 3
396 396 $ hg remove large2
397 397 $ echo 'large2 as normal file' > large2
398 398 $ hg add large2
399 399 $ echo 'large3 as normal file' > large3
400 400 $ hg add large3
401 401 $ hg commit -m '#5'
402 402 $ hg manifest
403 403 .hglf/large1
404 404 large2
405 405 large3
406 406 normal1
407 407
408 408 (modified largefile is already switched to normal)
409 409
410 410 $ hg update -q -C 2
411 411 $ echo 'modified large2 for linear merge' > large2
412 412 $ hg update -q 5
413 413 remote turned local largefile large2 into a normal file
414 414 keep (l)argefile or use (n)ormal file? l
415 $ hg debugdirstate --nodates | grep large2
415 $ hg debugdirstate --no-dates | grep large2
416 416 a 0 -1 unset .hglf/large2
417 417 r 0 0 set large2
418 418 $ hg status -A large2
419 419 A large2
420 420 $ cat large2
421 421 modified large2 for linear merge
422 422
423 423 (added largefile is already committed as normal)
424 424
425 425 $ hg update -q -C 2
426 426 $ echo 'large3 as large file for linear merge' > large3
427 427 $ hg add --large large3
428 428 $ hg update -q 5
429 429 remote turned local largefile large3 into a normal file
430 430 keep (l)argefile or use (n)ormal file? l
431 $ hg debugdirstate --nodates | grep large3
431 $ hg debugdirstate --no-dates | grep large3
432 432 a 0 -1 unset .hglf/large3
433 433 r 0 0 set large3
434 434 $ hg status -A large3
435 435 A large3
436 436 $ cat large3
437 437 large3 as large file for linear merge
438 438 $ rm -f large3 .hglf/large3
439 439
440 440 Test that the internal linear merging works correctly
441 441 (both heads are stripped to keep pairing of revision number and commit log)
442 442
443 443 $ hg update -q -C 2
444 444 $ hg strip 3 4
445 445 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-2e7b195d-backup.hg
446 446 $ mv .hg/strip-backup/9530e27857f7-2e7b195d-backup.hg $TESTTMP
447 447
448 448 (internal linear merging at "hg pull --update")
449 449
450 450 $ echo 'large1 for linear merge (conflict)' > large1
451 451 $ echo 'large2 for linear merge (conflict with normal file)' > large2
452 452 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
453 453 pulling from $TESTTMP/9530e27857f7-2e7b195d-backup.hg
454 454 searching for changes
455 455 adding changesets
456 456 adding manifests
457 457 adding file changes
458 458 added 3 changesets with 5 changes to 5 files
459 459 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
460 460 remote turned local largefile large2 into a normal file
461 461 keep (l)argefile or use (n)ormal file? l
462 462 largefile large1 has a merge conflict
463 463 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
464 464 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
465 465 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
466 466 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
467 467 updated to "d65e59e952a9: #5"
468 468 1 other heads for branch "default"
469 469
470 470 $ hg status -A large1
471 471 M large1
472 472 $ cat large1
473 473 large1 for linear merge (conflict)
474 474 $ cat .hglf/large1
475 475 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
476 476 $ hg status -A large2
477 477 A large2
478 478 $ cat large2
479 479 large2 for linear merge (conflict with normal file)
480 480 $ cat .hglf/large2
481 481 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
482 482
483 483 (internal linear merging at "hg unbundle --update")
484 484
485 485 $ hg update -q -C 2
486 486 $ hg rollback -q
487 487
488 488 $ echo 'large1 for linear merge (conflict)' > large1
489 489 $ echo 'large2 for linear merge (conflict with normal file)' > large2
490 490 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
491 491 adding changesets
492 492 adding manifests
493 493 adding file changes
494 494 added 3 changesets with 5 changes to 5 files
495 495 new changesets 9530e27857f7:d65e59e952a9 (3 drafts)
496 496 remote turned local largefile large2 into a normal file
497 497 keep (l)argefile or use (n)ormal file? l
498 498 largefile large1 has a merge conflict
499 499 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
500 500 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
501 501 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
502 502 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
503 503 updated to "d65e59e952a9: #5"
504 504 1 other heads for branch "default"
505 505
506 506 $ hg status -A large1
507 507 M large1
508 508 $ cat large1
509 509 large1 for linear merge (conflict)
510 510 $ cat .hglf/large1
511 511 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
512 512 $ hg status -A large2
513 513 A large2
514 514 $ cat large2
515 515 large2 for linear merge (conflict with normal file)
516 516 $ cat .hglf/large2
517 517 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
518 518
519 519 (internal linear merging in subrepo at "hg update")
520 520
521 521 $ cd ..
522 522 $ hg init subparent
523 523 $ cd subparent
524 524
525 525 $ hg clone -q -u 2 ../repo sub
526 526 $ cat > .hgsub <<EOF
527 527 > sub = sub
528 528 > EOF
529 529 $ hg add .hgsub
530 530 $ hg commit -m '#0@parent'
531 531 $ cat .hgsubstate
532 532 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
533 533 $ hg -R sub update -q
534 534 $ hg commit -m '#1@parent'
535 535 $ cat .hgsubstate
536 536 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
537 537 $ hg update -q 0
538 538
539 539 $ echo 'large1 for linear merge (conflict)' > sub/large1
540 540 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
541 541 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
542 542 > m
543 543 > r
544 544 > l
545 545 > l
546 546 > EOF
547 547 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
548 548 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
549 549 subrepository sources for sub differ (in checked out version)
550 550 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
551 551 remote turned local largefile large2 into a normal file
552 552 keep (l)argefile or use (n)ormal file? l
553 553 largefile large1 has a merge conflict
554 554 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
555 555 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
556 556 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
557 557 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
558 558 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
559 559
560 560 $ hg -R sub status -A sub/large1
561 561 M sub/large1
562 562 $ cat sub/large1
563 563 large1 for linear merge (conflict)
564 564 $ cat sub/.hglf/large1
565 565 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
566 566 $ hg -R sub status -A sub/large2
567 567 A sub/large2
568 568 $ cat sub/large2
569 569 large2 for linear merge (conflict with normal file)
570 570 $ cat sub/.hglf/large2
571 571 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
572 572
573 573 $ cd ..
574 574 $ cd repo
575 575
576 576 Test that rebase updates largefiles in the working directory even if
577 577 it is aborted by conflict.
578 578
579 579 $ hg update -q -C 3
580 580 $ cat .hglf/large1
581 581 e5bb990443d6a92aaf7223813720f7566c9dd05b
582 582 $ cat large1
583 583 large1 in #3
584 584 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
585 585 > o
586 586 > EOF
587 587 rebasing 1:72518492caa6 "#1"
588 588 largefile large1 has a merge conflict
589 589 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
590 590 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
591 591 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
592 592 merging normal1
593 593 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
594 594 unresolved conflicts (see hg resolve, then hg rebase --continue)
595 595 [1]
596 596 $ cat .hglf/large1
597 597 58e24f733a964da346e2407a2bee99d9001184f5
598 598 $ cat large1
599 599 large1 in #1
600 600 $ rm normal1.orig
601 601
602 602 Test that rebase updates standins for manually modified largefiles at
603 603 the 1st commit of resuming.
604 604
605 605 $ echo "manually modified before 'hg rebase --continue'" > large1
606 606 $ hg resolve -m normal1
607 607 (no more unresolved files)
608 608 continue: hg rebase --continue
609 609 $ hg rebase --continue --config ui.interactive=True <<EOF
610 610 > c
611 611 > EOF
612 612 rebasing 1:72518492caa6 "#1"
613 613 rebasing 4:07d6153b5c04 "#4"
614 614 file '.hglf/large1' was deleted in other [source] but was modified in local [dest].
615 615 What do you want to do?
616 616 use (c)hanged version, (d)elete, or leave (u)nresolved? c
617 617
618 618 $ hg diff -c "tip~1" --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
619 619 -e5bb990443d6a92aaf7223813720f7566c9dd05b
620 620 +8a4f783556e7dea21139ca0466eafce954c75c13
621 621 $ rm -f large1
622 622 $ hg update -q -C tip
623 623 $ cat large1
624 624 manually modified before 'hg rebase --continue'
625 625
626 626 Test that transplant updates largefiles, of which standins are safely
627 627 changed, even if it is aborted by conflict of other.
628 628
629 629 $ hg update -q -C 5
630 630 $ cat .hglf/large1
631 631 e5bb990443d6a92aaf7223813720f7566c9dd05b
632 632 $ cat large1
633 633 large1 in #3
634 634 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
635 635 +fa44618ea25181aff4f48b70428294790cec9f61
636 636 $ hg transplant 4
637 637 applying 07d6153b5c04
638 638 patching file .hglf/large1
639 639 Hunk #1 FAILED at 0
640 640 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
641 641 patch failed to apply
642 642 abort: fix up the working directory and run hg transplant --continue
643 643 [255]
644 644 $ hg status -A large1
645 645 C large1
646 646 $ cat .hglf/large1
647 647 e5bb990443d6a92aaf7223813720f7566c9dd05b
648 648 $ cat large1
649 649 large1 in #3
650 650 $ hg status -A largeX
651 651 A largeX
652 652 $ cat .hglf/largeX
653 653 fa44618ea25181aff4f48b70428294790cec9f61
654 654 $ cat largeX
655 655 largeX
656 656
657 657 Test that transplant updates standins for manually modified largefiles
658 658 at the 1st commit of resuming.
659 659
660 660 $ echo "manually modified before 'hg transplant --continue'" > large1
661 661 $ hg transplant --continue
662 662 07d6153b5c04 transplanted as f1bf30eb88cc
663 663 $ hg diff -c tip .hglf/large1 | grep '^[+-][0-9a-z]'
664 664 -e5bb990443d6a92aaf7223813720f7566c9dd05b
665 665 +6a4f36d4075fbe0f30ec1d26ca44e63c05903671
666 666 $ rm -f large1
667 667 $ hg update -q -C tip
668 668 $ cat large1
669 669 manually modified before 'hg transplant --continue'
670 670
671 671 Test that "hg status" doesn't show removal of largefiles not managed
672 672 in the target context.
673 673
674 674 $ hg update -q -C 4
675 675 $ hg remove largeX
676 676 $ hg status -A largeX
677 677 R largeX
678 678 $ hg status -A --rev '.^1' largeX
679 679
680 680 #if execbit
681 681
682 682 Test that "hg status" against revisions other than parent notices exec
683 683 bit changes of largefiles.
684 684
685 685 $ hg update -q -C 4
686 686
687 687 (the case that large2 doesn't have exec bit in the target context but
688 688 in the working context)
689 689
690 690 $ chmod +x large2
691 691 $ hg status -A --rev 0 large2
692 692 M large2
693 693 $ hg commit -m 'chmod +x large2'
694 694
695 695 (the case that large2 has exec bit in the target context but not in
696 696 the working context)
697 697
698 698 $ echo dummy > dummy
699 699 $ hg add dummy
700 700 $ hg commit -m 'revision for separation'
701 701 $ chmod -x large2
702 702 $ hg status -A --rev '.^1' large2
703 703 M large2
704 704
705 705 #else
706 706
707 707 Test that "hg status" against revisions other than parent ignores exec
708 708 bit correctly on the platform being unaware of it.
709 709
710 710 $ hg update -q -C 4
711 711
712 712 $ cat > ../exec-bit.patch <<EOF
713 713 > # HG changeset patch
714 714 > # User test
715 715 > # Date 0 0
716 716 > # Thu Jan 01 00:00:00 1970 +0000
717 717 > # Node ID be1b433a65b12b27b5519d92213e14f7e1769b90
718 718 > # Parent 07d6153b5c04313efb75deec9ba577de7faeb727
719 719 > chmod +x large2
720 720 >
721 721 > diff --git a/.hglf/large2 b/.hglf/large2
722 722 > old mode 100644
723 723 > new mode 100755
724 724 > EOF
725 725 $ hg import --exact --bypass ../exec-bit.patch
726 726 applying ../exec-bit.patch
727 727 $ hg status -A --rev tip large2
728 728 C large2
729 729
730 730 #endif
731 731
732 732 The fileset revset is evaluated for each revision, instead of once on wdir(),
733 733 and then patterns matched on each revision. Here, no exec bits are set in
734 734 wdir(), but a matching revision is detected.
735 735
736 736 (Teach large2 is not an executable. Maybe this is a bug of largefiles.)
737 737 #if execbit
738 738 $ chmod -x .hglf/large2
739 739 #endif
740 740
741 741 $ hg files 'set:exec()'
742 742 [1]
743 743 $ hg log -qr 'file("set:exec()")'
744 744 9:be1b433a65b1
745 745
746 746 Test a fatal error interrupting an update. Verify that status report dirty
747 747 files correctly after an interrupted update. Also verify that checking all
748 748 hashes reveals it isn't clean.
749 749
750 750 Start with clean dirstates:
751 751 $ hg up --quiet --clean --rev "8^"
752 752 $ sleep 1
753 753 $ hg st
754 754 Update standins without updating largefiles - large1 is modified and largeX is
755 755 added:
756 756 $ cat << EOF > ../crashupdatelfiles.py
757 757 > import hgext.largefiles.lfutil
758 758 > def getlfilestoupdate(oldstandins, newstandins):
759 759 > raise SystemExit(7)
760 760 > hgext.largefiles.lfutil.getlfilestoupdate = getlfilestoupdate
761 761 > EOF
762 762 $ hg up -Cr "8" --config extensions.crashupdatelfiles=../crashupdatelfiles.py
763 763 [7]
764 764 Check large1 content and status ... and that update will undo modifications:
765 765 $ cat large1
766 766 large1 in #3
767 767 $ hg st
768 768 M large1
769 769 ! largeX
770 770 $ hg up -Cr .
771 771 getting changed largefiles
772 772 2 largefiles updated, 0 removed
773 773 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 774 $ cat large1
775 775 manually modified before 'hg transplant --continue'
776 776 $ hg st
777 777 Force largefiles rehashing and check that all changes have been caught by
778 778 status and update:
779 779 $ rm .hg/largefiles/dirstate
780 780 $ hg st
781 781
782 782 $ cd ..
783 783
784 784 Test that "hg convert" avoids copying largefiles from the working
785 785 directory into store, because "hg convert" doesn't update largefiles
786 786 in the working directory (removing files under ".cache/largefiles"
787 787 forces "hg convert" to copy corresponding largefiles)
788 788
789 789 $ cat >> $HGRCPATH <<EOF
790 790 > [extensions]
791 791 > convert =
792 792 > EOF
793 793
794 794 $ rm $TESTTMP/.cache/largefiles/6a4f36d4075fbe0f30ec1d26ca44e63c05903671
795 795 $ hg convert -q repo repo.converted
@@ -1,1889 +1,1889 b''
1 1 This file used to contains all largefile tests.
2 2 Do not add any new tests in this file as it his already far too long to run.
3 3
4 4 It contains all the testing of the basic concepts of large file in a single block.
5 5
6 6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
7 7 $ mkdir "${USERCACHE}"
8 8 $ cat >> $HGRCPATH <<EOF
9 9 > [extensions]
10 10 > largefiles=
11 11 > purge=
12 12 > rebase=
13 13 > transplant=
14 14 > [phases]
15 15 > publish=False
16 16 > [largefiles]
17 17 > minsize=2
18 18 > patterns=glob:**.dat
19 19 > usercache=${USERCACHE}
20 20 > [hooks]
21 21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
22 22 > EOF
23 23
24 24 Create the repo with a couple of revisions of both large and normal
25 25 files.
26 26 Test status and dirstate of largefiles and that summary output is correct.
27 27
28 28 $ hg init a
29 29 $ cd a
30 30 $ mkdir sub
31 31 $ echo normal1 > normal1
32 32 $ echo normal2 > sub/normal2
33 33 $ echo large1 > large1
34 34 $ echo large2 > sub/large2
35 35 $ hg add normal1 sub/normal2
36 36 $ hg add --large large1 sub/large2
37 37 $ hg commit -m "add files"
38 38 Invoking status precommit hook
39 39 A large1
40 40 A normal1
41 41 A sub/large2
42 42 A sub/normal2
43 43 $ touch large1 sub/large2
44 44 $ sleep 1
45 45 $ hg st
46 $ hg debugstate --nodates
46 $ hg debugstate --no-dates
47 47 n 644 41 set .hglf/large1
48 48 n 644 41 set .hglf/sub/large2
49 49 n 644 8 set normal1
50 50 n 644 8 set sub/normal2
51 $ hg debugstate --large --nodates
51 $ hg debugstate --large --no-dates
52 52 n 644 7 set large1
53 53 n 644 7 set sub/large2
54 54 $ echo normal11 > normal1
55 55 $ echo normal22 > sub/normal2
56 56 $ echo large11 > large1
57 57 $ echo large22 > sub/large2
58 58 $ hg commit -m "edit files"
59 59 Invoking status precommit hook
60 60 M large1
61 61 M normal1
62 62 M sub/large2
63 63 M sub/normal2
64 64 $ hg sum --large
65 65 parent: 1:ce8896473775 tip
66 66 edit files
67 67 branch: default
68 68 commit: (clean)
69 69 update: (current)
70 70 phases: 2 draft
71 71 largefiles: (no remote repo)
72 72
73 73 Commit preserved largefile contents.
74 74
75 75 $ cat normal1
76 76 normal11
77 77 $ cat large1
78 78 large11
79 79 $ cat sub/normal2
80 80 normal22
81 81 $ cat sub/large2
82 82 large22
83 83
84 84 Test status, subdir and unknown files
85 85
86 86 $ echo unknown > sub/unknown
87 87 $ hg st --all
88 88 ? sub/unknown
89 89 C large1
90 90 C normal1
91 91 C sub/large2
92 92 C sub/normal2
93 93 $ hg st --all sub
94 94 ? sub/unknown
95 95 C sub/large2
96 96 C sub/normal2
97 97 $ rm sub/unknown
98 98
99 99 Test messages and exit codes for remove warning cases
100 100
101 101 $ hg remove -A large1
102 102 not removing large1: file still exists
103 103 [1]
104 104 $ echo 'modified' > large1
105 105 $ hg remove large1
106 106 not removing large1: file is modified (use -f to force removal)
107 107 [1]
108 108 $ echo 'new' > normalnew
109 109 $ hg add normalnew
110 110 $ echo 'new' > largenew
111 111 $ hg add --large normalnew
112 112 normalnew already tracked!
113 113 $ hg remove normalnew largenew
114 114 not removing largenew: file is untracked
115 115 not removing normalnew: file has been marked for add (use 'hg forget' to undo add)
116 116 [1]
117 117 $ rm normalnew largenew
118 118 $ hg up -Cq
119 119
120 120 Remove both largefiles and normal files.
121 121
122 122 $ hg remove normal1 large1
123 123 $ hg status large1
124 124 R large1
125 125 $ hg commit -m "remove files"
126 126 Invoking status precommit hook
127 127 R large1
128 128 R normal1
129 129 $ ls
130 130 sub
131 131 $ echo "testlargefile" > large1-test
132 132 $ hg add --large large1-test
133 133 $ hg st
134 134 A large1-test
135 135 $ hg rm large1-test
136 136 not removing large1-test: file has been marked for add (use forget to undo)
137 137 [1]
138 138 $ hg st
139 139 A large1-test
140 140 $ hg forget large1-test
141 141 $ hg st
142 142 ? large1-test
143 143 $ hg remove large1-test
144 144 not removing large1-test: file is untracked
145 145 [1]
146 146 $ hg forget large1-test
147 147 not removing large1-test: file is already untracked
148 148 [1]
149 149 $ rm large1-test
150 150
151 151 Copy both largefiles and normal files (testing that status output is correct).
152 152
153 153 $ hg cp sub/normal2 normal1
154 154 $ hg cp sub/large2 large1
155 155 $ hg commit -m "copy files"
156 156 Invoking status precommit hook
157 157 A large1
158 158 A normal1
159 159 $ cat normal1
160 160 normal22
161 161 $ cat large1
162 162 large22
163 163
164 164 Test moving largefiles and verify that normal files are also unaffected.
165 165
166 166 $ hg mv normal1 normal3
167 167 $ hg mv large1 large3
168 168 $ hg mv sub/normal2 sub/normal4
169 169 $ hg mv sub/large2 sub/large4
170 170 $ hg commit -m "move files"
171 171 Invoking status precommit hook
172 172 A large3
173 173 A normal3
174 174 A sub/large4
175 175 A sub/normal4
176 176 R large1
177 177 R normal1
178 178 R sub/large2
179 179 R sub/normal2
180 180 $ cat normal3
181 181 normal22
182 182 $ cat large3
183 183 large22
184 184 $ cat sub/normal4
185 185 normal22
186 186 $ cat sub/large4
187 187 large22
188 188
189 189
190 190 #if serve
191 191 Test display of largefiles in hgweb
192 192
193 193 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
194 194 $ cat ../hg.pid >> $DAEMON_PIDS
195 195 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/?style=raw'
196 196 200 Script output follows
197 197
198 198
199 199 drwxr-xr-x sub
200 200 -rw-r--r-- 41 large3
201 201 -rw-r--r-- 9 normal3
202 202
203 203
204 204 $ get-with-headers.py $LOCALIP:$HGPORT 'file/tip/sub/?style=raw'
205 205 200 Script output follows
206 206
207 207
208 208 -rw-r--r-- 41 large4
209 209 -rw-r--r-- 9 normal4
210 210
211 211
212 212 $ killdaemons.py
213 213 #endif
214 214
215 215 Test largefiles can be loaded in hgweb (wrapcommand() shouldn't fail)
216 216
217 217 $ cat <<EOF > "$TESTTMP/hgweb.cgi"
218 218 > #!$PYTHON
219 219 > from mercurial import demandimport; demandimport.enable()
220 220 > from mercurial.hgweb import hgweb
221 221 > from mercurial.hgweb import wsgicgi
222 222 > application = hgweb(b'.', b'test repo')
223 223 > wsgicgi.launch(application)
224 224 > EOF
225 225 $ . "$TESTDIR/cgienv"
226 226
227 227 $ SCRIPT_NAME='' \
228 228 > "$PYTHON" "$TESTTMP/hgweb.cgi" > /dev/null
229 229
230 230 Test archiving the various revisions. These hit corner cases known with
231 231 archiving.
232 232
233 233 $ hg archive -r 0 ../archive0
234 234 $ hg archive -r 1 ../archive1
235 235 $ hg archive -r 2 ../archive2
236 236 $ hg archive -r 3 ../archive3
237 237 $ hg archive -r 4 ../archive4
238 238 $ cd ../archive0
239 239 $ cat normal1
240 240 normal1
241 241 $ cat large1
242 242 large1
243 243 $ cat sub/normal2
244 244 normal2
245 245 $ cat sub/large2
246 246 large2
247 247 $ cd ../archive1
248 248 $ cat normal1
249 249 normal11
250 250 $ cat large1
251 251 large11
252 252 $ cat sub/normal2
253 253 normal22
254 254 $ cat sub/large2
255 255 large22
256 256 $ cd ../archive2
257 257 $ ls
258 258 sub
259 259 $ cat sub/normal2
260 260 normal22
261 261 $ cat sub/large2
262 262 large22
263 263 $ cd ../archive3
264 264 $ cat normal1
265 265 normal22
266 266 $ cat large1
267 267 large22
268 268 $ cat sub/normal2
269 269 normal22
270 270 $ cat sub/large2
271 271 large22
272 272 $ cd ../archive4
273 273 $ cat normal3
274 274 normal22
275 275 $ cat large3
276 276 large22
277 277 $ cat sub/normal4
278 278 normal22
279 279 $ cat sub/large4
280 280 large22
281 281
282 282 Commit corner case: specify files to commit.
283 283
284 284 $ cd ../a
285 285 $ echo normal3 > normal3
286 286 $ echo large3 > large3
287 287 $ echo normal4 > sub/normal4
288 288 $ echo large4 > sub/large4
289 289 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
290 290 Invoking status precommit hook
291 291 M large3
292 292 M normal3
293 293 M sub/large4
294 294 M sub/normal4
295 295 $ cat normal3
296 296 normal3
297 297 $ cat large3
298 298 large3
299 299 $ cat sub/normal4
300 300 normal4
301 301 $ cat sub/large4
302 302 large4
303 303
304 304 One more commit corner case: commit from a subdirectory.
305 305
306 306 $ cd ../a
307 307 $ echo normal33 > normal3
308 308 $ echo large33 > large3
309 309 $ echo normal44 > sub/normal4
310 310 $ echo large44 > sub/large4
311 311 $ cd sub
312 312 $ hg commit -m "edit files yet again"
313 313 Invoking status precommit hook
314 314 M large3
315 315 M normal3
316 316 M sub/large4
317 317 M sub/normal4
318 318 $ cat ../normal3
319 319 normal33
320 320 $ cat ../large3
321 321 large33
322 322 $ cat normal4
323 323 normal44
324 324 $ cat large4
325 325 large44
326 326
327 327 Committing standins is not allowed.
328 328
329 329 $ cd ..
330 330 $ echo large3 > large3
331 331 $ hg commit .hglf/large3 -m "try to commit standin"
332 332 abort: file ".hglf/large3" is a largefile standin
333 333 (commit the largefile itself instead)
334 334 [255]
335 335
336 336 Corner cases for adding largefiles.
337 337
338 338 $ echo large5 > large5
339 339 $ hg add --large large5
340 340 $ hg add --large large5
341 341 large5 already a largefile
342 342 $ mkdir sub2
343 343 $ echo large6 > sub2/large6
344 344 $ echo large7 > sub2/large7
345 345 $ hg add --large sub2
346 346 adding sub2/large6 as a largefile
347 347 adding sub2/large7 as a largefile
348 348 $ hg st
349 349 M large3
350 350 A large5
351 351 A sub2/large6
352 352 A sub2/large7
353 353
354 354 Committing directories containing only largefiles.
355 355
356 356 $ mkdir -p z/y/x/m
357 357 $ touch z/y/x/m/large1
358 358 $ touch z/y/x/large2
359 359 $ hg add --large z/y/x/m/large1 z/y/x/large2
360 360 $ hg commit -m "Subdir with directory only containing largefiles" z
361 361 Invoking status precommit hook
362 362 M large3
363 363 A large5
364 364 A sub2/large6
365 365 A sub2/large7
366 366 A z/y/x/large2
367 367 A z/y/x/m/large1
368 368
369 369 (and a bit of log testing)
370 370
371 371 $ hg log -T '{rev}\n' z/y/x/m/large1
372 372 7
373 373 $ hg log -T '{rev}\n' z/y/x/m # with only a largefile
374 374 7
375 375
376 376 $ hg rollback --quiet
377 377 $ touch z/y/x/m/normal
378 378 $ hg add z/y/x/m/normal
379 379 $ hg commit -m "Subdir with mixed contents" z
380 380 Invoking status precommit hook
381 381 M large3
382 382 A large5
383 383 A sub2/large6
384 384 A sub2/large7
385 385 A z/y/x/large2
386 386 A z/y/x/m/large1
387 387 A z/y/x/m/normal
388 388 $ hg st
389 389 M large3
390 390 A large5
391 391 A sub2/large6
392 392 A sub2/large7
393 393 $ hg rollback --quiet
394 394 $ hg revert z/y/x/large2 z/y/x/m/large1
395 395 $ rm z/y/x/large2 z/y/x/m/large1
396 396 $ hg commit -m "Subdir with normal contents" z
397 397 Invoking status precommit hook
398 398 M large3
399 399 A large5
400 400 A sub2/large6
401 401 A sub2/large7
402 402 A z/y/x/m/normal
403 403 $ hg st
404 404 M large3
405 405 A large5
406 406 A sub2/large6
407 407 A sub2/large7
408 408 $ hg rollback --quiet
409 409 $ hg revert --quiet z
410 410 $ hg commit -m "Empty subdir" z
411 411 abort: z: no match under directory!
412 412 [255]
413 413 $ rm -rf z
414 414 $ hg ci -m "standin" .hglf
415 415 abort: file ".hglf" is a largefile standin
416 416 (commit the largefile itself instead)
417 417 [255]
418 418
419 419 Test "hg status" with combination of 'file pattern' and 'directory
420 420 pattern' for largefiles:
421 421
422 422 $ hg status sub2/large6 sub2
423 423 A sub2/large6
424 424 A sub2/large7
425 425
426 426 Config settings (pattern **.dat, minsize 2 MB) are respected.
427 427
428 428 $ echo testdata > test.dat
429 429 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
430 430 $ hg add
431 431 adding reallylarge as a largefile
432 432 adding test.dat as a largefile
433 433
434 434 Test that minsize and --lfsize handle float values;
435 435 also tests that --lfsize overrides largefiles.minsize.
436 436 (0.250 MB = 256 kB = 262144 B)
437 437
438 438 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
439 439 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
440 440 $ hg --config largefiles.minsize=.25 add
441 441 adding ratherlarge as a largefile
442 442 adding medium
443 443 $ hg forget medium
444 444 $ hg --config largefiles.minsize=.25 add --lfsize=.125
445 445 adding medium as a largefile
446 446 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
447 447 $ hg --config largefiles.minsize=.25 add --lfsize=.125
448 448 adding notlarge
449 449 $ hg forget notlarge
450 450
451 451 Test forget on largefiles.
452 452
453 453 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
454 454 $ hg commit -m "add/edit more largefiles"
455 455 Invoking status precommit hook
456 456 A sub2/large6
457 457 A sub2/large7
458 458 R large3
459 459 ? large5
460 460 ? medium
461 461 ? notlarge
462 462 ? ratherlarge
463 463 ? reallylarge
464 464 ? test.dat
465 465 $ hg st
466 466 ? large3
467 467 ? large5
468 468 ? medium
469 469 ? notlarge
470 470 ? ratherlarge
471 471 ? reallylarge
472 472 ? test.dat
473 473
474 474 Purge with largefiles: verify that largefiles are still in the working
475 475 dir after a purge.
476 476
477 477 $ hg purge --all
478 478 $ cat sub/large4
479 479 large44
480 480 $ cat sub2/large6
481 481 large6
482 482 $ cat sub2/large7
483 483 large7
484 484
485 485 Test addremove: verify that files that should be added as largefiles are added as
486 486 such and that already-existing largefiles are not added as normal files by
487 487 accident.
488 488
489 489 $ rm normal3
490 490 $ rm sub/large4
491 491 $ echo "testing addremove with patterns" > testaddremove.dat
492 492 $ echo "normaladdremove" > normaladdremove
493 493 $ hg addremove
494 494 removing sub/large4
495 495 adding testaddremove.dat as a largefile
496 496 removing normal3
497 497 adding normaladdremove
498 498
499 499 Test addremove with -R
500 500
501 501 $ hg up -C
502 502 getting changed largefiles
503 503 1 largefiles updated, 0 removed
504 504 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
505 505 $ rm normal3
506 506 $ rm sub/large4
507 507 $ echo "testing addremove with patterns" > testaddremove.dat
508 508 $ echo "normaladdremove" > normaladdremove
509 509 $ cd ..
510 510 $ hg -R a -v addremove
511 511 removing sub/large4
512 512 adding testaddremove.dat as a largefile
513 513 removing normal3
514 514 adding normaladdremove
515 515 $ cd a
516 516
517 517 Test 3364
518 518 $ hg clone . ../addrm
519 519 updating to branch default
520 520 getting changed largefiles
521 521 3 largefiles updated, 0 removed
522 522 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
523 523 $ cd ../addrm
524 524 $ cat >> .hg/hgrc <<EOF
525 525 > [hooks]
526 526 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
527 527 > EOF
528 528 $ touch foo
529 529 $ hg add --large foo
530 530 $ hg ci -m "add foo"
531 531 Invoking status precommit hook
532 532 A foo
533 533 Invoking status postcommit hook
534 534 C foo
535 535 C normal3
536 536 C sub/large4
537 537 C sub/normal4
538 538 C sub2/large6
539 539 C sub2/large7
540 540 $ rm foo
541 541 $ hg st
542 542 ! foo
543 543 hmm.. no precommit invoked, but there is a postcommit??
544 544 $ hg ci -m "will not checkin"
545 545 nothing changed (1 missing files, see 'hg status')
546 546 Invoking status postcommit hook
547 547 ! foo
548 548 C normal3
549 549 C sub/large4
550 550 C sub/normal4
551 551 C sub2/large6
552 552 C sub2/large7
553 553 [1]
554 554 $ hg addremove
555 555 removing foo
556 556 $ hg st
557 557 R foo
558 558 $ hg ci -m "used to say nothing changed"
559 559 Invoking status precommit hook
560 560 R foo
561 561 Invoking status postcommit hook
562 562 C normal3
563 563 C sub/large4
564 564 C sub/normal4
565 565 C sub2/large6
566 566 C sub2/large7
567 567 $ hg st
568 568
569 569 Test 3507 (both normal files and largefiles were a problem)
570 570
571 571 $ touch normal
572 572 $ touch large
573 573 $ hg add normal
574 574 $ hg add --large large
575 575 $ hg ci -m "added"
576 576 Invoking status precommit hook
577 577 A large
578 578 A normal
579 579 Invoking status postcommit hook
580 580 C large
581 581 C normal
582 582 C normal3
583 583 C sub/large4
584 584 C sub/normal4
585 585 C sub2/large6
586 586 C sub2/large7
587 587 $ hg remove normal
588 588 $ hg addremove --traceback
589 589 $ hg ci -m "addremoved normal"
590 590 Invoking status precommit hook
591 591 R normal
592 592 Invoking status postcommit hook
593 593 C large
594 594 C normal3
595 595 C sub/large4
596 596 C sub/normal4
597 597 C sub2/large6
598 598 C sub2/large7
599 599 $ hg up -C '.^'
600 600 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 601 $ hg remove large
602 602 $ hg addremove --traceback
603 603 $ hg ci -m "removed large"
604 604 Invoking status precommit hook
605 605 R large
606 606 created new head
607 607 Invoking status postcommit hook
608 608 C normal
609 609 C normal3
610 610 C sub/large4
611 611 C sub/normal4
612 612 C sub2/large6
613 613 C sub2/large7
614 614
615 615 Test commit -A (issue3542)
616 616 $ echo large8 > large8
617 617 $ hg add --large large8
618 618 $ hg ci -Am 'this used to add large8 as normal and commit both'
619 619 Invoking status precommit hook
620 620 A large8
621 621 Invoking status postcommit hook
622 622 C large8
623 623 C normal
624 624 C normal3
625 625 C sub/large4
626 626 C sub/normal4
627 627 C sub2/large6
628 628 C sub2/large7
629 629 $ rm large8
630 630 $ hg ci -Am 'this used to not notice the rm'
631 631 removing large8
632 632 Invoking status precommit hook
633 633 R large8
634 634 Invoking status postcommit hook
635 635 C normal
636 636 C normal3
637 637 C sub/large4
638 638 C sub/normal4
639 639 C sub2/large6
640 640 C sub2/large7
641 641
642 642 Test that a standin can't be added as a large file
643 643
644 644 $ touch large
645 645 $ hg add --large large
646 646 $ hg ci -m "add"
647 647 Invoking status precommit hook
648 648 A large
649 649 Invoking status postcommit hook
650 650 C large
651 651 C normal
652 652 C normal3
653 653 C sub/large4
654 654 C sub/normal4
655 655 C sub2/large6
656 656 C sub2/large7
657 657 $ hg remove large
658 658 $ touch large
659 659 $ hg addremove --config largefiles.patterns=**large --traceback
660 660 adding large as a largefile
661 661
662 662 Test that outgoing --large works (with revsets too)
663 663 $ hg outgoing --rev '.^' --large
664 664 comparing with $TESTTMP/a
665 665 searching for changes
666 666 changeset: 8:c02fd3b77ec4
667 667 user: test
668 668 date: Thu Jan 01 00:00:00 1970 +0000
669 669 summary: add foo
670 670
671 671 changeset: 9:289dd08c9bbb
672 672 user: test
673 673 date: Thu Jan 01 00:00:00 1970 +0000
674 674 summary: used to say nothing changed
675 675
676 676 changeset: 10:34f23ac6ac12
677 677 user: test
678 678 date: Thu Jan 01 00:00:00 1970 +0000
679 679 summary: added
680 680
681 681 changeset: 12:710c1b2f523c
682 682 parent: 10:34f23ac6ac12
683 683 user: test
684 684 date: Thu Jan 01 00:00:00 1970 +0000
685 685 summary: removed large
686 686
687 687 changeset: 13:0a3e75774479
688 688 user: test
689 689 date: Thu Jan 01 00:00:00 1970 +0000
690 690 summary: this used to add large8 as normal and commit both
691 691
692 692 changeset: 14:84f3d378175c
693 693 user: test
694 694 date: Thu Jan 01 00:00:00 1970 +0000
695 695 summary: this used to not notice the rm
696 696
697 697 largefiles to upload (1 entities):
698 698 large8
699 699
700 700 $ cd ../a
701 701
702 702 Clone a largefiles repo.
703 703
704 704 $ hg clone . ../b
705 705 updating to branch default
706 706 getting changed largefiles
707 707 3 largefiles updated, 0 removed
708 708 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
709 709 $ cd ../b
710 710 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
711 711 7:daea875e9014 add/edit more largefiles
712 712 6:4355d653f84f edit files yet again
713 713 5:9d5af5072dbd edit files again
714 714 4:74c02385b94c move files
715 715 3:9e8fbc4bce62 copy files
716 716 2:51a0ae4d5864 remove files
717 717 1:ce8896473775 edit files
718 718 0:30d30fe6a5be add files
719 719 $ cat normal3
720 720 normal33
721 721
722 722 Test graph log
723 723
724 724 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
725 725 @ 7:daea875e9014 add/edit more largefiles
726 726 |
727 727 o 6:4355d653f84f edit files yet again
728 728 |
729 729 o 5:9d5af5072dbd edit files again
730 730 |
731 731 o 4:74c02385b94c move files
732 732 |
733 733 o 3:9e8fbc4bce62 copy files
734 734 |
735 735 o 2:51a0ae4d5864 remove files
736 736 |
737 737 o 1:ce8896473775 edit files
738 738 |
739 739 o 0:30d30fe6a5be add files
740 740
741 741
742 742 Test log with --patch
743 743
744 744 $ hg log --patch -r 6::7
745 745 changeset: 6:4355d653f84f
746 746 user: test
747 747 date: Thu Jan 01 00:00:00 1970 +0000
748 748 summary: edit files yet again
749 749
750 750 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
751 751 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
752 752 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
753 753 @@ -1,1 +1,1 @@
754 754 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
755 755 +7838695e10da2bb75ac1156565f40a2595fa2fa0
756 756 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
757 757 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
758 758 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
759 759 @@ -1,1 +1,1 @@
760 760 -aeb2210d19f02886dde00dac279729a48471e2f9
761 761 +971fb41e78fea4f8e0ba5244784239371cb00591
762 762 diff -r 9d5af5072dbd -r 4355d653f84f normal3
763 763 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
764 764 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
765 765 @@ -1,1 +1,1 @@
766 766 -normal3
767 767 +normal33
768 768 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
769 769 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
770 770 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
771 771 @@ -1,1 +1,1 @@
772 772 -normal4
773 773 +normal44
774 774
775 775 changeset: 7:daea875e9014
776 776 tag: tip
777 777 user: test
778 778 date: Thu Jan 01 00:00:00 1970 +0000
779 779 summary: add/edit more largefiles
780 780
781 781 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
782 782 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
783 783 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
784 784 @@ -1,1 +0,0 @@
785 785 -7838695e10da2bb75ac1156565f40a2595fa2fa0
786 786 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
787 787 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
788 788 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
789 789 @@ -0,0 +1,1 @@
790 790 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
791 791 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
792 792 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
793 793 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
794 794 @@ -0,0 +1,1 @@
795 795 +bb3151689acb10f0c3125c560d5e63df914bc1af
796 796
797 797
798 798 $ hg log --patch -r 6::7 sub/
799 799 changeset: 6:4355d653f84f
800 800 user: test
801 801 date: Thu Jan 01 00:00:00 1970 +0000
802 802 summary: edit files yet again
803 803
804 804 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
805 805 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
806 806 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
807 807 @@ -1,1 +1,1 @@
808 808 -aeb2210d19f02886dde00dac279729a48471e2f9
809 809 +971fb41e78fea4f8e0ba5244784239371cb00591
810 810 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
811 811 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
812 812 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
813 813 @@ -1,1 +1,1 @@
814 814 -normal4
815 815 +normal44
816 816
817 817
818 818 log with both --follow and --patch
819 819
820 820 $ hg log --follow --patch --limit 2
821 821 changeset: 7:daea875e9014
822 822 tag: tip
823 823 user: test
824 824 date: Thu Jan 01 00:00:00 1970 +0000
825 825 summary: add/edit more largefiles
826 826
827 827 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
828 828 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
829 829 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
830 830 @@ -1,1 +0,0 @@
831 831 -7838695e10da2bb75ac1156565f40a2595fa2fa0
832 832 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
833 833 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
834 834 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
835 835 @@ -0,0 +1,1 @@
836 836 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
837 837 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
838 838 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
839 839 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
840 840 @@ -0,0 +1,1 @@
841 841 +bb3151689acb10f0c3125c560d5e63df914bc1af
842 842
843 843 changeset: 6:4355d653f84f
844 844 user: test
845 845 date: Thu Jan 01 00:00:00 1970 +0000
846 846 summary: edit files yet again
847 847
848 848 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
849 849 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
850 850 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
851 851 @@ -1,1 +1,1 @@
852 852 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
853 853 +7838695e10da2bb75ac1156565f40a2595fa2fa0
854 854 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
855 855 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
856 856 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
857 857 @@ -1,1 +1,1 @@
858 858 -aeb2210d19f02886dde00dac279729a48471e2f9
859 859 +971fb41e78fea4f8e0ba5244784239371cb00591
860 860 diff -r 9d5af5072dbd -r 4355d653f84f normal3
861 861 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
862 862 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
863 863 @@ -1,1 +1,1 @@
864 864 -normal3
865 865 +normal33
866 866 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
867 867 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
868 868 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
869 869 @@ -1,1 +1,1 @@
870 870 -normal4
871 871 +normal44
872 872
873 873 $ hg log --follow --patch sub/large4
874 874 changeset: 6:4355d653f84f
875 875 user: test
876 876 date: Thu Jan 01 00:00:00 1970 +0000
877 877 summary: edit files yet again
878 878
879 879 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
880 880 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
881 881 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
882 882 @@ -1,1 +1,1 @@
883 883 -aeb2210d19f02886dde00dac279729a48471e2f9
884 884 +971fb41e78fea4f8e0ba5244784239371cb00591
885 885
886 886 changeset: 5:9d5af5072dbd
887 887 user: test
888 888 date: Thu Jan 01 00:00:00 1970 +0000
889 889 summary: edit files again
890 890
891 891 diff -r 74c02385b94c -r 9d5af5072dbd .hglf/sub/large4
892 892 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
893 893 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
894 894 @@ -1,1 +1,1 @@
895 895 -eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
896 896 +aeb2210d19f02886dde00dac279729a48471e2f9
897 897
898 898 changeset: 4:74c02385b94c
899 899 user: test
900 900 date: Thu Jan 01 00:00:00 1970 +0000
901 901 summary: move files
902 902
903 903 diff -r 9e8fbc4bce62 -r 74c02385b94c .hglf/sub/large4
904 904 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
905 905 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
906 906 @@ -0,0 +1,1 @@
907 907 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
908 908
909 909 changeset: 1:ce8896473775
910 910 user: test
911 911 date: Thu Jan 01 00:00:00 1970 +0000
912 912 summary: edit files
913 913
914 914 diff -r 30d30fe6a5be -r ce8896473775 .hglf/sub/large2
915 915 --- a/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
916 916 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
917 917 @@ -1,1 +1,1 @@
918 918 -1deebade43c8c498a3c8daddac0244dc55d1331d
919 919 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
920 920
921 921 changeset: 0:30d30fe6a5be
922 922 user: test
923 923 date: Thu Jan 01 00:00:00 1970 +0000
924 924 summary: add files
925 925
926 926 diff -r 000000000000 -r 30d30fe6a5be .hglf/sub/large2
927 927 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
928 928 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
929 929 @@ -0,0 +1,1 @@
930 930 +1deebade43c8c498a3c8daddac0244dc55d1331d
931 931
932 932 $ cat sub/normal4
933 933 normal44
934 934 $ cat sub/large4
935 935 large44
936 936 $ cat sub2/large6
937 937 large6
938 938 $ cat sub2/large7
939 939 large7
940 940 $ hg log -qf sub2/large7
941 941 7:daea875e9014
942 942 $ hg log -Gqf sub2/large7
943 943 @ 7:daea875e9014
944 944 |
945 945 ~
946 946 $ cd ..
947 947
948 948 Test log from outside repo
949 949
950 950 $ hg log b/sub -T '{rev}:{node|short} {desc|firstline}\n'
951 951 6:4355d653f84f edit files yet again
952 952 5:9d5af5072dbd edit files again
953 953 4:74c02385b94c move files
954 954 1:ce8896473775 edit files
955 955 0:30d30fe6a5be add files
956 956
957 957 Test clone at revision
958 958
959 959 $ hg clone a -r 3 c
960 960 adding changesets
961 961 adding manifests
962 962 adding file changes
963 963 added 4 changesets with 10 changes to 4 files
964 964 new changesets 30d30fe6a5be:9e8fbc4bce62 (4 drafts)
965 965 updating to branch default
966 966 getting changed largefiles
967 967 2 largefiles updated, 0 removed
968 968 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
969 969 $ cd c
970 970 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
971 971 3:9e8fbc4bce62 copy files
972 972 2:51a0ae4d5864 remove files
973 973 1:ce8896473775 edit files
974 974 0:30d30fe6a5be add files
975 975 $ cat normal1
976 976 normal22
977 977 $ cat large1
978 978 large22
979 979 $ cat sub/normal2
980 980 normal22
981 981 $ cat sub/large2
982 982 large22
983 983
984 984 Old revisions of a clone have correct largefiles content (this also
985 985 tests update).
986 986
987 987 $ hg update -r 1
988 988 getting changed largefiles
989 989 1 largefiles updated, 0 removed
990 990 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
991 991 $ cat large1
992 992 large11
993 993 $ cat sub/large2
994 994 large22
995 995 $ cd ..
996 996
997 997 Test cloning with --all-largefiles flag
998 998
999 999 $ rm "${USERCACHE}"/*
1000 1000 $ hg clone --all-largefiles a a-backup
1001 1001 updating to branch default
1002 1002 getting changed largefiles
1003 1003 3 largefiles updated, 0 removed
1004 1004 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1005 1005 8 additional largefiles cached
1006 1006
1007 1007 $ rm "${USERCACHE}"/*
1008 1008 $ hg clone --all-largefiles -u 0 a a-clone0
1009 1009 updating to branch default
1010 1010 getting changed largefiles
1011 1011 2 largefiles updated, 0 removed
1012 1012 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1013 1013 9 additional largefiles cached
1014 1014 $ hg -R a-clone0 sum
1015 1015 parent: 0:30d30fe6a5be
1016 1016 add files
1017 1017 branch: default
1018 1018 commit: (clean)
1019 1019 update: 7 new changesets (update)
1020 1020 phases: 8 draft
1021 1021
1022 1022 $ rm "${USERCACHE}"/*
1023 1023 $ hg clone --all-largefiles -u 1 a a-clone1
1024 1024 updating to branch default
1025 1025 getting changed largefiles
1026 1026 2 largefiles updated, 0 removed
1027 1027 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1028 1028 8 additional largefiles cached
1029 1029 $ hg -R a-clone1 verify --large --lfa --lfc
1030 1030 checking changesets
1031 1031 checking manifests
1032 1032 crosschecking files in changesets and manifests
1033 1033 checking files
1034 1034 checked 8 changesets with 24 changes to 10 files
1035 1035 searching 8 changesets for largefiles
1036 1036 verified contents of 13 revisions of 6 largefiles
1037 1037 $ hg -R a-clone1 sum
1038 1038 parent: 1:ce8896473775
1039 1039 edit files
1040 1040 branch: default
1041 1041 commit: (clean)
1042 1042 update: 6 new changesets (update)
1043 1043 phases: 8 draft
1044 1044
1045 1045 $ rm "${USERCACHE}"/*
1046 1046 $ hg clone --all-largefiles -U a a-clone-u
1047 1047 11 additional largefiles cached
1048 1048 $ hg -R a-clone-u sum
1049 1049 parent: -1:000000000000 (no revision checked out)
1050 1050 branch: default
1051 1051 commit: (clean)
1052 1052 update: 8 new changesets (update)
1053 1053 phases: 8 draft
1054 1054
1055 1055 Show computed destination directory:
1056 1056
1057 1057 $ mkdir xyz
1058 1058 $ cd xyz
1059 1059 $ hg clone ../a
1060 1060 destination directory: a
1061 1061 updating to branch default
1062 1062 getting changed largefiles
1063 1063 3 largefiles updated, 0 removed
1064 1064 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1065 1065 $ cd ..
1066 1066
1067 1067 Clone URL without path:
1068 1068
1069 1069 $ hg clone file://
1070 1070 abort: repository / not found!
1071 1071 [255]
1072 1072
1073 1073 Ensure base clone command argument validation
1074 1074
1075 1075 $ hg clone -U -u 0 a a-clone-failure
1076 1076 abort: cannot specify both --noupdate and --updaterev
1077 1077 [255]
1078 1078
1079 1079 $ hg clone --all-largefiles a ssh://localhost/a
1080 1080 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
1081 1081 [255]
1082 1082
1083 1083 Test pulling with --all-largefiles flag. Also test that the largefiles are
1084 1084 downloaded from 'default' instead of 'default-push' when no source is specified
1085 1085 (issue3584)
1086 1086
1087 1087 $ rm -Rf a-backup
1088 1088 $ hg clone -r 1 a a-backup
1089 1089 adding changesets
1090 1090 adding manifests
1091 1091 adding file changes
1092 1092 added 2 changesets with 8 changes to 4 files
1093 1093 new changesets 30d30fe6a5be:ce8896473775 (2 drafts)
1094 1094 updating to branch default
1095 1095 getting changed largefiles
1096 1096 2 largefiles updated, 0 removed
1097 1097 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1098 1098 $ rm "${USERCACHE}"/*
1099 1099 $ cd a-backup
1100 1100 $ hg pull --all-largefiles --config paths.default-push=bogus/path
1101 1101 pulling from $TESTTMP/a
1102 1102 searching for changes
1103 1103 adding changesets
1104 1104 adding manifests
1105 1105 adding file changes
1106 1106 added 6 changesets with 16 changes to 8 files
1107 1107 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1108 1108 (run 'hg update' to get a working copy)
1109 1109 6 largefiles cached
1110 1110
1111 1111 redo pull with --lfrev and check it pulls largefiles for the right revs
1112 1112
1113 1113 $ hg rollback
1114 1114 repository tip rolled back to revision 1 (undo pull)
1115 1115 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
1116 1116 pulling from $TESTTMP/a
1117 1117 searching for changes
1118 1118 all local heads known remotely
1119 1119 6 changesets found
1120 1120 uncompressed size of bundle content:
1121 1121 1389 (changelog)
1122 1122 1599 (manifests)
1123 1123 254 .hglf/large1
1124 1124 564 .hglf/large3
1125 1125 572 .hglf/sub/large4
1126 1126 182 .hglf/sub2/large6
1127 1127 182 .hglf/sub2/large7
1128 1128 212 normal1
1129 1129 457 normal3
1130 1130 465 sub/normal4
1131 1131 adding changesets
1132 1132 adding manifests
1133 1133 adding file changes
1134 1134 added 6 changesets with 16 changes to 8 files
1135 1135 new changesets 51a0ae4d5864:daea875e9014 (6 drafts)
1136 1136 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
1137 1137 (run 'hg update' to get a working copy)
1138 1138 pulling largefiles for revision 7
1139 1139 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
1140 1140 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
1141 1141 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
1142 1142 pulling largefiles for revision 2
1143 1143 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1144 1144 0 largefiles cached
1145 1145
1146 1146 lfpull
1147 1147
1148 1148 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
1149 1149 2 largefiles cached
1150 1150 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
1151 1151 pulling largefiles for revision 4
1152 1152 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1153 1153 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1154 1154 pulling largefiles for revision 2
1155 1155 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1156 1156 0 largefiles cached
1157 1157
1158 1158 $ ls usercache-lfpull/* | sort
1159 1159 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
1160 1160 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
1161 1161
1162 1162 $ cd ..
1163 1163
1164 1164 Rebasing between two repositories does not revert largefiles to old
1165 1165 revisions (this was a very bad bug that took a lot of work to fix).
1166 1166
1167 1167 $ hg clone a d
1168 1168 updating to branch default
1169 1169 getting changed largefiles
1170 1170 3 largefiles updated, 0 removed
1171 1171 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1172 1172 $ cd b
1173 1173 $ echo large4-modified > sub/large4
1174 1174 $ echo normal3-modified > normal3
1175 1175 $ hg commit -m "modify normal file and largefile in repo b"
1176 1176 Invoking status precommit hook
1177 1177 M normal3
1178 1178 M sub/large4
1179 1179 $ cd ../d
1180 1180 $ echo large6-modified > sub2/large6
1181 1181 $ echo normal4-modified > sub/normal4
1182 1182 $ hg commit -m "modify normal file largefile in repo d"
1183 1183 Invoking status precommit hook
1184 1184 M sub/normal4
1185 1185 M sub2/large6
1186 1186 $ cd ..
1187 1187 $ hg clone d e
1188 1188 updating to branch default
1189 1189 getting changed largefiles
1190 1190 3 largefiles updated, 0 removed
1191 1191 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1192 1192 $ cd d
1193 1193
1194 1194 More rebase testing, but also test that the largefiles are downloaded from
1195 1195 'default-push' when no source is specified (issue3584). (The largefile from the
1196 1196 pulled revision is however not downloaded but found in the local cache.)
1197 1197 Largefiles are fetched for the new pulled revision, not for existing revisions,
1198 1198 rebased or not.
1199 1199
1200 1200 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1201 1201 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
1202 1202 pulling from $TESTTMP/b
1203 1203 searching for changes
1204 1204 adding changesets
1205 1205 adding manifests
1206 1206 adding file changes
1207 1207 added 1 changesets with 2 changes to 2 files (+1 heads)
1208 1208 new changesets a381d2c8c80e (1 drafts)
1209 1209 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1210 1210 Invoking status precommit hook
1211 1211 M sub/normal4
1212 1212 M sub2/large6
1213 1213 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1214 1214 0 largefiles cached
1215 1215 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1216 1216 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1217 1217 9:598410d3eb9a modify normal file largefile in repo d
1218 1218 8:a381d2c8c80e modify normal file and largefile in repo b
1219 1219 7:daea875e9014 add/edit more largefiles
1220 1220 6:4355d653f84f edit files yet again
1221 1221 5:9d5af5072dbd edit files again
1222 1222 4:74c02385b94c move files
1223 1223 3:9e8fbc4bce62 copy files
1224 1224 2:51a0ae4d5864 remove files
1225 1225 1:ce8896473775 edit files
1226 1226 0:30d30fe6a5be add files
1227 1227 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
1228 1228 @ 9:598410d3eb9a modify normal file largefile in repo d
1229 1229 |
1230 1230 o 8:a381d2c8c80e modify normal file and largefile in repo b
1231 1231 |
1232 1232 o 7:daea875e9014 add/edit more largefiles
1233 1233 |
1234 1234 o 6:4355d653f84f edit files yet again
1235 1235 |
1236 1236 o 5:9d5af5072dbd edit files again
1237 1237 |
1238 1238 o 4:74c02385b94c move files
1239 1239 |
1240 1240 o 3:9e8fbc4bce62 copy files
1241 1241 |
1242 1242 o 2:51a0ae4d5864 remove files
1243 1243 |
1244 1244 o 1:ce8896473775 edit files
1245 1245 |
1246 1246 o 0:30d30fe6a5be add files
1247 1247
1248 1248 $ cat normal3
1249 1249 normal3-modified
1250 1250 $ cat sub/normal4
1251 1251 normal4-modified
1252 1252 $ cat sub/large4
1253 1253 large4-modified
1254 1254 $ cat sub2/large6
1255 1255 large6-modified
1256 1256 $ cat sub2/large7
1257 1257 large7
1258 1258 $ cd ../e
1259 1259 $ hg pull ../b
1260 1260 pulling from ../b
1261 1261 searching for changes
1262 1262 adding changesets
1263 1263 adding manifests
1264 1264 adding file changes
1265 1265 added 1 changesets with 2 changes to 2 files (+1 heads)
1266 1266 new changesets a381d2c8c80e (1 drafts)
1267 1267 (run 'hg heads' to see heads, 'hg merge' to merge)
1268 1268 $ hg rebase
1269 1269 rebasing 8:f574fb32bb45 "modify normal file largefile in repo d"
1270 1270 Invoking status precommit hook
1271 1271 M sub/normal4
1272 1272 M sub2/large6
1273 1273 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-dd1d9f80-rebase.hg
1274 1274 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1275 1275 9:598410d3eb9a modify normal file largefile in repo d
1276 1276 8:a381d2c8c80e modify normal file and largefile in repo b
1277 1277 7:daea875e9014 add/edit more largefiles
1278 1278 6:4355d653f84f edit files yet again
1279 1279 5:9d5af5072dbd edit files again
1280 1280 4:74c02385b94c move files
1281 1281 3:9e8fbc4bce62 copy files
1282 1282 2:51a0ae4d5864 remove files
1283 1283 1:ce8896473775 edit files
1284 1284 0:30d30fe6a5be add files
1285 1285 $ cat normal3
1286 1286 normal3-modified
1287 1287 $ cat sub/normal4
1288 1288 normal4-modified
1289 1289 $ cat sub/large4
1290 1290 large4-modified
1291 1291 $ cat sub2/large6
1292 1292 large6-modified
1293 1293 $ cat sub2/large7
1294 1294 large7
1295 1295
1296 1296 Log on largefiles
1297 1297
1298 1298 - same output
1299 1299 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1300 1300 8:a381d2c8c80e modify normal file and largefile in repo b
1301 1301 6:4355d653f84f edit files yet again
1302 1302 5:9d5af5072dbd edit files again
1303 1303 4:74c02385b94c move files
1304 1304 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1305 1305 o 8:a381d2c8c80e modify normal file and largefile in repo b
1306 1306 :
1307 1307 o 6:4355d653f84f edit files yet again
1308 1308 |
1309 1309 o 5:9d5af5072dbd edit files again
1310 1310 |
1311 1311 o 4:74c02385b94c move files
1312 1312 |
1313 1313 ~
1314 1314 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1315 1315 8:a381d2c8c80e modify normal file and largefile in repo b
1316 1316 6:4355d653f84f edit files yet again
1317 1317 5:9d5af5072dbd edit files again
1318 1318 4:74c02385b94c move files
1319 1319 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1320 1320 o 8:a381d2c8c80e modify normal file and largefile in repo b
1321 1321 :
1322 1322 o 6:4355d653f84f edit files yet again
1323 1323 |
1324 1324 o 5:9d5af5072dbd edit files again
1325 1325 |
1326 1326 o 4:74c02385b94c move files
1327 1327 |
1328 1328 ~
1329 1329
1330 1330 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1331 1331 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1332 1332 8:a381d2c8c80e modify normal file and largefile in repo b
1333 1333 6:4355d653f84f edit files yet again
1334 1334 5:9d5af5072dbd edit files again
1335 1335 4:74c02385b94c move files
1336 1336 1:ce8896473775 edit files
1337 1337 0:30d30fe6a5be add files
1338 1338 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1339 1339 o 8:a381d2c8c80e modify normal file and largefile in repo b
1340 1340 :
1341 1341 o 6:4355d653f84f edit files yet again
1342 1342 |
1343 1343 o 5:9d5af5072dbd edit files again
1344 1344 |
1345 1345 o 4:74c02385b94c move files
1346 1346 :
1347 1347 o 1:ce8896473775 edit files
1348 1348 |
1349 1349 o 0:30d30fe6a5be add files
1350 1350
1351 1351 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1352 1352 9:598410d3eb9a modify normal file largefile in repo d
1353 1353 8:a381d2c8c80e modify normal file and largefile in repo b
1354 1354 6:4355d653f84f edit files yet again
1355 1355 5:9d5af5072dbd edit files again
1356 1356 4:74c02385b94c move files
1357 1357 1:ce8896473775 edit files
1358 1358 0:30d30fe6a5be add files
1359 1359 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' sub
1360 1360 @ 9:598410d3eb9a modify normal file largefile in repo d
1361 1361 |
1362 1362 o 8:a381d2c8c80e modify normal file and largefile in repo b
1363 1363 :
1364 1364 o 6:4355d653f84f edit files yet again
1365 1365 |
1366 1366 o 5:9d5af5072dbd edit files again
1367 1367 |
1368 1368 o 4:74c02385b94c move files
1369 1369 :
1370 1370 o 1:ce8896473775 edit files
1371 1371 |
1372 1372 o 0:30d30fe6a5be add files
1373 1373
1374 1374 - globbing gives same result
1375 1375 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1376 1376 9:598410d3eb9a modify normal file largefile in repo d
1377 1377 8:a381d2c8c80e modify normal file and largefile in repo b
1378 1378 6:4355d653f84f edit files yet again
1379 1379 5:9d5af5072dbd edit files again
1380 1380 4:74c02385b94c move files
1381 1381 1:ce8896473775 edit files
1382 1382 0:30d30fe6a5be add files
1383 1383 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1384 1384 @ 9:598410d3eb9a modify normal file largefile in repo d
1385 1385 |
1386 1386 o 8:a381d2c8c80e modify normal file and largefile in repo b
1387 1387 :
1388 1388 o 6:4355d653f84f edit files yet again
1389 1389 |
1390 1390 o 5:9d5af5072dbd edit files again
1391 1391 |
1392 1392 o 4:74c02385b94c move files
1393 1393 :
1394 1394 o 1:ce8896473775 edit files
1395 1395 |
1396 1396 o 0:30d30fe6a5be add files
1397 1397
1398 1398 Rollback on largefiles.
1399 1399
1400 1400 $ echo large4-modified-again > sub/large4
1401 1401 $ hg commit -m "Modify large4 again"
1402 1402 Invoking status precommit hook
1403 1403 M sub/large4
1404 1404 $ hg rollback
1405 1405 repository tip rolled back to revision 9 (undo commit)
1406 1406 working directory now based on revision 9
1407 1407 $ hg st
1408 1408 M sub/large4
1409 1409 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1410 1410 9:598410d3eb9a modify normal file largefile in repo d
1411 1411 8:a381d2c8c80e modify normal file and largefile in repo b
1412 1412 7:daea875e9014 add/edit more largefiles
1413 1413 6:4355d653f84f edit files yet again
1414 1414 5:9d5af5072dbd edit files again
1415 1415 4:74c02385b94c move files
1416 1416 3:9e8fbc4bce62 copy files
1417 1417 2:51a0ae4d5864 remove files
1418 1418 1:ce8896473775 edit files
1419 1419 0:30d30fe6a5be add files
1420 1420 $ cat sub/large4
1421 1421 large4-modified-again
1422 1422
1423 1423 "update --check" refuses to update with uncommitted changes.
1424 1424 $ hg update --check 8
1425 1425 abort: uncommitted changes
1426 1426 [255]
1427 1427
1428 1428 "update --clean" leaves correct largefiles in working copy, even when there is
1429 1429 .orig files from revert in .hglf.
1430 1430
1431 1431 $ echo mistake > sub2/large7
1432 1432 $ hg revert sub2/large7
1433 1433 $ cat sub2/large7
1434 1434 large7
1435 1435 $ cat sub2/large7.orig
1436 1436 mistake
1437 1437 $ test ! -f .hglf/sub2/large7.orig
1438 1438
1439 1439 $ hg -q update --clean -r null
1440 1440 $ hg update --clean
1441 1441 getting changed largefiles
1442 1442 3 largefiles updated, 0 removed
1443 1443 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1444 1444 $ cat normal3
1445 1445 normal3-modified
1446 1446 $ cat sub/normal4
1447 1447 normal4-modified
1448 1448 $ cat sub/large4
1449 1449 large4-modified
1450 1450 $ cat sub2/large6
1451 1451 large6-modified
1452 1452 $ cat sub2/large7
1453 1453 large7
1454 1454 $ cat sub2/large7.orig
1455 1455 mistake
1456 1456 $ test ! -f .hglf/sub2/large7.orig
1457 1457
1458 1458 verify that largefile .orig file no longer is overwritten on every update -C:
1459 1459 $ hg update --clean
1460 1460 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1461 1461 $ cat sub2/large7.orig
1462 1462 mistake
1463 1463 $ rm sub2/large7.orig
1464 1464
1465 1465 Now "update check" is happy.
1466 1466 $ hg update --check 8
1467 1467 getting changed largefiles
1468 1468 1 largefiles updated, 0 removed
1469 1469 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1470 1470 $ hg update --check
1471 1471 getting changed largefiles
1472 1472 1 largefiles updated, 0 removed
1473 1473 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1474 1474
1475 1475 Test removing empty largefiles directories on update
1476 1476 $ test -d sub2 && echo "sub2 exists"
1477 1477 sub2 exists
1478 1478 $ hg update -q null
1479 1479 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1480 1480 [1]
1481 1481 $ hg update -q
1482 1482
1483 1483 Test hg remove removes empty largefiles directories
1484 1484 $ test -d sub2 && echo "sub2 exists"
1485 1485 sub2 exists
1486 1486 $ hg remove sub2/*
1487 1487 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1488 1488 [1]
1489 1489 $ hg revert sub2/large6 sub2/large7
1490 1490
1491 1491 "revert" works on largefiles (and normal files too).
1492 1492 $ echo hack3 >> normal3
1493 1493 $ echo hack4 >> sub/normal4
1494 1494 $ echo hack4 >> sub/large4
1495 1495 $ rm sub2/large6
1496 1496 $ hg revert sub2/large6
1497 1497 $ hg rm sub2/large6
1498 1498 $ echo new >> sub2/large8
1499 1499 $ hg add --large sub2/large8
1500 1500 # XXX we don't really want to report that we're reverting the standin;
1501 1501 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1502 1502 $ hg revert sub
1503 1503 reverting .hglf/sub/large4
1504 1504 reverting sub/normal4
1505 1505 $ hg status
1506 1506 M normal3
1507 1507 A sub2/large8
1508 1508 R sub2/large6
1509 1509 ? sub/large4.orig
1510 1510 ? sub/normal4.orig
1511 1511 $ cat sub/normal4
1512 1512 normal4-modified
1513 1513 $ cat sub/large4
1514 1514 large4-modified
1515 1515 $ hg revert -a --no-backup
1516 1516 forgetting .hglf/sub2/large8
1517 1517 reverting normal3
1518 1518 undeleting .hglf/sub2/large6
1519 1519 $ hg status
1520 1520 ? sub/large4.orig
1521 1521 ? sub/normal4.orig
1522 1522 ? sub2/large8
1523 1523 $ cat normal3
1524 1524 normal3-modified
1525 1525 $ cat sub2/large6
1526 1526 large6-modified
1527 1527 $ rm sub/*.orig sub2/large8
1528 1528
1529 1529 revert some files to an older revision
1530 1530 $ hg revert --no-backup -r 8 sub2
1531 1531 reverting .hglf/sub2/large6
1532 1532 $ cat sub2/large6
1533 1533 large6
1534 1534 $ hg revert --no-backup -C -r '.^' sub2
1535 1535 $ hg revert --no-backup sub2
1536 1536 reverting .hglf/sub2/large6
1537 1537 $ hg status
1538 1538
1539 1539 "verify --large" actually verifies largefiles
1540 1540
1541 1541 - Where Do We Come From? What Are We? Where Are We Going?
1542 1542 $ pwd
1543 1543 $TESTTMP/e
1544 1544 $ hg paths
1545 1545 default = $TESTTMP/d
1546 1546
1547 1547 $ hg verify --large
1548 1548 checking changesets
1549 1549 checking manifests
1550 1550 crosschecking files in changesets and manifests
1551 1551 checking files
1552 1552 checked 10 changesets with 28 changes to 10 files
1553 1553 searching 1 changesets for largefiles
1554 1554 verified existence of 3 revisions of 3 largefiles
1555 1555
1556 1556 - introduce missing blob in local store repo and remote store
1557 1557 and make sure that this is caught:
1558 1558
1559 1559 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1560 1560 $ rm .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1561 1561 $ hg verify --large
1562 1562 checking changesets
1563 1563 checking manifests
1564 1564 crosschecking files in changesets and manifests
1565 1565 checking files
1566 1566 checked 10 changesets with 28 changes to 10 files
1567 1567 searching 1 changesets for largefiles
1568 1568 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1569 1569 verified existence of 3 revisions of 3 largefiles
1570 1570 [1]
1571 1571
1572 1572 - introduce corruption and make sure that it is caught when checking content:
1573 1573 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1574 1574 $ hg verify -q --large --lfc
1575 1575 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1576 1576 [1]
1577 1577
1578 1578 - cleanup
1579 1579 $ cp e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1580 1580 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 .hg/largefiles/
1581 1581
1582 1582 - verifying all revisions will fail because we didn't clone all largefiles to d:
1583 1583 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1584 1584 $ hg verify -q --lfa --lfc
1585 1585 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64
1586 1586 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d
1587 1587 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f
1588 1588 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1589 1589 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1590 1590 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1591 1591 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1592 1592 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c
1593 1593 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9
1594 1594 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0
1595 1595 [1]
1596 1596
1597 1597 - cleanup
1598 1598 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1599 1599 $ rm -f .hglf/sub/*.orig
1600 1600
1601 1601 Update to revision with missing largefile - and make sure it really is missing
1602 1602
1603 1603 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1604 1604 $ hg up -r 6
1605 1605 getting changed largefiles
1606 1606 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1607 1607 1 largefiles updated, 2 removed
1608 1608 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1609 1609 $ rm normal3
1610 1610 $ echo >> sub/normal4
1611 1611 $ hg ci -m 'commit with missing files'
1612 1612 Invoking status precommit hook
1613 1613 M sub/normal4
1614 1614 ! large3
1615 1615 ! normal3
1616 1616 created new head
1617 1617 $ hg st
1618 1618 ! large3
1619 1619 ! normal3
1620 1620 $ hg up -r.
1621 1621 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1622 1622 $ hg st
1623 1623 ! large3
1624 1624 ! normal3
1625 1625 $ hg up -Cr.
1626 1626 getting changed largefiles
1627 1627 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1628 1628 0 largefiles updated, 0 removed
1629 1629 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1630 1630 $ hg st
1631 1631 ! large3
1632 1632 $ hg rollback
1633 1633 repository tip rolled back to revision 9 (undo commit)
1634 1634 working directory now based on revision 6
1635 1635
1636 1636 Merge with revision with missing largefile - and make sure it tries to fetch it.
1637 1637
1638 1638 $ hg up -Cqr null
1639 1639 $ echo f > f
1640 1640 $ hg ci -Am branch
1641 1641 adding f
1642 1642 Invoking status precommit hook
1643 1643 A f
1644 1644 created new head
1645 1645 $ hg merge -r 6
1646 1646 getting changed largefiles
1647 1647 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1648 1648 1 largefiles updated, 0 removed
1649 1649 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1650 1650 (branch merge, don't forget to commit)
1651 1651
1652 1652 $ hg rollback -q
1653 1653 $ hg up -Cq
1654 1654
1655 1655 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1656 1656
1657 1657 $ hg pull --all-largefiles
1658 1658 pulling from $TESTTMP/d
1659 1659 searching for changes
1660 1660 no changes found
1661 1661
1662 1662 Merging does not revert to old versions of largefiles and also check
1663 1663 that merging after having pulled from a non-default remote works
1664 1664 correctly.
1665 1665
1666 1666 $ cd ..
1667 1667 $ hg clone -r 7 e temp
1668 1668 adding changesets
1669 1669 adding manifests
1670 1670 adding file changes
1671 1671 added 8 changesets with 24 changes to 10 files
1672 1672 new changesets 30d30fe6a5be:daea875e9014 (8 drafts)
1673 1673 updating to branch default
1674 1674 getting changed largefiles
1675 1675 3 largefiles updated, 0 removed
1676 1676 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1677 1677 $ hg clone temp f
1678 1678 updating to branch default
1679 1679 getting changed largefiles
1680 1680 3 largefiles updated, 0 removed
1681 1681 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1682 1682 # Delete the largefiles in the largefiles system cache so that we have an
1683 1683 # opportunity to test that caching after a pull works.
1684 1684 $ rm "${USERCACHE}"/*
1685 1685 $ cd f
1686 1686 $ echo "large4-merge-test" > sub/large4
1687 1687 $ hg commit -m "Modify large4 to test merge"
1688 1688 Invoking status precommit hook
1689 1689 M sub/large4
1690 1690 # Test --cache-largefiles flag
1691 1691 $ hg pull --lfrev 'heads(pulled())' ../e
1692 1692 pulling from ../e
1693 1693 searching for changes
1694 1694 adding changesets
1695 1695 adding manifests
1696 1696 adding file changes
1697 1697 added 2 changesets with 4 changes to 4 files (+1 heads)
1698 1698 new changesets a381d2c8c80e:598410d3eb9a (2 drafts)
1699 1699 (run 'hg heads' to see heads, 'hg merge' to merge)
1700 1700 2 largefiles cached
1701 1701 $ hg merge
1702 1702 largefile sub/large4 has a merge conflict
1703 1703 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1704 1704 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
1705 1705 take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
1706 1706 getting changed largefiles
1707 1707 1 largefiles updated, 0 removed
1708 1708 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1709 1709 (branch merge, don't forget to commit)
1710 1710 $ hg commit -m "Merge repos e and f"
1711 1711 Invoking status precommit hook
1712 1712 M normal3
1713 1713 M sub/normal4
1714 1714 M sub2/large6
1715 1715 $ cat normal3
1716 1716 normal3-modified
1717 1717 $ cat sub/normal4
1718 1718 normal4-modified
1719 1719 $ cat sub/large4
1720 1720 large4-merge-test
1721 1721 $ cat sub2/large6
1722 1722 large6-modified
1723 1723 $ cat sub2/large7
1724 1724 large7
1725 1725
1726 1726 Test status after merging with a branch that introduces a new largefile:
1727 1727
1728 1728 $ echo large > large
1729 1729 $ hg add --large large
1730 1730 $ hg commit -m 'add largefile'
1731 1731 Invoking status precommit hook
1732 1732 A large
1733 1733 $ hg update -q ".^"
1734 1734 $ echo change >> normal3
1735 1735 $ hg commit -m 'some change'
1736 1736 Invoking status precommit hook
1737 1737 M normal3
1738 1738 created new head
1739 1739 $ hg merge
1740 1740 getting changed largefiles
1741 1741 1 largefiles updated, 0 removed
1742 1742 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1743 1743 (branch merge, don't forget to commit)
1744 1744 $ hg status
1745 1745 M large
1746 1746
1747 1747 - make sure update of merge with removed largefiles fails as expected
1748 1748 $ hg rm sub2/large6
1749 1749 $ hg up -r.
1750 1750 abort: outstanding uncommitted merge
1751 1751 [255]
1752 1752
1753 1753 - revert should be able to revert files introduced in a pending merge
1754 1754 $ hg revert --all -r .
1755 1755 removing .hglf/large
1756 1756 undeleting .hglf/sub2/large6
1757 1757
1758 1758 Test that a normal file and a largefile with the same name and path cannot
1759 1759 coexist.
1760 1760
1761 1761 $ rm sub2/large7
1762 1762 $ echo "largeasnormal" > sub2/large7
1763 1763 $ hg add sub2/large7
1764 1764 sub2/large7 already a largefile
1765 1765
1766 1766 Test that transplanting a largefile change works correctly.
1767 1767
1768 1768 $ cd ..
1769 1769 $ hg clone -r 8 d g
1770 1770 adding changesets
1771 1771 adding manifests
1772 1772 adding file changes
1773 1773 added 9 changesets with 26 changes to 10 files
1774 1774 new changesets 30d30fe6a5be:a381d2c8c80e (9 drafts)
1775 1775 updating to branch default
1776 1776 getting changed largefiles
1777 1777 3 largefiles updated, 0 removed
1778 1778 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1779 1779 $ cd g
1780 1780 $ hg transplant -s ../d 598410d3eb9a
1781 1781 searching for changes
1782 1782 searching for changes
1783 1783 adding changesets
1784 1784 adding manifests
1785 1785 adding file changes
1786 1786 added 1 changesets with 2 changes to 2 files
1787 1787 new changesets 598410d3eb9a (1 drafts)
1788 1788 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1789 1789 9:598410d3eb9a modify normal file largefile in repo d
1790 1790 8:a381d2c8c80e modify normal file and largefile in repo b
1791 1791 7:daea875e9014 add/edit more largefiles
1792 1792 6:4355d653f84f edit files yet again
1793 1793 5:9d5af5072dbd edit files again
1794 1794 4:74c02385b94c move files
1795 1795 3:9e8fbc4bce62 copy files
1796 1796 2:51a0ae4d5864 remove files
1797 1797 1:ce8896473775 edit files
1798 1798 0:30d30fe6a5be add files
1799 1799 $ cat normal3
1800 1800 normal3-modified
1801 1801 $ cat sub/normal4
1802 1802 normal4-modified
1803 1803 $ cat sub/large4
1804 1804 large4-modified
1805 1805 $ cat sub2/large6
1806 1806 large6-modified
1807 1807 $ cat sub2/large7
1808 1808 large7
1809 1809
1810 1810 Cat a largefile
1811 1811 $ hg cat normal3
1812 1812 normal3-modified
1813 1813 $ hg cat sub/large4
1814 1814 large4-modified
1815 1815 $ rm "${USERCACHE}"/*
1816 1816 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1817 1817 $ cat cat.out
1818 1818 large4-modified
1819 1819 $ rm cat.out
1820 1820 $ hg cat -r a381d2c8c80e normal3
1821 1821 normal3-modified
1822 1822 $ hg cat -r '.^' normal3
1823 1823 normal3-modified
1824 1824 $ hg cat -r '.^' sub/large4 doesntexist
1825 1825 large4-modified
1826 1826 doesntexist: no such file in rev a381d2c8c80e
1827 1827 $ hg --cwd sub cat -r '.^' large4
1828 1828 large4-modified
1829 1829 $ hg --cwd sub cat -r '.^' ../normal3
1830 1830 normal3-modified
1831 1831 Cat a standin
1832 1832 $ hg cat .hglf/sub/large4
1833 1833 e166e74c7303192238d60af5a9c4ce9bef0b7928
1834 1834 $ hg cat .hglf/normal3
1835 1835 .hglf/normal3: no such file in rev 598410d3eb9a
1836 1836 [1]
1837 1837
1838 1838 Test that renaming a largefile results in correct output for status
1839 1839
1840 1840 $ hg rename sub/large4 large4-renamed
1841 1841 $ hg commit -m "test rename output"
1842 1842 Invoking status precommit hook
1843 1843 A large4-renamed
1844 1844 R sub/large4
1845 1845 $ cat large4-renamed
1846 1846 large4-modified
1847 1847 $ cd sub2
1848 1848 $ hg rename large6 large6-renamed
1849 1849 $ hg st
1850 1850 A sub2/large6-renamed
1851 1851 R sub2/large6
1852 1852 $ cd ..
1853 1853
1854 1854 Test --normal flag
1855 1855
1856 1856 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1857 1857 $ hg add --normal --large new-largefile
1858 1858 abort: --normal cannot be used with --large
1859 1859 [255]
1860 1860 $ hg add --normal new-largefile
1861 1861 new-largefile: up to 69 MB of RAM may be required to manage this file
1862 1862 (use 'hg revert new-largefile' to cancel the pending addition)
1863 1863 $ hg revert new-largefile
1864 1864 $ hg --config ui.large-file-limit=22M add --normal new-largefile
1865 1865
1866 1866 Test explicit commit of switch between normal and largefile - make sure both
1867 1867 the add and the remove is committed.
1868 1868
1869 1869 $ hg up -qC
1870 1870 $ hg forget normal3 large4-renamed
1871 1871 $ hg add --large normal3
1872 1872 $ hg add large4-renamed
1873 1873 $ hg commit -m 'swap' normal3 large4-renamed
1874 1874 Invoking status precommit hook
1875 1875 A large4-renamed
1876 1876 A normal3
1877 1877 ? new-largefile
1878 1878 ? sub2/large6-renamed
1879 1879 $ hg mani
1880 1880 .hglf/normal3
1881 1881 .hglf/sub2/large6
1882 1882 .hglf/sub2/large7
1883 1883 large4-renamed
1884 1884 sub/normal4
1885 1885
1886 1886 $ cd ..
1887 1887
1888 1888
1889 1889
@@ -1,116 +1,116 b''
1 1 $ hg init
2 2
3 3 $ echo foo > foo
4 4 $ echo bar > bar
5 5 $ hg ci -qAm 'add foo bar'
6 6
7 7 $ echo foo2 >> foo
8 8 $ echo bleh > bar
9 9 $ hg ci -m 'change foo bar'
10 10
11 11 $ hg up -qC 0
12 12 $ hg mv foo foo1
13 13 $ echo foo1 > foo1
14 14 $ hg cat foo >> foo1
15 15 $ hg ci -m 'mv foo foo1'
16 16 created new head
17 17
18 18 $ hg merge
19 19 merging foo1 and foo to foo1
20 20 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
21 21 (branch merge, don't forget to commit)
22 22
23 $ hg debugstate --nodates
23 $ hg debugstate --no-dates
24 24 m 0 -2 unset bar
25 25 m 0 -2 unset foo1
26 26 copy: foo -> foo1
27 27
28 28 $ hg st -q
29 29 M bar
30 30 M foo1
31 31
32 32
33 33 Removing foo1 and bar:
34 34
35 35 $ cp foo1 F
36 36 $ cp bar B
37 37 $ hg rm -f foo1 bar
38 38
39 $ hg debugstate --nodates
39 $ hg debugstate --no-dates
40 40 r 0 -1 set bar
41 41 r 0 -1 set foo1
42 42 copy: foo -> foo1
43 43
44 44 $ hg st -qC
45 45 R bar
46 46 R foo1
47 47
48 48
49 49 Re-adding foo1 and bar:
50 50
51 51 $ cp F foo1
52 52 $ cp B bar
53 53 $ hg add -v foo1 bar
54 54 adding bar
55 55 adding foo1
56 56
57 $ hg debugstate --nodates
57 $ hg debugstate --no-dates
58 58 n 0 -2 unset bar
59 59 n 0 -2 unset foo1
60 60 copy: foo -> foo1
61 61
62 62 $ hg st -qC
63 63 M bar
64 64 M foo1
65 65 foo
66 66
67 67
68 68 Reverting foo1 and bar:
69 69
70 70 $ hg revert -vr . foo1 bar
71 71 saving current version of bar as bar.orig
72 72 saving current version of foo1 as foo1.orig
73 73 reverting bar
74 74 reverting foo1
75 75
76 $ hg debugstate --nodates
76 $ hg debugstate --no-dates
77 77 n 0 -2 unset bar
78 78 n 0 -2 unset foo1
79 79 copy: foo -> foo1
80 80
81 81 $ hg st -qC
82 82 M bar
83 83 M foo1
84 84 foo
85 85
86 86 $ hg diff
87 87
88 88 Merge should not overwrite local file that is untracked after remove
89 89
90 90 $ rm *
91 91 $ hg up -qC
92 92 $ hg rm bar
93 93 $ hg ci -m 'remove bar'
94 94 $ echo 'memories of buried pirate treasure' > bar
95 95 $ hg merge
96 96 bar: untracked file differs
97 97 abort: untracked files in working directory differ from files in requested revision
98 98 [255]
99 99 $ cat bar
100 100 memories of buried pirate treasure
101 101
102 102 Those who use force will lose
103 103
104 104 $ hg merge -f
105 105 file 'bar' was deleted in local [working copy] but was modified in other [merge rev].
106 106 What do you want to do?
107 107 use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u
108 108 merging foo1 and foo to foo1
109 109 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
110 110 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
111 111 [1]
112 112 $ cat bar
113 113 bleh
114 114 $ hg st
115 115 M bar
116 116 M foo1
@@ -1,107 +1,107 b''
1 1 #testcases flat tree
2 2
3 3 $ . "$TESTDIR/narrow-library.sh"
4 4
5 5 #if tree
6 6 $ cat << EOF >> $HGRCPATH
7 7 > [experimental]
8 8 > treemanifest = 1
9 9 > EOF
10 10 #endif
11 11
12 12 create full repo
13 13
14 14 $ hg init master
15 15 $ cd master
16 16
17 17 $ mkdir inside
18 18 $ echo inside > inside/f1
19 19 $ mkdir outside
20 20 $ echo outside > outside/f1
21 21 $ hg ci -Aqm 'initial'
22 22
23 23 $ echo modified > inside/f1
24 24 $ hg ci -qm 'modify inside'
25 25
26 26 $ echo modified > outside/f1
27 27 $ hg ci -qm 'modify outside'
28 28
29 29 $ cd ..
30 30
31 31 (The lfs extension does nothing here, but this test ensures that its hook that
32 32 determines whether to add the lfs requirement, respects the narrow boundaries.)
33 33
34 34 $ hg --config extensions.lfs= clone --narrow ssh://user@dummy/master narrow \
35 35 > --include inside
36 36 requesting all changes
37 37 adding changesets
38 38 adding manifests
39 39 adding file changes
40 40 added 3 changesets with 2 changes to 1 files
41 41 new changesets *:* (glob)
42 42 updating to branch default
43 43 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 $ cd narrow
45 45
46 46 $ hg update -q 0
47 47
48 48 Can not modify dirstate outside
49 49
50 50 $ mkdir outside
51 51 $ touch outside/f1
52 52 $ hg debugwalk -v -I 'relglob:f1'
53 53 * matcher:
54 54 <includematcher includes='(?:(?:|.*/)f1(?:/|$))'>
55 55 f inside/f1 inside/f1
56 56 $ hg add outside/f1
57 57 abort: cannot track 'outside/f1' - it is outside the narrow clone
58 58 [255]
59 59 $ touch outside/f3
60 60 $ hg add outside/f3
61 61 abort: cannot track 'outside/f3' - it is outside the narrow clone
62 62 [255]
63 63
64 64 But adding a truly excluded file shouldn't count
65 65
66 66 $ hg add outside/f3 -X outside/f3
67 67
68 68 $ rm -r outside
69 69
70 70 Can modify dirstate inside
71 71
72 72 $ echo modified > inside/f1
73 73 $ touch inside/f3
74 74 $ hg add inside/f3
75 75 $ hg status
76 76 M inside/f1
77 77 A inside/f3
78 78 $ hg revert -qC .
79 79 $ rm inside/f3
80 80
81 81 Can commit changes inside. Leaves outside unchanged.
82 82
83 83 $ hg update -q 'desc("initial")'
84 84 $ echo modified2 > inside/f1
85 85 $ hg manifest --debug
86 86 4d6a634d5ba06331a60c29ee0db8412490a54fcd 644 inside/f1
87 87 7fb3bb6356d28d4dc352c5ba52d7350a81b6bd46 644 outside/f1 (flat !)
88 88 d0f2f706468ab0e8bec7af87446835fb1b13511b 755 d outside/ (tree !)
89 89 $ hg commit -m 'modify inside/f1'
90 90 created new head
91 91 $ hg files -r .
92 92 inside/f1
93 93 outside/f1 (flat !)
94 94 outside/ (tree !)
95 95 $ hg manifest --debug
96 96 3f4197b4a11b9016e77ebc47fe566944885fd11b 644 inside/f1
97 97 7fb3bb6356d28d4dc352c5ba52d7350a81b6bd46 644 outside/f1 (flat !)
98 98 d0f2f706468ab0e8bec7af87446835fb1b13511b 755 d outside/ (tree !)
99 99 Some filesystems (notably FAT/exFAT only store timestamps with 2
100 100 seconds of precision, so by sleeping for 3 seconds, we can ensure that
101 101 the timestamps of files stored by dirstate will appear older than the
102 102 dirstate file, and therefore we'll be able to get stable output from
103 103 debugdirstate. If we don't do this, the test can be slightly flaky.
104 104 $ sleep 3
105 105 $ hg status
106 $ hg debugdirstate --nodates
106 $ hg debugdirstate --no-dates
107 107 n 644 10 set inside/f1
@@ -1,125 +1,125 b''
1 1
2 2 $ cat > adddrop.py <<EOF
3 3 > from mercurial import registrar
4 4 > cmdtable = {}
5 5 > command = registrar.command(cmdtable)
6 6 > @command(b'debugadddrop',
7 7 > [(b'', b'drop', False, b'drop file from dirstate', b'FILE'),
8 8 > (b'', b'normal-lookup', False, b'add file to dirstate', b'FILE')],
9 9 > b'hg debugadddrop')
10 10 > def debugadddrop(ui, repo, *pats, **opts):
11 11 > '''Add or drop unnamed arguments to or from the dirstate'''
12 12 > drop = opts.get('drop')
13 13 > nl = opts.get('normal_lookup')
14 14 > if nl and drop:
15 15 > raise error.Abort('drop and normal-lookup are mutually exclusive')
16 16 > wlock = repo.wlock()
17 17 > try:
18 18 > for file in pats:
19 19 > if opts.get('normal_lookup'):
20 20 > repo.dirstate.normallookup(file)
21 21 > else:
22 22 > repo.dirstate.drop(file)
23 23 >
24 24 > repo.dirstate.write(repo.currenttransaction())
25 25 > finally:
26 26 > wlock.release()
27 27 > EOF
28 28
29 29 $ echo "[extensions]" >> $HGRCPATH
30 30 $ echo "debugadddrop=`pwd`/adddrop.py" >> $HGRCPATH
31 31
32 32 basic test for hg debugrebuildstate
33 33
34 34 $ hg init repo
35 35 $ cd repo
36 36
37 37 $ touch foo bar
38 38 $ hg ci -Am 'add foo bar'
39 39 adding bar
40 40 adding foo
41 41
42 42 $ touch baz
43 43 $ hg add baz
44 44 $ hg rm bar
45 45
46 46 $ hg debugrebuildstate
47 47
48 48 state dump after
49 49
50 $ hg debugstate --nodates | sort
50 $ hg debugstate --no-dates | sort
51 51 n 0 -1 unset bar
52 52 n 0 -1 unset foo
53 53
54 54 $ hg debugadddrop --normal-lookup file1 file2
55 55 $ hg debugadddrop --drop bar
56 56 $ hg debugadddrop --drop
57 $ hg debugstate --nodates
57 $ hg debugstate --no-dates
58 58 n 0 -1 unset file1
59 59 n 0 -1 unset file2
60 60 n 0 -1 unset foo
61 61 $ hg debugrebuildstate
62 62
63 63 status
64 64
65 65 $ hg st -A
66 66 ! bar
67 67 ? baz
68 68 C foo
69 69
70 70 Test debugdirstate --minimal where a file is not in parent manifest
71 71 but in the dirstate
72 72 $ touch foo bar qux
73 73 $ hg add qux
74 74 $ hg remove bar
75 75 $ hg status -A
76 76 A qux
77 77 R bar
78 78 ? baz
79 79 C foo
80 80 $ hg debugadddrop --normal-lookup baz
81 $ hg debugdirstate --nodates
81 $ hg debugdirstate --no-dates
82 82 r 0 0 * bar (glob)
83 83 n 0 -1 * baz (glob)
84 84 n 644 0 * foo (glob)
85 85 a 0 -1 * qux (glob)
86 86 $ hg debugrebuilddirstate --minimal
87 $ hg debugdirstate --nodates
87 $ hg debugdirstate --no-dates
88 88 r 0 0 * bar (glob)
89 89 n 644 0 * foo (glob)
90 90 a 0 -1 * qux (glob)
91 91 $ hg status -A
92 92 A qux
93 93 R bar
94 94 ? baz
95 95 C foo
96 96
97 97 Test debugdirstate --minimal where file is in the parent manifest but not the
98 98 dirstate
99 99 $ hg manifest
100 100 bar
101 101 foo
102 102 $ hg status -A
103 103 A qux
104 104 R bar
105 105 ? baz
106 106 C foo
107 $ hg debugdirstate --nodates
107 $ hg debugdirstate --no-dates
108 108 r 0 0 * bar (glob)
109 109 n 644 0 * foo (glob)
110 110 a 0 -1 * qux (glob)
111 111 $ hg debugadddrop --drop foo
112 $ hg debugdirstate --nodates
112 $ hg debugdirstate --no-dates
113 113 r 0 0 * bar (glob)
114 114 a 0 -1 * qux (glob)
115 115 $ hg debugrebuilddirstate --minimal
116 $ hg debugdirstate --nodates
116 $ hg debugdirstate --no-dates
117 117 r 0 0 * bar (glob)
118 118 n 0 -1 * foo (glob)
119 119 a 0 -1 * qux (glob)
120 120 $ hg status -A
121 121 A qux
122 122 R bar
123 123 ? baz
124 124 C foo
125 125
@@ -1,422 +1,422 b''
1 1 test sparse
2 2
3 3 $ hg init myrepo
4 4 $ cd myrepo
5 5 $ cat > .hg/hgrc <<EOF
6 6 > [extensions]
7 7 > sparse=
8 8 > strip=
9 9 > EOF
10 10
11 11 $ echo a > show
12 12 $ echo x > hide
13 13 $ hg ci -Aqm 'initial'
14 14
15 15 $ echo b > show
16 16 $ echo y > hide
17 17 $ echo aa > show2
18 18 $ echo xx > hide2
19 19 $ hg ci -Aqm 'two'
20 20
21 21 Verify basic --include
22 22
23 23 $ hg up -q 0
24 24 $ hg debugsparse --include 'hide'
25 25 $ ls
26 26 hide
27 27
28 28 Absolute paths outside the repo should just be rejected
29 29
30 30 #if no-windows
31 31 $ hg debugsparse --include /foo/bar
32 32 abort: paths cannot be absolute
33 33 [255]
34 34 $ hg debugsparse --include '$TESTTMP/myrepo/hide'
35 35
36 36 $ hg debugsparse --include '/root'
37 37 abort: paths cannot be absolute
38 38 [255]
39 39 #else
40 40 TODO: See if this can be made to fail the same way as on Unix
41 41 $ hg debugsparse --include /c/foo/bar
42 42 abort: paths cannot be absolute
43 43 [255]
44 44 $ hg debugsparse --include '$TESTTMP/myrepo/hide'
45 45
46 46 $ hg debugsparse --include '/c/root'
47 47 abort: paths cannot be absolute
48 48 [255]
49 49 #endif
50 50
51 51 Paths should be treated as cwd-relative, not repo-root-relative
52 52 $ mkdir subdir && cd subdir
53 53 $ hg debugsparse --include path
54 54 $ hg debugsparse
55 55 [include]
56 56 $TESTTMP/myrepo/hide
57 57 hide
58 58 subdir/path
59 59
60 60 $ cd ..
61 61 $ echo hello > subdir/file2.ext
62 62 $ cd subdir
63 63 $ hg debugsparse --include '**.ext' # let us test globs
64 64 $ hg debugsparse --include 'path:abspath' # and a path: pattern
65 65 $ cd ..
66 66 $ hg debugsparse
67 67 [include]
68 68 $TESTTMP/myrepo/hide
69 69 hide
70 70 path:abspath
71 71 subdir/**.ext
72 72 subdir/path
73 73
74 74 $ rm -rf subdir
75 75
76 76 Verify commiting while sparse includes other files
77 77
78 78 $ echo z > hide
79 79 $ hg ci -Aqm 'edit hide'
80 80 $ ls
81 81 hide
82 82 $ hg manifest
83 83 hide
84 84 show
85 85
86 86 Verify --reset brings files back
87 87
88 88 $ hg debugsparse --reset
89 89 $ ls
90 90 hide
91 91 show
92 92 $ cat hide
93 93 z
94 94 $ cat show
95 95 a
96 96
97 97 Verify 'hg debugsparse' default output
98 98
99 99 $ hg up -q null
100 100 $ hg debugsparse --include 'show*'
101 101
102 102 $ hg debugsparse
103 103 [include]
104 104 show*
105 105
106 106 Verify update only writes included files
107 107
108 108 $ hg up -q 0
109 109 $ ls
110 110 show
111 111
112 112 $ hg up -q 1
113 113 $ ls
114 114 show
115 115 show2
116 116
117 117 Verify status only shows included files
118 118
119 119 $ touch hide
120 120 $ touch hide3
121 121 $ echo c > show
122 122 $ hg status
123 123 M show
124 124
125 125 Adding an excluded file should fail
126 126
127 127 $ hg add hide3
128 128 abort: cannot add 'hide3' - it is outside the sparse checkout
129 129 (include file with `hg debugsparse --include <pattern>` or use `hg add -s <file>` to include file directory while adding)
130 130 [255]
131 131
132 132 But adding a truly excluded file shouldn't count
133 133
134 134 $ hg add hide3 -X hide3
135 135
136 136 Verify deleting sparseness while a file has changes fails
137 137
138 138 $ hg debugsparse --delete 'show*'
139 139 pending changes to 'hide'
140 140 abort: cannot change sparseness due to pending changes (delete the files or use --force to bring them back dirty)
141 141 [255]
142 142
143 143 Verify deleting sparseness with --force brings back files
144 144
145 145 $ hg debugsparse --delete -f 'show*'
146 146 pending changes to 'hide'
147 147 $ ls
148 148 hide
149 149 hide2
150 150 hide3
151 151 show
152 152 show2
153 153 $ hg st
154 154 M hide
155 155 M show
156 156 ? hide3
157 157
158 158 Verify editing sparseness fails if pending changes
159 159
160 160 $ hg debugsparse --include 'show*'
161 161 pending changes to 'hide'
162 162 abort: could not update sparseness due to pending changes
163 163 [255]
164 164
165 165 Verify adding sparseness hides files
166 166
167 167 $ hg debugsparse --exclude -f 'hide*'
168 168 pending changes to 'hide'
169 169 $ ls
170 170 hide
171 171 hide3
172 172 show
173 173 show2
174 174 $ hg st
175 175 M show
176 176
177 177 $ hg up -qC .
178 178 TODO: add an option to purge to also purge files outside the sparse config?
179 179 $ hg purge --all --config extensions.purge=
180 180 $ ls
181 181 hide
182 182 hide3
183 183 show
184 184 show2
185 185 For now, manually remove the files
186 186 $ rm hide hide3
187 187
188 188 Verify rebase temporarily includes excluded files
189 189
190 190 $ hg rebase -d 1 -r 2 --config extensions.rebase=
191 191 rebasing 2:b91df4f39e75 "edit hide" (tip)
192 192 temporarily included 2 file(s) in the sparse checkout for merging
193 193 merging hide
194 194 warning: conflicts while merging hide! (edit, then use 'hg resolve --mark')
195 195 unresolved conflicts (see hg resolve, then hg rebase --continue)
196 196 [1]
197 197
198 198 $ hg debugsparse
199 199 [exclude]
200 200 hide*
201 201
202 202 Temporarily Included Files (for merge/rebase):
203 203 hide
204 204
205 205 $ cat hide
206 206 <<<<<<< dest: 39278f7c08a9 - test: two
207 207 y
208 208 =======
209 209 z
210 210 >>>>>>> source: b91df4f39e75 - test: edit hide
211 211
212 212 Verify aborting a rebase cleans up temporary files
213 213
214 214 $ hg rebase --abort --config extensions.rebase=
215 215 cleaned up 1 temporarily added file(s) from the sparse checkout
216 216 rebase aborted
217 217 $ rm hide.orig
218 218
219 219 $ ls
220 220 show
221 221 show2
222 222
223 223 Verify merge fails if merging excluded files
224 224
225 225 $ hg up -q 1
226 226 $ hg merge -r 2
227 227 temporarily included 2 file(s) in the sparse checkout for merging
228 228 merging hide
229 229 warning: conflicts while merging hide! (edit, then use 'hg resolve --mark')
230 230 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
231 231 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
232 232 [1]
233 233 $ hg debugsparse
234 234 [exclude]
235 235 hide*
236 236
237 237 Temporarily Included Files (for merge/rebase):
238 238 hide
239 239
240 240 $ hg up -C .
241 241 cleaned up 1 temporarily added file(s) from the sparse checkout
242 242 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
243 243 $ hg debugsparse
244 244 [exclude]
245 245 hide*
246 246
247 247
248 248 Verify strip -k resets dirstate correctly
249 249
250 250 $ hg status
251 251 $ hg debugsparse
252 252 [exclude]
253 253 hide*
254 254
255 255 $ hg log -r . -T '{rev}\n' --stat
256 256 1
257 257 hide | 2 +-
258 258 hide2 | 1 +
259 259 show | 2 +-
260 260 show2 | 1 +
261 261 4 files changed, 4 insertions(+), 2 deletions(-)
262 262
263 263 $ hg strip -r . -k
264 264 saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/39278f7c08a9-ce59e002-backup.hg
265 265 $ hg status
266 266 M show
267 267 ? show2
268 268
269 269 Verify rebase succeeds if all changed files are in sparse checkout
270 270
271 271 $ hg commit -Aqm "add show2"
272 272 $ hg rebase -d 1 --config extensions.rebase=
273 273 rebasing 2:bdde55290160 "add show2" (tip)
274 274 saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/bdde55290160-216ed9c6-rebase.hg
275 275
276 276 Verify log --sparse only shows commits that affect the sparse checkout
277 277
278 278 $ hg log -T '{rev} '
279 279 2 1 0 (no-eol)
280 280 $ hg log --sparse -T '{rev} '
281 281 2 0 (no-eol)
282 282
283 283 Test status on a file in a subdir
284 284
285 285 $ mkdir -p dir1/dir2
286 286 $ touch dir1/dir2/file
287 287 $ hg debugsparse -I dir1/dir2
288 288 $ hg status
289 289 ? dir1/dir2/file
290 290
291 291 Mix files and subdirectories, both "glob:" and unprefixed
292 292
293 293 $ hg debugsparse --reset
294 294 $ touch dir1/notshown
295 295 $ hg commit -A dir1/notshown -m "notshown"
296 296 $ hg debugsparse --include 'dir1/dir2'
297 297 $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
298 298 ./
299 299 ./dir1/
300 300 ./dir1/dir2/
301 301 ./dir1/dir2/file
302 302 ./hide.orig
303 303 $ hg debugsparse --delete 'dir1/dir2'
304 304 $ hg debugsparse --include 'glob:dir1/dir2'
305 305 $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
306 306 ./
307 307 ./dir1/
308 308 ./dir1/dir2/
309 309 ./dir1/dir2/file
310 310 ./hide.orig
311 311
312 312 Test that add -s adds dirs to sparse profile
313 313
314 314 $ hg debugsparse --reset
315 315 $ hg debugsparse --include empty
316 316 $ hg debugsparse
317 317 [include]
318 318 empty
319 319
320 320
321 321 $ mkdir add
322 322 $ touch add/foo
323 323 $ touch add/bar
324 324 $ hg add add/foo
325 325 abort: cannot add 'add/foo' - it is outside the sparse checkout
326 326 (include file with `hg debugsparse --include <pattern>` or use `hg add -s <file>` to include file directory while adding)
327 327 [255]
328 328 $ hg add -s add/foo
329 329 $ hg st
330 330 A add/foo
331 331 ? add/bar
332 332 $ hg debugsparse
333 333 [include]
334 334 add
335 335 empty
336 336
337 337 $ hg add -s add/*
338 338 add/foo already tracked!
339 339 $ hg st
340 340 A add/bar
341 341 A add/foo
342 342 $ hg debugsparse
343 343 [include]
344 344 add
345 345 empty
346 346
347 347
348 348 $ cd ..
349 349
350 350 Test non-sparse repos work while sparse is loaded
351 351 $ hg init sparserepo
352 352 $ hg init nonsparserepo
353 353 $ cd sparserepo
354 354 $ cat > .hg/hgrc <<EOF
355 355 > [extensions]
356 356 > sparse=
357 357 > EOF
358 358 $ cd ../nonsparserepo
359 359 $ echo x > x && hg add x && hg commit -qAm x
360 360 $ cd ../sparserepo
361 361 $ hg clone ../nonsparserepo ../nonsparserepo2
362 362 updating to branch default
363 363 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
364 364
365 365 Test debugrebuilddirstate
366 366 $ cd ../sparserepo
367 367 $ touch included
368 368 $ touch excluded
369 369 $ hg add included excluded
370 370 $ hg commit -m 'a commit' -q
371 371 $ cp .hg/dirstate ../dirstateboth
372 372 $ hg debugsparse -X excluded
373 373 $ cp ../dirstateboth .hg/dirstate
374 374 $ hg debugrebuilddirstate
375 375 $ hg debugdirstate
376 376 n 0 -1 unset included
377 377
378 378 Test debugdirstate --minimal where file is in the parent manifest but not the
379 379 dirstate
380 380 $ hg debugsparse -X included
381 381 $ hg debugdirstate
382 382 $ cp .hg/dirstate ../dirstateallexcluded
383 383 $ hg debugsparse --reset
384 384 $ hg debugsparse -X excluded
385 385 $ cp ../dirstateallexcluded .hg/dirstate
386 386 $ touch includedadded
387 387 $ hg add includedadded
388 $ hg debugdirstate --nodates
388 $ hg debugdirstate --no-dates
389 389 a 0 -1 unset includedadded
390 390 $ hg debugrebuilddirstate --minimal
391 $ hg debugdirstate --nodates
391 $ hg debugdirstate --no-dates
392 392 n 0 -1 unset included
393 393 a 0 -1 * includedadded (glob)
394 394
395 395 Test debugdirstate --minimal where a file is not in parent manifest
396 396 but in the dirstate. This should take into account excluded files in the
397 397 manifest
398 398 $ cp ../dirstateboth .hg/dirstate
399 399 $ touch includedadded
400 400 $ hg add includedadded
401 401 $ touch excludednomanifest
402 402 $ hg add excludednomanifest
403 403 $ cp .hg/dirstate ../moreexcluded
404 404 $ hg forget excludednomanifest
405 405 $ rm excludednomanifest
406 406 $ hg debugsparse -X excludednomanifest
407 407 $ cp ../moreexcluded .hg/dirstate
408 408 $ hg manifest
409 409 excluded
410 410 included
411 411 We have files in the dirstate that are included and excluded. Some are in the
412 412 manifest and some are not.
413 $ hg debugdirstate --nodates
413 $ hg debugdirstate --no-dates
414 414 n 644 0 * excluded (glob)
415 415 a 0 -1 * excludednomanifest (glob)
416 416 n 644 0 * included (glob)
417 417 a 0 -1 * includedadded (glob)
418 418 $ hg debugrebuilddirstate --minimal
419 $ hg debugdirstate --nodates
419 $ hg debugdirstate --no-dates
420 420 n 644 0 * included (glob)
421 421 a 0 -1 * includedadded (glob)
422 422
General Comments 0
You need to be logged in to leave comments. Login now