##// END OF EJS Templates
debugcommands: drop offset and length from debugindex by default...
Gregory Szorc -
r37301:d4e62df1 default
parent child Browse files
Show More
@@ -1,3056 +1,3075 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 tempfile
25 25 import time
26 26
27 27 from .i18n import _
28 28 from .node import (
29 29 bin,
30 30 hex,
31 31 nullhex,
32 32 nullid,
33 33 nullrev,
34 34 short,
35 35 )
36 36 from . import (
37 37 bundle2,
38 38 changegroup,
39 39 cmdutil,
40 40 color,
41 41 context,
42 42 dagparser,
43 43 dagutil,
44 44 encoding,
45 45 error,
46 46 exchange,
47 47 extensions,
48 48 filemerge,
49 49 fileset,
50 50 formatter,
51 51 hg,
52 52 httppeer,
53 53 localrepo,
54 54 lock as lockmod,
55 55 logcmdutil,
56 56 merge as mergemod,
57 57 obsolete,
58 58 obsutil,
59 59 phases,
60 60 policy,
61 61 pvec,
62 62 pycompat,
63 63 registrar,
64 64 repair,
65 65 revlog,
66 66 revset,
67 67 revsetlang,
68 68 scmutil,
69 69 setdiscovery,
70 70 simplemerge,
71 71 smartset,
72 72 sshpeer,
73 73 sslutil,
74 74 streamclone,
75 75 templater,
76 76 treediscovery,
77 77 upgrade,
78 78 url as urlmod,
79 79 util,
80 80 vfs as vfsmod,
81 81 wireprotoframing,
82 82 wireprotoserver,
83 83 )
84 84 from .utils import (
85 85 dateutil,
86 86 procutil,
87 87 stringutil,
88 88 )
89 89
90 90 release = lockmod.release
91 91
92 92 command = registrar.command()
93 93
94 94 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
95 95 def debugancestor(ui, repo, *args):
96 96 """find the ancestor revision of two revisions in a given index"""
97 97 if len(args) == 3:
98 98 index, rev1, rev2 = args
99 99 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
100 100 lookup = r.lookup
101 101 elif len(args) == 2:
102 102 if not repo:
103 103 raise error.Abort(_('there is no Mercurial repository here '
104 104 '(.hg not found)'))
105 105 rev1, rev2 = args
106 106 r = repo.changelog
107 107 lookup = repo.lookup
108 108 else:
109 109 raise error.Abort(_('either two or three arguments required'))
110 110 a = r.ancestor(lookup(rev1), lookup(rev2))
111 111 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
112 112
113 113 @command('debugapplystreamclonebundle', [], 'FILE')
114 114 def debugapplystreamclonebundle(ui, repo, fname):
115 115 """apply a stream clone bundle file"""
116 116 f = hg.openpath(ui, fname)
117 117 gen = exchange.readbundle(ui, f, fname)
118 118 gen.apply(repo)
119 119
120 120 @command('debugbuilddag',
121 121 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
122 122 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
123 123 ('n', 'new-file', None, _('add new file at each rev'))],
124 124 _('[OPTION]... [TEXT]'))
125 125 def debugbuilddag(ui, repo, text=None,
126 126 mergeable_file=False,
127 127 overwritten_file=False,
128 128 new_file=False):
129 129 """builds a repo with a given DAG from scratch in the current empty repo
130 130
131 131 The description of the DAG is read from stdin if not given on the
132 132 command line.
133 133
134 134 Elements:
135 135
136 136 - "+n" is a linear run of n nodes based on the current default parent
137 137 - "." is a single node based on the current default parent
138 138 - "$" resets the default parent to null (implied at the start);
139 139 otherwise the default parent is always the last node created
140 140 - "<p" sets the default parent to the backref p
141 141 - "*p" is a fork at parent p, which is a backref
142 142 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
143 143 - "/p2" is a merge of the preceding node and p2
144 144 - ":tag" defines a local tag for the preceding node
145 145 - "@branch" sets the named branch for subsequent nodes
146 146 - "#...\\n" is a comment up to the end of the line
147 147
148 148 Whitespace between the above elements is ignored.
149 149
150 150 A backref is either
151 151
152 152 - a number n, which references the node curr-n, where curr is the current
153 153 node, or
154 154 - the name of a local tag you placed earlier using ":tag", or
155 155 - empty to denote the default parent.
156 156
157 157 All string valued-elements are either strictly alphanumeric, or must
158 158 be enclosed in double quotes ("..."), with "\\" as escape character.
159 159 """
160 160
161 161 if text is None:
162 162 ui.status(_("reading DAG from stdin\n"))
163 163 text = ui.fin.read()
164 164
165 165 cl = repo.changelog
166 166 if len(cl) > 0:
167 167 raise error.Abort(_('repository is not empty'))
168 168
169 169 # determine number of revs in DAG
170 170 total = 0
171 171 for type, data in dagparser.parsedag(text):
172 172 if type == 'n':
173 173 total += 1
174 174
175 175 if mergeable_file:
176 176 linesperrev = 2
177 177 # make a file with k lines per rev
178 178 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
179 179 initialmergedlines.append("")
180 180
181 181 tags = []
182 182
183 183 wlock = lock = tr = None
184 184 try:
185 185 wlock = repo.wlock()
186 186 lock = repo.lock()
187 187 tr = repo.transaction("builddag")
188 188
189 189 at = -1
190 190 atbranch = 'default'
191 191 nodeids = []
192 192 id = 0
193 193 ui.progress(_('building'), id, unit=_('revisions'), total=total)
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 ui.progress(_('building'), id, unit=_('revisions'), total=total)
267 267 tr.close()
268 268
269 269 if tags:
270 270 repo.vfs.write("localtags", "".join(tags))
271 271 finally:
272 272 ui.progress(_('building'), None)
273 273 release(tr, lock, wlock)
274 274
275 275 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
276 276 indent_string = ' ' * indent
277 277 if all:
278 278 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
279 279 % indent_string)
280 280
281 281 def showchunks(named):
282 282 ui.write("\n%s%s\n" % (indent_string, named))
283 283 for deltadata in gen.deltaiter():
284 284 node, p1, p2, cs, deltabase, delta, flags = deltadata
285 285 ui.write("%s%s %s %s %s %s %d\n" %
286 286 (indent_string, hex(node), hex(p1), hex(p2),
287 287 hex(cs), hex(deltabase), len(delta)))
288 288
289 289 chunkdata = gen.changelogheader()
290 290 showchunks("changelog")
291 291 chunkdata = gen.manifestheader()
292 292 showchunks("manifest")
293 293 for chunkdata in iter(gen.filelogheader, {}):
294 294 fname = chunkdata['filename']
295 295 showchunks(fname)
296 296 else:
297 297 if isinstance(gen, bundle2.unbundle20):
298 298 raise error.Abort(_('use debugbundle2 for this file'))
299 299 chunkdata = gen.changelogheader()
300 300 for deltadata in gen.deltaiter():
301 301 node, p1, p2, cs, deltabase, delta, flags = deltadata
302 302 ui.write("%s%s\n" % (indent_string, hex(node)))
303 303
304 304 def _debugobsmarkers(ui, part, indent=0, **opts):
305 305 """display version and markers contained in 'data'"""
306 306 opts = pycompat.byteskwargs(opts)
307 307 data = part.read()
308 308 indent_string = ' ' * indent
309 309 try:
310 310 version, markers = obsolete._readmarkers(data)
311 311 except error.UnknownVersion as exc:
312 312 msg = "%sunsupported version: %s (%d bytes)\n"
313 313 msg %= indent_string, exc.version, len(data)
314 314 ui.write(msg)
315 315 else:
316 316 msg = "%sversion: %d (%d bytes)\n"
317 317 msg %= indent_string, version, len(data)
318 318 ui.write(msg)
319 319 fm = ui.formatter('debugobsolete', opts)
320 320 for rawmarker in sorted(markers):
321 321 m = obsutil.marker(None, rawmarker)
322 322 fm.startitem()
323 323 fm.plain(indent_string)
324 324 cmdutil.showmarker(fm, m)
325 325 fm.end()
326 326
327 327 def _debugphaseheads(ui, data, indent=0):
328 328 """display version and markers contained in 'data'"""
329 329 indent_string = ' ' * indent
330 330 headsbyphase = phases.binarydecode(data)
331 331 for phase in phases.allphases:
332 332 for head in headsbyphase[phase]:
333 333 ui.write(indent_string)
334 334 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
335 335
336 336 def _quasirepr(thing):
337 337 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
338 338 return '{%s}' % (
339 339 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
340 340 return pycompat.bytestr(repr(thing))
341 341
342 342 def _debugbundle2(ui, gen, all=None, **opts):
343 343 """lists the contents of a bundle2"""
344 344 if not isinstance(gen, bundle2.unbundle20):
345 345 raise error.Abort(_('not a bundle2 file'))
346 346 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
347 347 parttypes = opts.get(r'part_type', [])
348 348 for part in gen.iterparts():
349 349 if parttypes and part.type not in parttypes:
350 350 continue
351 351 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
352 352 if part.type == 'changegroup':
353 353 version = part.params.get('version', '01')
354 354 cg = changegroup.getunbundler(version, part, 'UN')
355 355 if not ui.quiet:
356 356 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
357 357 if part.type == 'obsmarkers':
358 358 if not ui.quiet:
359 359 _debugobsmarkers(ui, part, indent=4, **opts)
360 360 if part.type == 'phase-heads':
361 361 if not ui.quiet:
362 362 _debugphaseheads(ui, part, indent=4)
363 363
364 364 @command('debugbundle',
365 365 [('a', 'all', None, _('show all details')),
366 366 ('', 'part-type', [], _('show only the named part type')),
367 367 ('', 'spec', None, _('print the bundlespec of the bundle'))],
368 368 _('FILE'),
369 369 norepo=True)
370 370 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
371 371 """lists the contents of a bundle"""
372 372 with hg.openpath(ui, bundlepath) as f:
373 373 if spec:
374 374 spec = exchange.getbundlespec(ui, f)
375 375 ui.write('%s\n' % spec)
376 376 return
377 377
378 378 gen = exchange.readbundle(ui, f, bundlepath)
379 379 if isinstance(gen, bundle2.unbundle20):
380 380 return _debugbundle2(ui, gen, all=all, **opts)
381 381 _debugchangegroup(ui, gen, all=all, **opts)
382 382
383 383 @command('debugcapabilities',
384 384 [], _('PATH'),
385 385 norepo=True)
386 386 def debugcapabilities(ui, path, **opts):
387 387 """lists the capabilities of a remote peer"""
388 388 opts = pycompat.byteskwargs(opts)
389 389 peer = hg.peer(ui, opts, path)
390 390 caps = peer.capabilities()
391 391 ui.write(('Main capabilities:\n'))
392 392 for c in sorted(caps):
393 393 ui.write((' %s\n') % c)
394 394 b2caps = bundle2.bundle2caps(peer)
395 395 if b2caps:
396 396 ui.write(('Bundle2 capabilities:\n'))
397 397 for key, values in sorted(b2caps.iteritems()):
398 398 ui.write((' %s\n') % key)
399 399 for v in values:
400 400 ui.write((' %s\n') % v)
401 401
402 402 @command('debugcheckstate', [], '')
403 403 def debugcheckstate(ui, repo):
404 404 """validate the correctness of the current dirstate"""
405 405 parent1, parent2 = repo.dirstate.parents()
406 406 m1 = repo[parent1].manifest()
407 407 m2 = repo[parent2].manifest()
408 408 errors = 0
409 409 for f in repo.dirstate:
410 410 state = repo.dirstate[f]
411 411 if state in "nr" and f not in m1:
412 412 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
413 413 errors += 1
414 414 if state in "a" and f in m1:
415 415 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
416 416 errors += 1
417 417 if state in "m" and f not in m1 and f not in m2:
418 418 ui.warn(_("%s in state %s, but not in either manifest\n") %
419 419 (f, state))
420 420 errors += 1
421 421 for f in m1:
422 422 state = repo.dirstate[f]
423 423 if state not in "nrm":
424 424 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
425 425 errors += 1
426 426 if errors:
427 427 error = _(".hg/dirstate inconsistent with current parent's manifest")
428 428 raise error.Abort(error)
429 429
430 430 @command('debugcolor',
431 431 [('', 'style', None, _('show all configured styles'))],
432 432 'hg debugcolor')
433 433 def debugcolor(ui, repo, **opts):
434 434 """show available color, effects or style"""
435 435 ui.write(('color mode: %s\n') % ui._colormode)
436 436 if opts.get(r'style'):
437 437 return _debugdisplaystyle(ui)
438 438 else:
439 439 return _debugdisplaycolor(ui)
440 440
441 441 def _debugdisplaycolor(ui):
442 442 ui = ui.copy()
443 443 ui._styles.clear()
444 444 for effect in color._activeeffects(ui).keys():
445 445 ui._styles[effect] = effect
446 446 if ui._terminfoparams:
447 447 for k, v in ui.configitems('color'):
448 448 if k.startswith('color.'):
449 449 ui._styles[k] = k[6:]
450 450 elif k.startswith('terminfo.'):
451 451 ui._styles[k] = k[9:]
452 452 ui.write(_('available colors:\n'))
453 453 # sort label with a '_' after the other to group '_background' entry.
454 454 items = sorted(ui._styles.items(),
455 455 key=lambda i: ('_' in i[0], i[0], i[1]))
456 456 for colorname, label in items:
457 457 ui.write(('%s\n') % colorname, label=label)
458 458
459 459 def _debugdisplaystyle(ui):
460 460 ui.write(_('available style:\n'))
461 461 width = max(len(s) for s in ui._styles)
462 462 for label, effects in sorted(ui._styles.items()):
463 463 ui.write('%s' % label, label=label)
464 464 if effects:
465 465 # 50
466 466 ui.write(': ')
467 467 ui.write(' ' * (max(0, width - len(label))))
468 468 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
469 469 ui.write('\n')
470 470
471 471 @command('debugcreatestreamclonebundle', [], 'FILE')
472 472 def debugcreatestreamclonebundle(ui, repo, fname):
473 473 """create a stream clone bundle file
474 474
475 475 Stream bundles are special bundles that are essentially archives of
476 476 revlog files. They are commonly used for cloning very quickly.
477 477 """
478 478 # TODO we may want to turn this into an abort when this functionality
479 479 # is moved into `hg bundle`.
480 480 if phases.hassecret(repo):
481 481 ui.warn(_('(warning: stream clone bundle will contain secret '
482 482 'revisions)\n'))
483 483
484 484 requirements, gen = streamclone.generatebundlev1(repo)
485 485 changegroup.writechunks(ui, gen, fname)
486 486
487 487 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
488 488
489 489 @command('debugdag',
490 490 [('t', 'tags', None, _('use tags as labels')),
491 491 ('b', 'branches', None, _('annotate with branch names')),
492 492 ('', 'dots', None, _('use dots for runs')),
493 493 ('s', 'spaces', None, _('separate elements by spaces'))],
494 494 _('[OPTION]... [FILE [REV]...]'),
495 495 optionalrepo=True)
496 496 def debugdag(ui, repo, file_=None, *revs, **opts):
497 497 """format the changelog or an index DAG as a concise textual description
498 498
499 499 If you pass a revlog index, the revlog's DAG is emitted. If you list
500 500 revision numbers, they get labeled in the output as rN.
501 501
502 502 Otherwise, the changelog DAG of the current repo is emitted.
503 503 """
504 504 spaces = opts.get(r'spaces')
505 505 dots = opts.get(r'dots')
506 506 if file_:
507 507 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
508 508 file_)
509 509 revs = set((int(r) for r in revs))
510 510 def events():
511 511 for r in rlog:
512 512 yield 'n', (r, list(p for p in rlog.parentrevs(r)
513 513 if p != -1))
514 514 if r in revs:
515 515 yield 'l', (r, "r%i" % r)
516 516 elif repo:
517 517 cl = repo.changelog
518 518 tags = opts.get(r'tags')
519 519 branches = opts.get(r'branches')
520 520 if tags:
521 521 labels = {}
522 522 for l, n in repo.tags().items():
523 523 labels.setdefault(cl.rev(n), []).append(l)
524 524 def events():
525 525 b = "default"
526 526 for r in cl:
527 527 if branches:
528 528 newb = cl.read(cl.node(r))[5]['branch']
529 529 if newb != b:
530 530 yield 'a', newb
531 531 b = newb
532 532 yield 'n', (r, list(p for p in cl.parentrevs(r)
533 533 if p != -1))
534 534 if tags:
535 535 ls = labels.get(r)
536 536 if ls:
537 537 for l in ls:
538 538 yield 'l', (r, l)
539 539 else:
540 540 raise error.Abort(_('need repo for changelog dag'))
541 541
542 542 for line in dagparser.dagtextlines(events(),
543 543 addspaces=spaces,
544 544 wraplabels=True,
545 545 wrapannotations=True,
546 546 wrapnonlinear=dots,
547 547 usedots=dots,
548 548 maxlinewidth=70):
549 549 ui.write(line)
550 550 ui.write("\n")
551 551
552 552 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
553 553 def debugdata(ui, repo, file_, rev=None, **opts):
554 554 """dump the contents of a data file revision"""
555 555 opts = pycompat.byteskwargs(opts)
556 556 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
557 557 if rev is not None:
558 558 raise error.CommandError('debugdata', _('invalid arguments'))
559 559 file_, rev = None, file_
560 560 elif rev is None:
561 561 raise error.CommandError('debugdata', _('invalid arguments'))
562 562 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
563 563 try:
564 564 ui.write(r.revision(r.lookup(rev), raw=True))
565 565 except KeyError:
566 566 raise error.Abort(_('invalid revision identifier %s') % rev)
567 567
568 568 @command('debugdate',
569 569 [('e', 'extended', None, _('try extended date formats'))],
570 570 _('[-e] DATE [RANGE]'),
571 571 norepo=True, optionalrepo=True)
572 572 def debugdate(ui, date, range=None, **opts):
573 573 """parse and display a date"""
574 574 if opts[r"extended"]:
575 575 d = dateutil.parsedate(date, util.extendeddateformats)
576 576 else:
577 577 d = dateutil.parsedate(date)
578 578 ui.write(("internal: %d %d\n") % d)
579 579 ui.write(("standard: %s\n") % dateutil.datestr(d))
580 580 if range:
581 581 m = dateutil.matchdate(range)
582 582 ui.write(("match: %s\n") % m(d[0]))
583 583
584 584 @command('debugdeltachain',
585 585 cmdutil.debugrevlogopts + cmdutil.formatteropts,
586 586 _('-c|-m|FILE'),
587 587 optionalrepo=True)
588 588 def debugdeltachain(ui, repo, file_=None, **opts):
589 589 """dump information about delta chains in a revlog
590 590
591 591 Output can be templatized. Available template keywords are:
592 592
593 593 :``rev``: revision number
594 594 :``chainid``: delta chain identifier (numbered by unique base)
595 595 :``chainlen``: delta chain length to this revision
596 596 :``prevrev``: previous revision in delta chain
597 597 :``deltatype``: role of delta / how it was computed
598 598 :``compsize``: compressed size of revision
599 599 :``uncompsize``: uncompressed size of revision
600 600 :``chainsize``: total size of compressed revisions in chain
601 601 :``chainratio``: total chain size divided by uncompressed revision size
602 602 (new delta chains typically start at ratio 2.00)
603 603 :``lindist``: linear distance from base revision in delta chain to end
604 604 of this revision
605 605 :``extradist``: total size of revisions not part of this delta chain from
606 606 base of delta chain to end of this revision; a measurement
607 607 of how much extra data we need to read/seek across to read
608 608 the delta chain for this revision
609 609 :``extraratio``: extradist divided by chainsize; another representation of
610 610 how much unrelated data is needed to load this delta chain
611 611
612 612 If the repository is configured to use the sparse read, additional keywords
613 613 are available:
614 614
615 615 :``readsize``: total size of data read from the disk for a revision
616 616 (sum of the sizes of all the blocks)
617 617 :``largestblock``: size of the largest block of data read from the disk
618 618 :``readdensity``: density of useful bytes in the data read from the disk
619 619 :``srchunks``: in how many data hunks the whole revision would be read
620 620
621 621 The sparse read can be enabled with experimental.sparse-read = True
622 622 """
623 623 opts = pycompat.byteskwargs(opts)
624 624 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
625 625 index = r.index
626 626 generaldelta = r.version & revlog.FLAG_GENERALDELTA
627 627 withsparseread = getattr(r, '_withsparseread', False)
628 628
629 629 def revinfo(rev):
630 630 e = index[rev]
631 631 compsize = e[1]
632 632 uncompsize = e[2]
633 633 chainsize = 0
634 634
635 635 if generaldelta:
636 636 if e[3] == e[5]:
637 637 deltatype = 'p1'
638 638 elif e[3] == e[6]:
639 639 deltatype = 'p2'
640 640 elif e[3] == rev - 1:
641 641 deltatype = 'prev'
642 642 elif e[3] == rev:
643 643 deltatype = 'base'
644 644 else:
645 645 deltatype = 'other'
646 646 else:
647 647 if e[3] == rev:
648 648 deltatype = 'base'
649 649 else:
650 650 deltatype = 'prev'
651 651
652 652 chain = r._deltachain(rev)[0]
653 653 for iterrev in chain:
654 654 e = index[iterrev]
655 655 chainsize += e[1]
656 656
657 657 return compsize, uncompsize, deltatype, chain, chainsize
658 658
659 659 fm = ui.formatter('debugdeltachain', opts)
660 660
661 661 fm.plain(' rev chain# chainlen prev delta '
662 662 'size rawsize chainsize ratio lindist extradist '
663 663 'extraratio')
664 664 if withsparseread:
665 665 fm.plain(' readsize largestblk rddensity srchunks')
666 666 fm.plain('\n')
667 667
668 668 chainbases = {}
669 669 for rev in r:
670 670 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
671 671 chainbase = chain[0]
672 672 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
673 673 start = r.start
674 674 length = r.length
675 675 basestart = start(chainbase)
676 676 revstart = start(rev)
677 677 lineardist = revstart + comp - basestart
678 678 extradist = lineardist - chainsize
679 679 try:
680 680 prevrev = chain[-2]
681 681 except IndexError:
682 682 prevrev = -1
683 683
684 684 chainratio = float(chainsize) / float(uncomp)
685 685 extraratio = float(extradist) / float(chainsize)
686 686
687 687 fm.startitem()
688 688 fm.write('rev chainid chainlen prevrev deltatype compsize '
689 689 'uncompsize chainsize chainratio lindist extradist '
690 690 'extraratio',
691 691 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
692 692 rev, chainid, len(chain), prevrev, deltatype, comp,
693 693 uncomp, chainsize, chainratio, lineardist, extradist,
694 694 extraratio,
695 695 rev=rev, chainid=chainid, chainlen=len(chain),
696 696 prevrev=prevrev, deltatype=deltatype, compsize=comp,
697 697 uncompsize=uncomp, chainsize=chainsize,
698 698 chainratio=chainratio, lindist=lineardist,
699 699 extradist=extradist, extraratio=extraratio)
700 700 if withsparseread:
701 701 readsize = 0
702 702 largestblock = 0
703 703 srchunks = 0
704 704
705 705 for revschunk in revlog._slicechunk(r, chain):
706 706 srchunks += 1
707 707 blkend = start(revschunk[-1]) + length(revschunk[-1])
708 708 blksize = blkend - start(revschunk[0])
709 709
710 710 readsize += blksize
711 711 if largestblock < blksize:
712 712 largestblock = blksize
713 713
714 714 readdensity = float(chainsize) / float(readsize)
715 715
716 716 fm.write('readsize largestblock readdensity srchunks',
717 717 ' %10d %10d %9.5f %8d',
718 718 readsize, largestblock, readdensity, srchunks,
719 719 readsize=readsize, largestblock=largestblock,
720 720 readdensity=readdensity, srchunks=srchunks)
721 721
722 722 fm.plain('\n')
723 723
724 724 fm.end()
725 725
726 726 @command('debugdirstate|debugstate',
727 727 [('', 'nodates', None, _('do not display the saved mtime')),
728 728 ('', 'datesort', None, _('sort by saved mtime'))],
729 729 _('[OPTION]...'))
730 730 def debugstate(ui, repo, **opts):
731 731 """show the contents of the current dirstate"""
732 732
733 733 nodates = opts.get(r'nodates')
734 734 datesort = opts.get(r'datesort')
735 735
736 736 timestr = ""
737 737 if datesort:
738 738 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
739 739 else:
740 740 keyfunc = None # sort by filename
741 741 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
742 742 if ent[3] == -1:
743 743 timestr = 'unset '
744 744 elif nodates:
745 745 timestr = 'set '
746 746 else:
747 747 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
748 748 time.localtime(ent[3]))
749 749 timestr = encoding.strtolocal(timestr)
750 750 if ent[1] & 0o20000:
751 751 mode = 'lnk'
752 752 else:
753 753 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
754 754 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
755 755 for f in repo.dirstate.copies():
756 756 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
757 757
758 758 @command('debugdiscovery',
759 759 [('', 'old', None, _('use old-style discovery')),
760 760 ('', 'nonheads', None,
761 761 _('use old-style discovery with non-heads included')),
762 762 ('', 'rev', [], 'restrict discovery to this set of revs'),
763 763 ] + cmdutil.remoteopts,
764 764 _('[--rev REV] [OTHER]'))
765 765 def debugdiscovery(ui, repo, remoteurl="default", **opts):
766 766 """runs the changeset discovery protocol in isolation"""
767 767 opts = pycompat.byteskwargs(opts)
768 768 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
769 769 remote = hg.peer(repo, opts, remoteurl)
770 770 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
771 771
772 772 # make sure tests are repeatable
773 773 random.seed(12323)
774 774
775 775 def doit(pushedrevs, remoteheads, remote=remote):
776 776 if opts.get('old'):
777 777 if not util.safehasattr(remote, 'branches'):
778 778 # enable in-client legacy support
779 779 remote = localrepo.locallegacypeer(remote.local())
780 780 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
781 781 force=True)
782 782 common = set(common)
783 783 if not opts.get('nonheads'):
784 784 ui.write(("unpruned common: %s\n") %
785 785 " ".join(sorted(short(n) for n in common)))
786 786 dag = dagutil.revlogdag(repo.changelog)
787 787 all = dag.ancestorset(dag.internalizeall(common))
788 788 common = dag.externalizeall(dag.headsetofconnecteds(all))
789 789 else:
790 790 nodes = None
791 791 if pushedrevs:
792 792 revs = scmutil.revrange(repo, pushedrevs)
793 793 nodes = [repo[r].node() for r in revs]
794 794 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
795 795 ancestorsof=nodes)
796 796 common = set(common)
797 797 rheads = set(hds)
798 798 lheads = set(repo.heads())
799 799 ui.write(("common heads: %s\n") %
800 800 " ".join(sorted(short(n) for n in common)))
801 801 if lheads <= common:
802 802 ui.write(("local is subset\n"))
803 803 elif rheads <= common:
804 804 ui.write(("remote is subset\n"))
805 805
806 806 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
807 807 localrevs = opts['rev']
808 808 doit(localrevs, remoterevs)
809 809
810 810 _chunksize = 4 << 10
811 811
812 812 @command('debugdownload',
813 813 [
814 814 ('o', 'output', '', _('path')),
815 815 ],
816 816 optionalrepo=True)
817 817 def debugdownload(ui, repo, url, output=None, **opts):
818 818 """download a resource using Mercurial logic and config
819 819 """
820 820 fh = urlmod.open(ui, url, output)
821 821
822 822 dest = ui
823 823 if output:
824 824 dest = open(output, "wb", _chunksize)
825 825 try:
826 826 data = fh.read(_chunksize)
827 827 while data:
828 828 dest.write(data)
829 829 data = fh.read(_chunksize)
830 830 finally:
831 831 if output:
832 832 dest.close()
833 833
834 834 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
835 835 def debugextensions(ui, **opts):
836 836 '''show information about active extensions'''
837 837 opts = pycompat.byteskwargs(opts)
838 838 exts = extensions.extensions(ui)
839 839 hgver = util.version()
840 840 fm = ui.formatter('debugextensions', opts)
841 841 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
842 842 isinternal = extensions.ismoduleinternal(extmod)
843 843 extsource = pycompat.fsencode(extmod.__file__)
844 844 if isinternal:
845 845 exttestedwith = [] # never expose magic string to users
846 846 else:
847 847 exttestedwith = getattr(extmod, 'testedwith', '').split()
848 848 extbuglink = getattr(extmod, 'buglink', None)
849 849
850 850 fm.startitem()
851 851
852 852 if ui.quiet or ui.verbose:
853 853 fm.write('name', '%s\n', extname)
854 854 else:
855 855 fm.write('name', '%s', extname)
856 856 if isinternal or hgver in exttestedwith:
857 857 fm.plain('\n')
858 858 elif not exttestedwith:
859 859 fm.plain(_(' (untested!)\n'))
860 860 else:
861 861 lasttestedversion = exttestedwith[-1]
862 862 fm.plain(' (%s!)\n' % lasttestedversion)
863 863
864 864 fm.condwrite(ui.verbose and extsource, 'source',
865 865 _(' location: %s\n'), extsource or "")
866 866
867 867 if ui.verbose:
868 868 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
869 869 fm.data(bundled=isinternal)
870 870
871 871 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
872 872 _(' tested with: %s\n'),
873 873 fm.formatlist(exttestedwith, name='ver'))
874 874
875 875 fm.condwrite(ui.verbose and extbuglink, 'buglink',
876 876 _(' bug reporting: %s\n'), extbuglink or "")
877 877
878 878 fm.end()
879 879
880 880 @command('debugfileset',
881 881 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
882 882 _('[-r REV] FILESPEC'))
883 883 def debugfileset(ui, repo, expr, **opts):
884 884 '''parse and apply a fileset specification'''
885 885 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
886 886 if ui.verbose:
887 887 tree = fileset.parse(expr)
888 888 ui.note(fileset.prettyformat(tree), "\n")
889 889
890 890 for f in ctx.getfileset(expr):
891 891 ui.write("%s\n" % f)
892 892
893 893 @command('debugformat',
894 894 [] + cmdutil.formatteropts,
895 895 _(''))
896 896 def debugformat(ui, repo, **opts):
897 897 """display format information about the current repository
898 898
899 899 Use --verbose to get extra information about current config value and
900 900 Mercurial default."""
901 901 opts = pycompat.byteskwargs(opts)
902 902 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
903 903 maxvariantlength = max(len('format-variant'), maxvariantlength)
904 904
905 905 def makeformatname(name):
906 906 return '%s:' + (' ' * (maxvariantlength - len(name)))
907 907
908 908 fm = ui.formatter('debugformat', opts)
909 909 if fm.isplain():
910 910 def formatvalue(value):
911 911 if util.safehasattr(value, 'startswith'):
912 912 return value
913 913 if value:
914 914 return 'yes'
915 915 else:
916 916 return 'no'
917 917 else:
918 918 formatvalue = pycompat.identity
919 919
920 920 fm.plain('format-variant')
921 921 fm.plain(' ' * (maxvariantlength - len('format-variant')))
922 922 fm.plain(' repo')
923 923 if ui.verbose:
924 924 fm.plain(' config default')
925 925 fm.plain('\n')
926 926 for fv in upgrade.allformatvariant:
927 927 fm.startitem()
928 928 repovalue = fv.fromrepo(repo)
929 929 configvalue = fv.fromconfig(repo)
930 930
931 931 if repovalue != configvalue:
932 932 namelabel = 'formatvariant.name.mismatchconfig'
933 933 repolabel = 'formatvariant.repo.mismatchconfig'
934 934 elif repovalue != fv.default:
935 935 namelabel = 'formatvariant.name.mismatchdefault'
936 936 repolabel = 'formatvariant.repo.mismatchdefault'
937 937 else:
938 938 namelabel = 'formatvariant.name.uptodate'
939 939 repolabel = 'formatvariant.repo.uptodate'
940 940
941 941 fm.write('name', makeformatname(fv.name), fv.name,
942 942 label=namelabel)
943 943 fm.write('repo', ' %3s', formatvalue(repovalue),
944 944 label=repolabel)
945 945 if fv.default != configvalue:
946 946 configlabel = 'formatvariant.config.special'
947 947 else:
948 948 configlabel = 'formatvariant.config.default'
949 949 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
950 950 label=configlabel)
951 951 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
952 952 label='formatvariant.default')
953 953 fm.plain('\n')
954 954 fm.end()
955 955
956 956 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
957 957 def debugfsinfo(ui, path="."):
958 958 """show information detected about current filesystem"""
959 959 ui.write(('path: %s\n') % path)
960 960 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
961 961 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
962 962 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
963 963 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
964 964 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
965 965 casesensitive = '(unknown)'
966 966 try:
967 967 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
968 968 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
969 969 except OSError:
970 970 pass
971 971 ui.write(('case-sensitive: %s\n') % casesensitive)
972 972
973 973 @command('debuggetbundle',
974 974 [('H', 'head', [], _('id of head node'), _('ID')),
975 975 ('C', 'common', [], _('id of common node'), _('ID')),
976 976 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
977 977 _('REPO FILE [-H|-C ID]...'),
978 978 norepo=True)
979 979 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
980 980 """retrieves a bundle from a repo
981 981
982 982 Every ID must be a full-length hex node id string. Saves the bundle to the
983 983 given file.
984 984 """
985 985 opts = pycompat.byteskwargs(opts)
986 986 repo = hg.peer(ui, opts, repopath)
987 987 if not repo.capable('getbundle'):
988 988 raise error.Abort("getbundle() not supported by target repository")
989 989 args = {}
990 990 if common:
991 991 args[r'common'] = [bin(s) for s in common]
992 992 if head:
993 993 args[r'heads'] = [bin(s) for s in head]
994 994 # TODO: get desired bundlecaps from command line.
995 995 args[r'bundlecaps'] = None
996 996 bundle = repo.getbundle('debug', **args)
997 997
998 998 bundletype = opts.get('type', 'bzip2').lower()
999 999 btypes = {'none': 'HG10UN',
1000 1000 'bzip2': 'HG10BZ',
1001 1001 'gzip': 'HG10GZ',
1002 1002 'bundle2': 'HG20'}
1003 1003 bundletype = btypes.get(bundletype)
1004 1004 if bundletype not in bundle2.bundletypes:
1005 1005 raise error.Abort(_('unknown bundle type specified with --type'))
1006 1006 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1007 1007
1008 1008 @command('debugignore', [], '[FILE]')
1009 1009 def debugignore(ui, repo, *files, **opts):
1010 1010 """display the combined ignore pattern and information about ignored files
1011 1011
1012 1012 With no argument display the combined ignore pattern.
1013 1013
1014 1014 Given space separated file names, shows if the given file is ignored and
1015 1015 if so, show the ignore rule (file and line number) that matched it.
1016 1016 """
1017 1017 ignore = repo.dirstate._ignore
1018 1018 if not files:
1019 1019 # Show all the patterns
1020 1020 ui.write("%s\n" % pycompat.byterepr(ignore))
1021 1021 else:
1022 1022 m = scmutil.match(repo[None], pats=files)
1023 1023 for f in m.files():
1024 1024 nf = util.normpath(f)
1025 1025 ignored = None
1026 1026 ignoredata = None
1027 1027 if nf != '.':
1028 1028 if ignore(nf):
1029 1029 ignored = nf
1030 1030 ignoredata = repo.dirstate._ignorefileandline(nf)
1031 1031 else:
1032 1032 for p in util.finddirs(nf):
1033 1033 if ignore(p):
1034 1034 ignored = p
1035 1035 ignoredata = repo.dirstate._ignorefileandline(p)
1036 1036 break
1037 1037 if ignored:
1038 1038 if ignored == nf:
1039 1039 ui.write(_("%s is ignored\n") % m.uipath(f))
1040 1040 else:
1041 1041 ui.write(_("%s is ignored because of "
1042 1042 "containing folder %s\n")
1043 1043 % (m.uipath(f), ignored))
1044 1044 ignorefile, lineno, line = ignoredata
1045 1045 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1046 1046 % (ignorefile, lineno, line))
1047 1047 else:
1048 1048 ui.write(_("%s is not ignored\n") % m.uipath(f))
1049 1049
1050 1050 @command('debugindex', cmdutil.debugrevlogopts +
1051 1051 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1052 1052 _('[-f FORMAT] -c|-m|FILE'),
1053 1053 optionalrepo=True)
1054 1054 def debugindex(ui, repo, file_=None, **opts):
1055 1055 """dump the contents of an index file"""
1056 1056 opts = pycompat.byteskwargs(opts)
1057 1057 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1058 1058 format = opts.get('format', 0)
1059 1059 if format not in (0, 1):
1060 1060 raise error.Abort(_("unknown format %d") % format)
1061 1061
1062 1062 if ui.debugflag:
1063 1063 shortfn = hex
1064 1064 else:
1065 1065 shortfn = short
1066 1066
1067 1067 # There might not be anything in r, so have a sane default
1068 1068 idlen = 12
1069 1069 for i in r:
1070 1070 idlen = len(shortfn(r.node(i)))
1071 1071 break
1072 1072
1073 1073 if format == 0:
1074 ui.write((" rev offset length linkrev"
1075 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
1074 if ui.verbose:
1075 ui.write((" rev offset length linkrev"
1076 " %s %s p2\n") % ("nodeid".ljust(idlen),
1077 "p1".ljust(idlen)))
1078 else:
1079 ui.write((" rev linkrev %s %s p2\n") % (
1080 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1076 1081 elif format == 1:
1077 ui.write((" rev flag offset length size link p1 p2"
1078 " %s\n") % "nodeid".rjust(idlen))
1082 if ui.verbose:
1083 ui.write((" rev flag offset length size link p1"
1084 " p2 %s\n") % "nodeid".rjust(idlen))
1085 else:
1086 ui.write((" rev flag size link p1 p2 %s\n") %
1087 "nodeid".rjust(idlen))
1079 1088
1080 1089 for i in r:
1081 1090 node = r.node(i)
1082 1091 if format == 0:
1083 1092 try:
1084 1093 pp = r.parents(node)
1085 1094 except Exception:
1086 1095 pp = [nullid, nullid]
1087 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1088 i, r.start(i), r.length(i), r.linkrev(i),
1089 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1096 if ui.verbose:
1097 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1098 i, r.start(i), r.length(i), r.linkrev(i),
1099 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1100 else:
1101 ui.write("% 6d % 7d %s %s %s\n" % (
1102 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1103 shortfn(pp[1])))
1090 1104 elif format == 1:
1091 1105 pr = r.parentrevs(i)
1092 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1093 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1094 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1106 if ui.verbose:
1107 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1108 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1109 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1110 else:
1111 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1112 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1113 shortfn(node)))
1095 1114
1096 1115 @command('debugindexdot', cmdutil.debugrevlogopts,
1097 1116 _('-c|-m|FILE'), optionalrepo=True)
1098 1117 def debugindexdot(ui, repo, file_=None, **opts):
1099 1118 """dump an index DAG as a graphviz dot file"""
1100 1119 opts = pycompat.byteskwargs(opts)
1101 1120 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1102 1121 ui.write(("digraph G {\n"))
1103 1122 for i in r:
1104 1123 node = r.node(i)
1105 1124 pp = r.parents(node)
1106 1125 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1107 1126 if pp[1] != nullid:
1108 1127 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1109 1128 ui.write("}\n")
1110 1129
1111 1130 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1112 1131 def debuginstall(ui, **opts):
1113 1132 '''test Mercurial installation
1114 1133
1115 1134 Returns 0 on success.
1116 1135 '''
1117 1136 opts = pycompat.byteskwargs(opts)
1118 1137
1119 1138 def writetemp(contents):
1120 1139 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1121 1140 f = os.fdopen(fd, r"wb")
1122 1141 f.write(contents)
1123 1142 f.close()
1124 1143 return name
1125 1144
1126 1145 problems = 0
1127 1146
1128 1147 fm = ui.formatter('debuginstall', opts)
1129 1148 fm.startitem()
1130 1149
1131 1150 # encoding
1132 1151 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1133 1152 err = None
1134 1153 try:
1135 1154 codecs.lookup(pycompat.sysstr(encoding.encoding))
1136 1155 except LookupError as inst:
1137 1156 err = stringutil.forcebytestr(inst)
1138 1157 problems += 1
1139 1158 fm.condwrite(err, 'encodingerror', _(" %s\n"
1140 1159 " (check that your locale is properly set)\n"), err)
1141 1160
1142 1161 # Python
1143 1162 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1144 1163 pycompat.sysexecutable)
1145 1164 fm.write('pythonver', _("checking Python version (%s)\n"),
1146 1165 ("%d.%d.%d" % sys.version_info[:3]))
1147 1166 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1148 1167 os.path.dirname(pycompat.fsencode(os.__file__)))
1149 1168
1150 1169 security = set(sslutil.supportedprotocols)
1151 1170 if sslutil.hassni:
1152 1171 security.add('sni')
1153 1172
1154 1173 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1155 1174 fm.formatlist(sorted(security), name='protocol',
1156 1175 fmt='%s', sep=','))
1157 1176
1158 1177 # These are warnings, not errors. So don't increment problem count. This
1159 1178 # may change in the future.
1160 1179 if 'tls1.2' not in security:
1161 1180 fm.plain(_(' TLS 1.2 not supported by Python install; '
1162 1181 'network connections lack modern security\n'))
1163 1182 if 'sni' not in security:
1164 1183 fm.plain(_(' SNI not supported by Python install; may have '
1165 1184 'connectivity issues with some servers\n'))
1166 1185
1167 1186 # TODO print CA cert info
1168 1187
1169 1188 # hg version
1170 1189 hgver = util.version()
1171 1190 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1172 1191 hgver.split('+')[0])
1173 1192 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1174 1193 '+'.join(hgver.split('+')[1:]))
1175 1194
1176 1195 # compiled modules
1177 1196 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1178 1197 policy.policy)
1179 1198 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1180 1199 os.path.dirname(pycompat.fsencode(__file__)))
1181 1200
1182 1201 if policy.policy in ('c', 'allow'):
1183 1202 err = None
1184 1203 try:
1185 1204 from .cext import (
1186 1205 base85,
1187 1206 bdiff,
1188 1207 mpatch,
1189 1208 osutil,
1190 1209 )
1191 1210 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1192 1211 except Exception as inst:
1193 1212 err = stringutil.forcebytestr(inst)
1194 1213 problems += 1
1195 1214 fm.condwrite(err, 'extensionserror', " %s\n", err)
1196 1215
1197 1216 compengines = util.compengines._engines.values()
1198 1217 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1199 1218 fm.formatlist(sorted(e.name() for e in compengines),
1200 1219 name='compengine', fmt='%s', sep=', '))
1201 1220 fm.write('compenginesavail', _('checking available compression engines '
1202 1221 '(%s)\n'),
1203 1222 fm.formatlist(sorted(e.name() for e in compengines
1204 1223 if e.available()),
1205 1224 name='compengine', fmt='%s', sep=', '))
1206 1225 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1207 1226 fm.write('compenginesserver', _('checking available compression engines '
1208 1227 'for wire protocol (%s)\n'),
1209 1228 fm.formatlist([e.name() for e in wirecompengines
1210 1229 if e.wireprotosupport()],
1211 1230 name='compengine', fmt='%s', sep=', '))
1212 1231 re2 = 'missing'
1213 1232 if util._re2:
1214 1233 re2 = 'available'
1215 1234 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1216 1235 fm.data(re2=bool(util._re2))
1217 1236
1218 1237 # templates
1219 1238 p = templater.templatepaths()
1220 1239 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1221 1240 fm.condwrite(not p, '', _(" no template directories found\n"))
1222 1241 if p:
1223 1242 m = templater.templatepath("map-cmdline.default")
1224 1243 if m:
1225 1244 # template found, check if it is working
1226 1245 err = None
1227 1246 try:
1228 1247 templater.templater.frommapfile(m)
1229 1248 except Exception as inst:
1230 1249 err = stringutil.forcebytestr(inst)
1231 1250 p = None
1232 1251 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1233 1252 else:
1234 1253 p = None
1235 1254 fm.condwrite(p, 'defaulttemplate',
1236 1255 _("checking default template (%s)\n"), m)
1237 1256 fm.condwrite(not m, 'defaulttemplatenotfound',
1238 1257 _(" template '%s' not found\n"), "default")
1239 1258 if not p:
1240 1259 problems += 1
1241 1260 fm.condwrite(not p, '',
1242 1261 _(" (templates seem to have been installed incorrectly)\n"))
1243 1262
1244 1263 # editor
1245 1264 editor = ui.geteditor()
1246 1265 editor = util.expandpath(editor)
1247 1266 editorbin = procutil.shellsplit(editor)[0]
1248 1267 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1249 1268 cmdpath = procutil.findexe(editorbin)
1250 1269 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1251 1270 _(" No commit editor set and can't find %s in PATH\n"
1252 1271 " (specify a commit editor in your configuration"
1253 1272 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1254 1273 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1255 1274 _(" Can't find editor '%s' in PATH\n"
1256 1275 " (specify a commit editor in your configuration"
1257 1276 " file)\n"), not cmdpath and editorbin)
1258 1277 if not cmdpath and editor != 'vi':
1259 1278 problems += 1
1260 1279
1261 1280 # check username
1262 1281 username = None
1263 1282 err = None
1264 1283 try:
1265 1284 username = ui.username()
1266 1285 except error.Abort as e:
1267 1286 err = stringutil.forcebytestr(e)
1268 1287 problems += 1
1269 1288
1270 1289 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1271 1290 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1272 1291 " (specify a username in your configuration file)\n"), err)
1273 1292
1274 1293 fm.condwrite(not problems, '',
1275 1294 _("no problems detected\n"))
1276 1295 if not problems:
1277 1296 fm.data(problems=problems)
1278 1297 fm.condwrite(problems, 'problems',
1279 1298 _("%d problems detected,"
1280 1299 " please check your install!\n"), problems)
1281 1300 fm.end()
1282 1301
1283 1302 return problems
1284 1303
1285 1304 @command('debugknown', [], _('REPO ID...'), norepo=True)
1286 1305 def debugknown(ui, repopath, *ids, **opts):
1287 1306 """test whether node ids are known to a repo
1288 1307
1289 1308 Every ID must be a full-length hex node id string. Returns a list of 0s
1290 1309 and 1s indicating unknown/known.
1291 1310 """
1292 1311 opts = pycompat.byteskwargs(opts)
1293 1312 repo = hg.peer(ui, opts, repopath)
1294 1313 if not repo.capable('known'):
1295 1314 raise error.Abort("known() not supported by target repository")
1296 1315 flags = repo.known([bin(s) for s in ids])
1297 1316 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1298 1317
1299 1318 @command('debuglabelcomplete', [], _('LABEL...'))
1300 1319 def debuglabelcomplete(ui, repo, *args):
1301 1320 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1302 1321 debugnamecomplete(ui, repo, *args)
1303 1322
1304 1323 @command('debuglocks',
1305 1324 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1306 1325 ('W', 'force-wlock', None,
1307 1326 _('free the working state lock (DANGEROUS)')),
1308 1327 ('s', 'set-lock', None, _('set the store lock until stopped')),
1309 1328 ('S', 'set-wlock', None,
1310 1329 _('set the working state lock until stopped'))],
1311 1330 _('[OPTION]...'))
1312 1331 def debuglocks(ui, repo, **opts):
1313 1332 """show or modify state of locks
1314 1333
1315 1334 By default, this command will show which locks are held. This
1316 1335 includes the user and process holding the lock, the amount of time
1317 1336 the lock has been held, and the machine name where the process is
1318 1337 running if it's not local.
1319 1338
1320 1339 Locks protect the integrity of Mercurial's data, so should be
1321 1340 treated with care. System crashes or other interruptions may cause
1322 1341 locks to not be properly released, though Mercurial will usually
1323 1342 detect and remove such stale locks automatically.
1324 1343
1325 1344 However, detecting stale locks may not always be possible (for
1326 1345 instance, on a shared filesystem). Removing locks may also be
1327 1346 blocked by filesystem permissions.
1328 1347
1329 1348 Setting a lock will prevent other commands from changing the data.
1330 1349 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1331 1350 The set locks are removed when the command exits.
1332 1351
1333 1352 Returns 0 if no locks are held.
1334 1353
1335 1354 """
1336 1355
1337 1356 if opts.get(r'force_lock'):
1338 1357 repo.svfs.unlink('lock')
1339 1358 if opts.get(r'force_wlock'):
1340 1359 repo.vfs.unlink('wlock')
1341 1360 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1342 1361 return 0
1343 1362
1344 1363 locks = []
1345 1364 try:
1346 1365 if opts.get(r'set_wlock'):
1347 1366 try:
1348 1367 locks.append(repo.wlock(False))
1349 1368 except error.LockHeld:
1350 1369 raise error.Abort(_('wlock is already held'))
1351 1370 if opts.get(r'set_lock'):
1352 1371 try:
1353 1372 locks.append(repo.lock(False))
1354 1373 except error.LockHeld:
1355 1374 raise error.Abort(_('lock is already held'))
1356 1375 if len(locks):
1357 1376 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1358 1377 return 0
1359 1378 finally:
1360 1379 release(*locks)
1361 1380
1362 1381 now = time.time()
1363 1382 held = 0
1364 1383
1365 1384 def report(vfs, name, method):
1366 1385 # this causes stale locks to get reaped for more accurate reporting
1367 1386 try:
1368 1387 l = method(False)
1369 1388 except error.LockHeld:
1370 1389 l = None
1371 1390
1372 1391 if l:
1373 1392 l.release()
1374 1393 else:
1375 1394 try:
1376 1395 st = vfs.lstat(name)
1377 1396 age = now - st[stat.ST_MTIME]
1378 1397 user = util.username(st.st_uid)
1379 1398 locker = vfs.readlock(name)
1380 1399 if ":" in locker:
1381 1400 host, pid = locker.split(':')
1382 1401 if host == socket.gethostname():
1383 1402 locker = 'user %s, process %s' % (user, pid)
1384 1403 else:
1385 1404 locker = 'user %s, process %s, host %s' \
1386 1405 % (user, pid, host)
1387 1406 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1388 1407 return 1
1389 1408 except OSError as e:
1390 1409 if e.errno != errno.ENOENT:
1391 1410 raise
1392 1411
1393 1412 ui.write(("%-6s free\n") % (name + ":"))
1394 1413 return 0
1395 1414
1396 1415 held += report(repo.svfs, "lock", repo.lock)
1397 1416 held += report(repo.vfs, "wlock", repo.wlock)
1398 1417
1399 1418 return held
1400 1419
1401 1420 @command('debugmergestate', [], '')
1402 1421 def debugmergestate(ui, repo, *args):
1403 1422 """print merge state
1404 1423
1405 1424 Use --verbose to print out information about whether v1 or v2 merge state
1406 1425 was chosen."""
1407 1426 def _hashornull(h):
1408 1427 if h == nullhex:
1409 1428 return 'null'
1410 1429 else:
1411 1430 return h
1412 1431
1413 1432 def printrecords(version):
1414 1433 ui.write(('* version %d records\n') % version)
1415 1434 if version == 1:
1416 1435 records = v1records
1417 1436 else:
1418 1437 records = v2records
1419 1438
1420 1439 for rtype, record in records:
1421 1440 # pretty print some record types
1422 1441 if rtype == 'L':
1423 1442 ui.write(('local: %s\n') % record)
1424 1443 elif rtype == 'O':
1425 1444 ui.write(('other: %s\n') % record)
1426 1445 elif rtype == 'm':
1427 1446 driver, mdstate = record.split('\0', 1)
1428 1447 ui.write(('merge driver: %s (state "%s")\n')
1429 1448 % (driver, mdstate))
1430 1449 elif rtype in 'FDC':
1431 1450 r = record.split('\0')
1432 1451 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1433 1452 if version == 1:
1434 1453 onode = 'not stored in v1 format'
1435 1454 flags = r[7]
1436 1455 else:
1437 1456 onode, flags = r[7:9]
1438 1457 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1439 1458 % (f, rtype, state, _hashornull(hash)))
1440 1459 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1441 1460 ui.write((' ancestor path: %s (node %s)\n')
1442 1461 % (afile, _hashornull(anode)))
1443 1462 ui.write((' other path: %s (node %s)\n')
1444 1463 % (ofile, _hashornull(onode)))
1445 1464 elif rtype == 'f':
1446 1465 filename, rawextras = record.split('\0', 1)
1447 1466 extras = rawextras.split('\0')
1448 1467 i = 0
1449 1468 extrastrings = []
1450 1469 while i < len(extras):
1451 1470 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1452 1471 i += 2
1453 1472
1454 1473 ui.write(('file extras: %s (%s)\n')
1455 1474 % (filename, ', '.join(extrastrings)))
1456 1475 elif rtype == 'l':
1457 1476 labels = record.split('\0', 2)
1458 1477 labels = [l for l in labels if len(l) > 0]
1459 1478 ui.write(('labels:\n'))
1460 1479 ui.write((' local: %s\n' % labels[0]))
1461 1480 ui.write((' other: %s\n' % labels[1]))
1462 1481 if len(labels) > 2:
1463 1482 ui.write((' base: %s\n' % labels[2]))
1464 1483 else:
1465 1484 ui.write(('unrecognized entry: %s\t%s\n')
1466 1485 % (rtype, record.replace('\0', '\t')))
1467 1486
1468 1487 # Avoid mergestate.read() since it may raise an exception for unsupported
1469 1488 # merge state records. We shouldn't be doing this, but this is OK since this
1470 1489 # command is pretty low-level.
1471 1490 ms = mergemod.mergestate(repo)
1472 1491
1473 1492 # sort so that reasonable information is on top
1474 1493 v1records = ms._readrecordsv1()
1475 1494 v2records = ms._readrecordsv2()
1476 1495 order = 'LOml'
1477 1496 def key(r):
1478 1497 idx = order.find(r[0])
1479 1498 if idx == -1:
1480 1499 return (1, r[1])
1481 1500 else:
1482 1501 return (0, idx)
1483 1502 v1records.sort(key=key)
1484 1503 v2records.sort(key=key)
1485 1504
1486 1505 if not v1records and not v2records:
1487 1506 ui.write(('no merge state found\n'))
1488 1507 elif not v2records:
1489 1508 ui.note(('no version 2 merge state\n'))
1490 1509 printrecords(1)
1491 1510 elif ms._v1v2match(v1records, v2records):
1492 1511 ui.note(('v1 and v2 states match: using v2\n'))
1493 1512 printrecords(2)
1494 1513 else:
1495 1514 ui.note(('v1 and v2 states mismatch: using v1\n'))
1496 1515 printrecords(1)
1497 1516 if ui.verbose:
1498 1517 printrecords(2)
1499 1518
1500 1519 @command('debugnamecomplete', [], _('NAME...'))
1501 1520 def debugnamecomplete(ui, repo, *args):
1502 1521 '''complete "names" - tags, open branch names, bookmark names'''
1503 1522
1504 1523 names = set()
1505 1524 # since we previously only listed open branches, we will handle that
1506 1525 # specially (after this for loop)
1507 1526 for name, ns in repo.names.iteritems():
1508 1527 if name != 'branches':
1509 1528 names.update(ns.listnames(repo))
1510 1529 names.update(tag for (tag, heads, tip, closed)
1511 1530 in repo.branchmap().iterbranches() if not closed)
1512 1531 completions = set()
1513 1532 if not args:
1514 1533 args = ['']
1515 1534 for a in args:
1516 1535 completions.update(n for n in names if n.startswith(a))
1517 1536 ui.write('\n'.join(sorted(completions)))
1518 1537 ui.write('\n')
1519 1538
1520 1539 @command('debugobsolete',
1521 1540 [('', 'flags', 0, _('markers flag')),
1522 1541 ('', 'record-parents', False,
1523 1542 _('record parent information for the precursor')),
1524 1543 ('r', 'rev', [], _('display markers relevant to REV')),
1525 1544 ('', 'exclusive', False, _('restrict display to markers only '
1526 1545 'relevant to REV')),
1527 1546 ('', 'index', False, _('display index of the marker')),
1528 1547 ('', 'delete', [], _('delete markers specified by indices')),
1529 1548 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1530 1549 _('[OBSOLETED [REPLACEMENT ...]]'))
1531 1550 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1532 1551 """create arbitrary obsolete marker
1533 1552
1534 1553 With no arguments, displays the list of obsolescence markers."""
1535 1554
1536 1555 opts = pycompat.byteskwargs(opts)
1537 1556
1538 1557 def parsenodeid(s):
1539 1558 try:
1540 1559 # We do not use revsingle/revrange functions here to accept
1541 1560 # arbitrary node identifiers, possibly not present in the
1542 1561 # local repository.
1543 1562 n = bin(s)
1544 1563 if len(n) != len(nullid):
1545 1564 raise TypeError()
1546 1565 return n
1547 1566 except TypeError:
1548 1567 raise error.Abort('changeset references must be full hexadecimal '
1549 1568 'node identifiers')
1550 1569
1551 1570 if opts.get('delete'):
1552 1571 indices = []
1553 1572 for v in opts.get('delete'):
1554 1573 try:
1555 1574 indices.append(int(v))
1556 1575 except ValueError:
1557 1576 raise error.Abort(_('invalid index value: %r') % v,
1558 1577 hint=_('use integers for indices'))
1559 1578
1560 1579 if repo.currenttransaction():
1561 1580 raise error.Abort(_('cannot delete obsmarkers in the middle '
1562 1581 'of transaction.'))
1563 1582
1564 1583 with repo.lock():
1565 1584 n = repair.deleteobsmarkers(repo.obsstore, indices)
1566 1585 ui.write(_('deleted %i obsolescence markers\n') % n)
1567 1586
1568 1587 return
1569 1588
1570 1589 if precursor is not None:
1571 1590 if opts['rev']:
1572 1591 raise error.Abort('cannot select revision when creating marker')
1573 1592 metadata = {}
1574 1593 metadata['user'] = opts['user'] or ui.username()
1575 1594 succs = tuple(parsenodeid(succ) for succ in successors)
1576 1595 l = repo.lock()
1577 1596 try:
1578 1597 tr = repo.transaction('debugobsolete')
1579 1598 try:
1580 1599 date = opts.get('date')
1581 1600 if date:
1582 1601 date = dateutil.parsedate(date)
1583 1602 else:
1584 1603 date = None
1585 1604 prec = parsenodeid(precursor)
1586 1605 parents = None
1587 1606 if opts['record_parents']:
1588 1607 if prec not in repo.unfiltered():
1589 1608 raise error.Abort('cannot used --record-parents on '
1590 1609 'unknown changesets')
1591 1610 parents = repo.unfiltered()[prec].parents()
1592 1611 parents = tuple(p.node() for p in parents)
1593 1612 repo.obsstore.create(tr, prec, succs, opts['flags'],
1594 1613 parents=parents, date=date,
1595 1614 metadata=metadata, ui=ui)
1596 1615 tr.close()
1597 1616 except ValueError as exc:
1598 1617 raise error.Abort(_('bad obsmarker input: %s') %
1599 1618 pycompat.bytestr(exc))
1600 1619 finally:
1601 1620 tr.release()
1602 1621 finally:
1603 1622 l.release()
1604 1623 else:
1605 1624 if opts['rev']:
1606 1625 revs = scmutil.revrange(repo, opts['rev'])
1607 1626 nodes = [repo[r].node() for r in revs]
1608 1627 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1609 1628 exclusive=opts['exclusive']))
1610 1629 markers.sort(key=lambda x: x._data)
1611 1630 else:
1612 1631 markers = obsutil.getmarkers(repo)
1613 1632
1614 1633 markerstoiter = markers
1615 1634 isrelevant = lambda m: True
1616 1635 if opts.get('rev') and opts.get('index'):
1617 1636 markerstoiter = obsutil.getmarkers(repo)
1618 1637 markerset = set(markers)
1619 1638 isrelevant = lambda m: m in markerset
1620 1639
1621 1640 fm = ui.formatter('debugobsolete', opts)
1622 1641 for i, m in enumerate(markerstoiter):
1623 1642 if not isrelevant(m):
1624 1643 # marker can be irrelevant when we're iterating over a set
1625 1644 # of markers (markerstoiter) which is bigger than the set
1626 1645 # of markers we want to display (markers)
1627 1646 # this can happen if both --index and --rev options are
1628 1647 # provided and thus we need to iterate over all of the markers
1629 1648 # to get the correct indices, but only display the ones that
1630 1649 # are relevant to --rev value
1631 1650 continue
1632 1651 fm.startitem()
1633 1652 ind = i if opts.get('index') else None
1634 1653 cmdutil.showmarker(fm, m, index=ind)
1635 1654 fm.end()
1636 1655
1637 1656 @command('debugpathcomplete',
1638 1657 [('f', 'full', None, _('complete an entire path')),
1639 1658 ('n', 'normal', None, _('show only normal files')),
1640 1659 ('a', 'added', None, _('show only added files')),
1641 1660 ('r', 'removed', None, _('show only removed files'))],
1642 1661 _('FILESPEC...'))
1643 1662 def debugpathcomplete(ui, repo, *specs, **opts):
1644 1663 '''complete part or all of a tracked path
1645 1664
1646 1665 This command supports shells that offer path name completion. It
1647 1666 currently completes only files already known to the dirstate.
1648 1667
1649 1668 Completion extends only to the next path segment unless
1650 1669 --full is specified, in which case entire paths are used.'''
1651 1670
1652 1671 def complete(path, acceptable):
1653 1672 dirstate = repo.dirstate
1654 1673 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1655 1674 rootdir = repo.root + pycompat.ossep
1656 1675 if spec != repo.root and not spec.startswith(rootdir):
1657 1676 return [], []
1658 1677 if os.path.isdir(spec):
1659 1678 spec += '/'
1660 1679 spec = spec[len(rootdir):]
1661 1680 fixpaths = pycompat.ossep != '/'
1662 1681 if fixpaths:
1663 1682 spec = spec.replace(pycompat.ossep, '/')
1664 1683 speclen = len(spec)
1665 1684 fullpaths = opts[r'full']
1666 1685 files, dirs = set(), set()
1667 1686 adddir, addfile = dirs.add, files.add
1668 1687 for f, st in dirstate.iteritems():
1669 1688 if f.startswith(spec) and st[0] in acceptable:
1670 1689 if fixpaths:
1671 1690 f = f.replace('/', pycompat.ossep)
1672 1691 if fullpaths:
1673 1692 addfile(f)
1674 1693 continue
1675 1694 s = f.find(pycompat.ossep, speclen)
1676 1695 if s >= 0:
1677 1696 adddir(f[:s])
1678 1697 else:
1679 1698 addfile(f)
1680 1699 return files, dirs
1681 1700
1682 1701 acceptable = ''
1683 1702 if opts[r'normal']:
1684 1703 acceptable += 'nm'
1685 1704 if opts[r'added']:
1686 1705 acceptable += 'a'
1687 1706 if opts[r'removed']:
1688 1707 acceptable += 'r'
1689 1708 cwd = repo.getcwd()
1690 1709 if not specs:
1691 1710 specs = ['.']
1692 1711
1693 1712 files, dirs = set(), set()
1694 1713 for spec in specs:
1695 1714 f, d = complete(spec, acceptable or 'nmar')
1696 1715 files.update(f)
1697 1716 dirs.update(d)
1698 1717 files.update(dirs)
1699 1718 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1700 1719 ui.write('\n')
1701 1720
1702 1721 @command('debugpeer', [], _('PATH'), norepo=True)
1703 1722 def debugpeer(ui, path):
1704 1723 """establish a connection to a peer repository"""
1705 1724 # Always enable peer request logging. Requires --debug to display
1706 1725 # though.
1707 1726 overrides = {
1708 1727 ('devel', 'debug.peer-request'): True,
1709 1728 }
1710 1729
1711 1730 with ui.configoverride(overrides):
1712 1731 peer = hg.peer(ui, {}, path)
1713 1732
1714 1733 local = peer.local() is not None
1715 1734 canpush = peer.canpush()
1716 1735
1717 1736 ui.write(_('url: %s\n') % peer.url())
1718 1737 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1719 1738 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1720 1739
1721 1740 @command('debugpickmergetool',
1722 1741 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1723 1742 ('', 'changedelete', None, _('emulate merging change and delete')),
1724 1743 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1725 1744 _('[PATTERN]...'),
1726 1745 inferrepo=True)
1727 1746 def debugpickmergetool(ui, repo, *pats, **opts):
1728 1747 """examine which merge tool is chosen for specified file
1729 1748
1730 1749 As described in :hg:`help merge-tools`, Mercurial examines
1731 1750 configurations below in this order to decide which merge tool is
1732 1751 chosen for specified file.
1733 1752
1734 1753 1. ``--tool`` option
1735 1754 2. ``HGMERGE`` environment variable
1736 1755 3. configurations in ``merge-patterns`` section
1737 1756 4. configuration of ``ui.merge``
1738 1757 5. configurations in ``merge-tools`` section
1739 1758 6. ``hgmerge`` tool (for historical reason only)
1740 1759 7. default tool for fallback (``:merge`` or ``:prompt``)
1741 1760
1742 1761 This command writes out examination result in the style below::
1743 1762
1744 1763 FILE = MERGETOOL
1745 1764
1746 1765 By default, all files known in the first parent context of the
1747 1766 working directory are examined. Use file patterns and/or -I/-X
1748 1767 options to limit target files. -r/--rev is also useful to examine
1749 1768 files in another context without actual updating to it.
1750 1769
1751 1770 With --debug, this command shows warning messages while matching
1752 1771 against ``merge-patterns`` and so on, too. It is recommended to
1753 1772 use this option with explicit file patterns and/or -I/-X options,
1754 1773 because this option increases amount of output per file according
1755 1774 to configurations in hgrc.
1756 1775
1757 1776 With -v/--verbose, this command shows configurations below at
1758 1777 first (only if specified).
1759 1778
1760 1779 - ``--tool`` option
1761 1780 - ``HGMERGE`` environment variable
1762 1781 - configuration of ``ui.merge``
1763 1782
1764 1783 If merge tool is chosen before matching against
1765 1784 ``merge-patterns``, this command can't show any helpful
1766 1785 information, even with --debug. In such case, information above is
1767 1786 useful to know why a merge tool is chosen.
1768 1787 """
1769 1788 opts = pycompat.byteskwargs(opts)
1770 1789 overrides = {}
1771 1790 if opts['tool']:
1772 1791 overrides[('ui', 'forcemerge')] = opts['tool']
1773 1792 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1774 1793
1775 1794 with ui.configoverride(overrides, 'debugmergepatterns'):
1776 1795 hgmerge = encoding.environ.get("HGMERGE")
1777 1796 if hgmerge is not None:
1778 1797 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1779 1798 uimerge = ui.config("ui", "merge")
1780 1799 if uimerge:
1781 1800 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1782 1801
1783 1802 ctx = scmutil.revsingle(repo, opts.get('rev'))
1784 1803 m = scmutil.match(ctx, pats, opts)
1785 1804 changedelete = opts['changedelete']
1786 1805 for path in ctx.walk(m):
1787 1806 fctx = ctx[path]
1788 1807 try:
1789 1808 if not ui.debugflag:
1790 1809 ui.pushbuffer(error=True)
1791 1810 tool, toolpath = filemerge._picktool(repo, ui, path,
1792 1811 fctx.isbinary(),
1793 1812 'l' in fctx.flags(),
1794 1813 changedelete)
1795 1814 finally:
1796 1815 if not ui.debugflag:
1797 1816 ui.popbuffer()
1798 1817 ui.write(('%s = %s\n') % (path, tool))
1799 1818
1800 1819 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1801 1820 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1802 1821 '''access the pushkey key/value protocol
1803 1822
1804 1823 With two args, list the keys in the given namespace.
1805 1824
1806 1825 With five args, set a key to new if it currently is set to old.
1807 1826 Reports success or failure.
1808 1827 '''
1809 1828
1810 1829 target = hg.peer(ui, {}, repopath)
1811 1830 if keyinfo:
1812 1831 key, old, new = keyinfo
1813 1832 r = target.pushkey(namespace, key, old, new)
1814 1833 ui.status(pycompat.bytestr(r) + '\n')
1815 1834 return not r
1816 1835 else:
1817 1836 for k, v in sorted(target.listkeys(namespace).iteritems()):
1818 1837 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1819 1838 stringutil.escapestr(v)))
1820 1839
1821 1840 @command('debugpvec', [], _('A B'))
1822 1841 def debugpvec(ui, repo, a, b=None):
1823 1842 ca = scmutil.revsingle(repo, a)
1824 1843 cb = scmutil.revsingle(repo, b)
1825 1844 pa = pvec.ctxpvec(ca)
1826 1845 pb = pvec.ctxpvec(cb)
1827 1846 if pa == pb:
1828 1847 rel = "="
1829 1848 elif pa > pb:
1830 1849 rel = ">"
1831 1850 elif pa < pb:
1832 1851 rel = "<"
1833 1852 elif pa | pb:
1834 1853 rel = "|"
1835 1854 ui.write(_("a: %s\n") % pa)
1836 1855 ui.write(_("b: %s\n") % pb)
1837 1856 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1838 1857 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1839 1858 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1840 1859 pa.distance(pb), rel))
1841 1860
1842 1861 @command('debugrebuilddirstate|debugrebuildstate',
1843 1862 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1844 1863 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1845 1864 'the working copy parent')),
1846 1865 ],
1847 1866 _('[-r REV]'))
1848 1867 def debugrebuilddirstate(ui, repo, rev, **opts):
1849 1868 """rebuild the dirstate as it would look like for the given revision
1850 1869
1851 1870 If no revision is specified the first current parent will be used.
1852 1871
1853 1872 The dirstate will be set to the files of the given revision.
1854 1873 The actual working directory content or existing dirstate
1855 1874 information such as adds or removes is not considered.
1856 1875
1857 1876 ``minimal`` will only rebuild the dirstate status for files that claim to be
1858 1877 tracked but are not in the parent manifest, or that exist in the parent
1859 1878 manifest but are not in the dirstate. It will not change adds, removes, or
1860 1879 modified files that are in the working copy parent.
1861 1880
1862 1881 One use of this command is to make the next :hg:`status` invocation
1863 1882 check the actual file content.
1864 1883 """
1865 1884 ctx = scmutil.revsingle(repo, rev)
1866 1885 with repo.wlock():
1867 1886 dirstate = repo.dirstate
1868 1887 changedfiles = None
1869 1888 # See command doc for what minimal does.
1870 1889 if opts.get(r'minimal'):
1871 1890 manifestfiles = set(ctx.manifest().keys())
1872 1891 dirstatefiles = set(dirstate)
1873 1892 manifestonly = manifestfiles - dirstatefiles
1874 1893 dsonly = dirstatefiles - manifestfiles
1875 1894 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1876 1895 changedfiles = manifestonly | dsnotadded
1877 1896
1878 1897 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1879 1898
1880 1899 @command('debugrebuildfncache', [], '')
1881 1900 def debugrebuildfncache(ui, repo):
1882 1901 """rebuild the fncache file"""
1883 1902 repair.rebuildfncache(ui, repo)
1884 1903
1885 1904 @command('debugrename',
1886 1905 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1887 1906 _('[-r REV] FILE'))
1888 1907 def debugrename(ui, repo, file1, *pats, **opts):
1889 1908 """dump rename information"""
1890 1909
1891 1910 opts = pycompat.byteskwargs(opts)
1892 1911 ctx = scmutil.revsingle(repo, opts.get('rev'))
1893 1912 m = scmutil.match(ctx, (file1,) + pats, opts)
1894 1913 for abs in ctx.walk(m):
1895 1914 fctx = ctx[abs]
1896 1915 o = fctx.filelog().renamed(fctx.filenode())
1897 1916 rel = m.rel(abs)
1898 1917 if o:
1899 1918 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1900 1919 else:
1901 1920 ui.write(_("%s not renamed\n") % rel)
1902 1921
1903 1922 @command('debugrevlog', cmdutil.debugrevlogopts +
1904 1923 [('d', 'dump', False, _('dump index data'))],
1905 1924 _('-c|-m|FILE'),
1906 1925 optionalrepo=True)
1907 1926 def debugrevlog(ui, repo, file_=None, **opts):
1908 1927 """show data and statistics about a revlog"""
1909 1928 opts = pycompat.byteskwargs(opts)
1910 1929 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1911 1930
1912 1931 if opts.get("dump"):
1913 1932 numrevs = len(r)
1914 1933 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1915 1934 " rawsize totalsize compression heads chainlen\n"))
1916 1935 ts = 0
1917 1936 heads = set()
1918 1937
1919 1938 for rev in xrange(numrevs):
1920 1939 dbase = r.deltaparent(rev)
1921 1940 if dbase == -1:
1922 1941 dbase = rev
1923 1942 cbase = r.chainbase(rev)
1924 1943 clen = r.chainlen(rev)
1925 1944 p1, p2 = r.parentrevs(rev)
1926 1945 rs = r.rawsize(rev)
1927 1946 ts = ts + rs
1928 1947 heads -= set(r.parentrevs(rev))
1929 1948 heads.add(rev)
1930 1949 try:
1931 1950 compression = ts / r.end(rev)
1932 1951 except ZeroDivisionError:
1933 1952 compression = 0
1934 1953 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1935 1954 "%11d %5d %8d\n" %
1936 1955 (rev, p1, p2, r.start(rev), r.end(rev),
1937 1956 r.start(dbase), r.start(cbase),
1938 1957 r.start(p1), r.start(p2),
1939 1958 rs, ts, compression, len(heads), clen))
1940 1959 return 0
1941 1960
1942 1961 v = r.version
1943 1962 format = v & 0xFFFF
1944 1963 flags = []
1945 1964 gdelta = False
1946 1965 if v & revlog.FLAG_INLINE_DATA:
1947 1966 flags.append('inline')
1948 1967 if v & revlog.FLAG_GENERALDELTA:
1949 1968 gdelta = True
1950 1969 flags.append('generaldelta')
1951 1970 if not flags:
1952 1971 flags = ['(none)']
1953 1972
1954 1973 nummerges = 0
1955 1974 numfull = 0
1956 1975 numprev = 0
1957 1976 nump1 = 0
1958 1977 nump2 = 0
1959 1978 numother = 0
1960 1979 nump1prev = 0
1961 1980 nump2prev = 0
1962 1981 chainlengths = []
1963 1982 chainbases = []
1964 1983 chainspans = []
1965 1984
1966 1985 datasize = [None, 0, 0]
1967 1986 fullsize = [None, 0, 0]
1968 1987 deltasize = [None, 0, 0]
1969 1988 chunktypecounts = {}
1970 1989 chunktypesizes = {}
1971 1990
1972 1991 def addsize(size, l):
1973 1992 if l[0] is None or size < l[0]:
1974 1993 l[0] = size
1975 1994 if size > l[1]:
1976 1995 l[1] = size
1977 1996 l[2] += size
1978 1997
1979 1998 numrevs = len(r)
1980 1999 for rev in xrange(numrevs):
1981 2000 p1, p2 = r.parentrevs(rev)
1982 2001 delta = r.deltaparent(rev)
1983 2002 if format > 0:
1984 2003 addsize(r.rawsize(rev), datasize)
1985 2004 if p2 != nullrev:
1986 2005 nummerges += 1
1987 2006 size = r.length(rev)
1988 2007 if delta == nullrev:
1989 2008 chainlengths.append(0)
1990 2009 chainbases.append(r.start(rev))
1991 2010 chainspans.append(size)
1992 2011 numfull += 1
1993 2012 addsize(size, fullsize)
1994 2013 else:
1995 2014 chainlengths.append(chainlengths[delta] + 1)
1996 2015 baseaddr = chainbases[delta]
1997 2016 revaddr = r.start(rev)
1998 2017 chainbases.append(baseaddr)
1999 2018 chainspans.append((revaddr - baseaddr) + size)
2000 2019 addsize(size, deltasize)
2001 2020 if delta == rev - 1:
2002 2021 numprev += 1
2003 2022 if delta == p1:
2004 2023 nump1prev += 1
2005 2024 elif delta == p2:
2006 2025 nump2prev += 1
2007 2026 elif delta == p1:
2008 2027 nump1 += 1
2009 2028 elif delta == p2:
2010 2029 nump2 += 1
2011 2030 elif delta != nullrev:
2012 2031 numother += 1
2013 2032
2014 2033 # Obtain data on the raw chunks in the revlog.
2015 2034 segment = r._getsegmentforrevs(rev, rev)[1]
2016 2035 if segment:
2017 2036 chunktype = bytes(segment[0:1])
2018 2037 else:
2019 2038 chunktype = 'empty'
2020 2039
2021 2040 if chunktype not in chunktypecounts:
2022 2041 chunktypecounts[chunktype] = 0
2023 2042 chunktypesizes[chunktype] = 0
2024 2043
2025 2044 chunktypecounts[chunktype] += 1
2026 2045 chunktypesizes[chunktype] += size
2027 2046
2028 2047 # Adjust size min value for empty cases
2029 2048 for size in (datasize, fullsize, deltasize):
2030 2049 if size[0] is None:
2031 2050 size[0] = 0
2032 2051
2033 2052 numdeltas = numrevs - numfull
2034 2053 numoprev = numprev - nump1prev - nump2prev
2035 2054 totalrawsize = datasize[2]
2036 2055 datasize[2] /= numrevs
2037 2056 fulltotal = fullsize[2]
2038 2057 fullsize[2] /= numfull
2039 2058 deltatotal = deltasize[2]
2040 2059 if numrevs - numfull > 0:
2041 2060 deltasize[2] /= numrevs - numfull
2042 2061 totalsize = fulltotal + deltatotal
2043 2062 avgchainlen = sum(chainlengths) / numrevs
2044 2063 maxchainlen = max(chainlengths)
2045 2064 maxchainspan = max(chainspans)
2046 2065 compratio = 1
2047 2066 if totalsize:
2048 2067 compratio = totalrawsize / totalsize
2049 2068
2050 2069 basedfmtstr = '%%%dd\n'
2051 2070 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2052 2071
2053 2072 def dfmtstr(max):
2054 2073 return basedfmtstr % len(str(max))
2055 2074 def pcfmtstr(max, padding=0):
2056 2075 return basepcfmtstr % (len(str(max)), ' ' * padding)
2057 2076
2058 2077 def pcfmt(value, total):
2059 2078 if total:
2060 2079 return (value, 100 * float(value) / total)
2061 2080 else:
2062 2081 return value, 100.0
2063 2082
2064 2083 ui.write(('format : %d\n') % format)
2065 2084 ui.write(('flags : %s\n') % ', '.join(flags))
2066 2085
2067 2086 ui.write('\n')
2068 2087 fmt = pcfmtstr(totalsize)
2069 2088 fmt2 = dfmtstr(totalsize)
2070 2089 ui.write(('revisions : ') + fmt2 % numrevs)
2071 2090 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2072 2091 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2073 2092 ui.write(('revisions : ') + fmt2 % numrevs)
2074 2093 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2075 2094 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2076 2095 ui.write(('revision size : ') + fmt2 % totalsize)
2077 2096 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2078 2097 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2079 2098
2080 2099 def fmtchunktype(chunktype):
2081 2100 if chunktype == 'empty':
2082 2101 return ' %s : ' % chunktype
2083 2102 elif chunktype in pycompat.bytestr(string.ascii_letters):
2084 2103 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2085 2104 else:
2086 2105 return ' 0x%s : ' % hex(chunktype)
2087 2106
2088 2107 ui.write('\n')
2089 2108 ui.write(('chunks : ') + fmt2 % numrevs)
2090 2109 for chunktype in sorted(chunktypecounts):
2091 2110 ui.write(fmtchunktype(chunktype))
2092 2111 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2093 2112 ui.write(('chunks size : ') + fmt2 % totalsize)
2094 2113 for chunktype in sorted(chunktypecounts):
2095 2114 ui.write(fmtchunktype(chunktype))
2096 2115 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2097 2116
2098 2117 ui.write('\n')
2099 2118 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2100 2119 ui.write(('avg chain length : ') + fmt % avgchainlen)
2101 2120 ui.write(('max chain length : ') + fmt % maxchainlen)
2102 2121 ui.write(('max chain reach : ') + fmt % maxchainspan)
2103 2122 ui.write(('compression ratio : ') + fmt % compratio)
2104 2123
2105 2124 if format > 0:
2106 2125 ui.write('\n')
2107 2126 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2108 2127 % tuple(datasize))
2109 2128 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2110 2129 % tuple(fullsize))
2111 2130 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2112 2131 % tuple(deltasize))
2113 2132
2114 2133 if numdeltas > 0:
2115 2134 ui.write('\n')
2116 2135 fmt = pcfmtstr(numdeltas)
2117 2136 fmt2 = pcfmtstr(numdeltas, 4)
2118 2137 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2119 2138 if numprev > 0:
2120 2139 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2121 2140 numprev))
2122 2141 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2123 2142 numprev))
2124 2143 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2125 2144 numprev))
2126 2145 if gdelta:
2127 2146 ui.write(('deltas against p1 : ')
2128 2147 + fmt % pcfmt(nump1, numdeltas))
2129 2148 ui.write(('deltas against p2 : ')
2130 2149 + fmt % pcfmt(nump2, numdeltas))
2131 2150 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2132 2151 numdeltas))
2133 2152
2134 2153 @command('debugrevspec',
2135 2154 [('', 'optimize', None,
2136 2155 _('print parsed tree after optimizing (DEPRECATED)')),
2137 2156 ('', 'show-revs', True, _('print list of result revisions (default)')),
2138 2157 ('s', 'show-set', None, _('print internal representation of result set')),
2139 2158 ('p', 'show-stage', [],
2140 2159 _('print parsed tree at the given stage'), _('NAME')),
2141 2160 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2142 2161 ('', 'verify-optimized', False, _('verify optimized result')),
2143 2162 ],
2144 2163 ('REVSPEC'))
2145 2164 def debugrevspec(ui, repo, expr, **opts):
2146 2165 """parse and apply a revision specification
2147 2166
2148 2167 Use -p/--show-stage option to print the parsed tree at the given stages.
2149 2168 Use -p all to print tree at every stage.
2150 2169
2151 2170 Use --no-show-revs option with -s or -p to print only the set
2152 2171 representation or the parsed tree respectively.
2153 2172
2154 2173 Use --verify-optimized to compare the optimized result with the unoptimized
2155 2174 one. Returns 1 if the optimized result differs.
2156 2175 """
2157 2176 opts = pycompat.byteskwargs(opts)
2158 2177 aliases = ui.configitems('revsetalias')
2159 2178 stages = [
2160 2179 ('parsed', lambda tree: tree),
2161 2180 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2162 2181 ui.warn)),
2163 2182 ('concatenated', revsetlang.foldconcat),
2164 2183 ('analyzed', revsetlang.analyze),
2165 2184 ('optimized', revsetlang.optimize),
2166 2185 ]
2167 2186 if opts['no_optimized']:
2168 2187 stages = stages[:-1]
2169 2188 if opts['verify_optimized'] and opts['no_optimized']:
2170 2189 raise error.Abort(_('cannot use --verify-optimized with '
2171 2190 '--no-optimized'))
2172 2191 stagenames = set(n for n, f in stages)
2173 2192
2174 2193 showalways = set()
2175 2194 showchanged = set()
2176 2195 if ui.verbose and not opts['show_stage']:
2177 2196 # show parsed tree by --verbose (deprecated)
2178 2197 showalways.add('parsed')
2179 2198 showchanged.update(['expanded', 'concatenated'])
2180 2199 if opts['optimize']:
2181 2200 showalways.add('optimized')
2182 2201 if opts['show_stage'] and opts['optimize']:
2183 2202 raise error.Abort(_('cannot use --optimize with --show-stage'))
2184 2203 if opts['show_stage'] == ['all']:
2185 2204 showalways.update(stagenames)
2186 2205 else:
2187 2206 for n in opts['show_stage']:
2188 2207 if n not in stagenames:
2189 2208 raise error.Abort(_('invalid stage name: %s') % n)
2190 2209 showalways.update(opts['show_stage'])
2191 2210
2192 2211 treebystage = {}
2193 2212 printedtree = None
2194 2213 tree = revsetlang.parse(expr, lookup=repo.__contains__)
2195 2214 for n, f in stages:
2196 2215 treebystage[n] = tree = f(tree)
2197 2216 if n in showalways or (n in showchanged and tree != printedtree):
2198 2217 if opts['show_stage'] or n != 'parsed':
2199 2218 ui.write(("* %s:\n") % n)
2200 2219 ui.write(revsetlang.prettyformat(tree), "\n")
2201 2220 printedtree = tree
2202 2221
2203 2222 if opts['verify_optimized']:
2204 2223 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2205 2224 brevs = revset.makematcher(treebystage['optimized'])(repo)
2206 2225 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2207 2226 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2208 2227 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2209 2228 arevs = list(arevs)
2210 2229 brevs = list(brevs)
2211 2230 if arevs == brevs:
2212 2231 return 0
2213 2232 ui.write(('--- analyzed\n'), label='diff.file_a')
2214 2233 ui.write(('+++ optimized\n'), label='diff.file_b')
2215 2234 sm = difflib.SequenceMatcher(None, arevs, brevs)
2216 2235 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2217 2236 if tag in ('delete', 'replace'):
2218 2237 for c in arevs[alo:ahi]:
2219 2238 ui.write('-%s\n' % c, label='diff.deleted')
2220 2239 if tag in ('insert', 'replace'):
2221 2240 for c in brevs[blo:bhi]:
2222 2241 ui.write('+%s\n' % c, label='diff.inserted')
2223 2242 if tag == 'equal':
2224 2243 for c in arevs[alo:ahi]:
2225 2244 ui.write(' %s\n' % c)
2226 2245 return 1
2227 2246
2228 2247 func = revset.makematcher(tree)
2229 2248 revs = func(repo)
2230 2249 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2231 2250 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2232 2251 if not opts['show_revs']:
2233 2252 return
2234 2253 for c in revs:
2235 2254 ui.write("%d\n" % c)
2236 2255
2237 2256 @command('debugserve', [
2238 2257 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2239 2258 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2240 2259 ('', 'logiofile', '', _('file to log server I/O to')),
2241 2260 ], '')
2242 2261 def debugserve(ui, repo, **opts):
2243 2262 """run a server with advanced settings
2244 2263
2245 2264 This command is similar to :hg:`serve`. It exists partially as a
2246 2265 workaround to the fact that ``hg serve --stdio`` must have specific
2247 2266 arguments for security reasons.
2248 2267 """
2249 2268 opts = pycompat.byteskwargs(opts)
2250 2269
2251 2270 if not opts['sshstdio']:
2252 2271 raise error.Abort(_('only --sshstdio is currently supported'))
2253 2272
2254 2273 logfh = None
2255 2274
2256 2275 if opts['logiofd'] and opts['logiofile']:
2257 2276 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2258 2277
2259 2278 if opts['logiofd']:
2260 2279 # Line buffered because output is line based.
2261 2280 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2262 2281 elif opts['logiofile']:
2263 2282 logfh = open(opts['logiofile'], 'ab', 1)
2264 2283
2265 2284 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2266 2285 s.serve_forever()
2267 2286
2268 2287 @command('debugsetparents', [], _('REV1 [REV2]'))
2269 2288 def debugsetparents(ui, repo, rev1, rev2=None):
2270 2289 """manually set the parents of the current working directory
2271 2290
2272 2291 This is useful for writing repository conversion tools, but should
2273 2292 be used with care. For example, neither the working directory nor the
2274 2293 dirstate is updated, so file status may be incorrect after running this
2275 2294 command.
2276 2295
2277 2296 Returns 0 on success.
2278 2297 """
2279 2298
2280 2299 node1 = scmutil.revsingle(repo, rev1).node()
2281 2300 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2282 2301
2283 2302 with repo.wlock():
2284 2303 repo.setparents(node1, node2)
2285 2304
2286 2305 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2287 2306 def debugssl(ui, repo, source=None, **opts):
2288 2307 '''test a secure connection to a server
2289 2308
2290 2309 This builds the certificate chain for the server on Windows, installing the
2291 2310 missing intermediates and trusted root via Windows Update if necessary. It
2292 2311 does nothing on other platforms.
2293 2312
2294 2313 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2295 2314 that server is used. See :hg:`help urls` for more information.
2296 2315
2297 2316 If the update succeeds, retry the original operation. Otherwise, the cause
2298 2317 of the SSL error is likely another issue.
2299 2318 '''
2300 2319 if not pycompat.iswindows:
2301 2320 raise error.Abort(_('certificate chain building is only possible on '
2302 2321 'Windows'))
2303 2322
2304 2323 if not source:
2305 2324 if not repo:
2306 2325 raise error.Abort(_("there is no Mercurial repository here, and no "
2307 2326 "server specified"))
2308 2327 source = "default"
2309 2328
2310 2329 source, branches = hg.parseurl(ui.expandpath(source))
2311 2330 url = util.url(source)
2312 2331 addr = None
2313 2332
2314 2333 defaultport = {'https': 443, 'ssh': 22}
2315 2334 if url.scheme in defaultport:
2316 2335 try:
2317 2336 addr = (url.host, int(url.port or defaultport[url.scheme]))
2318 2337 except ValueError:
2319 2338 raise error.Abort(_("malformed port number in URL"))
2320 2339 else:
2321 2340 raise error.Abort(_("only https and ssh connections are supported"))
2322 2341
2323 2342 from . import win32
2324 2343
2325 2344 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2326 2345 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2327 2346
2328 2347 try:
2329 2348 s.connect(addr)
2330 2349 cert = s.getpeercert(True)
2331 2350
2332 2351 ui.status(_('checking the certificate chain for %s\n') % url.host)
2333 2352
2334 2353 complete = win32.checkcertificatechain(cert, build=False)
2335 2354
2336 2355 if not complete:
2337 2356 ui.status(_('certificate chain is incomplete, updating... '))
2338 2357
2339 2358 if not win32.checkcertificatechain(cert):
2340 2359 ui.status(_('failed.\n'))
2341 2360 else:
2342 2361 ui.status(_('done.\n'))
2343 2362 else:
2344 2363 ui.status(_('full certificate chain is available\n'))
2345 2364 finally:
2346 2365 s.close()
2347 2366
2348 2367 @command('debugsub',
2349 2368 [('r', 'rev', '',
2350 2369 _('revision to check'), _('REV'))],
2351 2370 _('[-r REV] [REV]'))
2352 2371 def debugsub(ui, repo, rev=None):
2353 2372 ctx = scmutil.revsingle(repo, rev, None)
2354 2373 for k, v in sorted(ctx.substate.items()):
2355 2374 ui.write(('path %s\n') % k)
2356 2375 ui.write((' source %s\n') % v[0])
2357 2376 ui.write((' revision %s\n') % v[1])
2358 2377
2359 2378 @command('debugsuccessorssets',
2360 2379 [('', 'closest', False, _('return closest successors sets only'))],
2361 2380 _('[REV]'))
2362 2381 def debugsuccessorssets(ui, repo, *revs, **opts):
2363 2382 """show set of successors for revision
2364 2383
2365 2384 A successors set of changeset A is a consistent group of revisions that
2366 2385 succeed A. It contains non-obsolete changesets only unless closests
2367 2386 successors set is set.
2368 2387
2369 2388 In most cases a changeset A has a single successors set containing a single
2370 2389 successor (changeset A replaced by A').
2371 2390
2372 2391 A changeset that is made obsolete with no successors are called "pruned".
2373 2392 Such changesets have no successors sets at all.
2374 2393
2375 2394 A changeset that has been "split" will have a successors set containing
2376 2395 more than one successor.
2377 2396
2378 2397 A changeset that has been rewritten in multiple different ways is called
2379 2398 "divergent". Such changesets have multiple successor sets (each of which
2380 2399 may also be split, i.e. have multiple successors).
2381 2400
2382 2401 Results are displayed as follows::
2383 2402
2384 2403 <rev1>
2385 2404 <successors-1A>
2386 2405 <rev2>
2387 2406 <successors-2A>
2388 2407 <successors-2B1> <successors-2B2> <successors-2B3>
2389 2408
2390 2409 Here rev2 has two possible (i.e. divergent) successors sets. The first
2391 2410 holds one element, whereas the second holds three (i.e. the changeset has
2392 2411 been split).
2393 2412 """
2394 2413 # passed to successorssets caching computation from one call to another
2395 2414 cache = {}
2396 2415 ctx2str = bytes
2397 2416 node2str = short
2398 2417 for rev in scmutil.revrange(repo, revs):
2399 2418 ctx = repo[rev]
2400 2419 ui.write('%s\n'% ctx2str(ctx))
2401 2420 for succsset in obsutil.successorssets(repo, ctx.node(),
2402 2421 closest=opts[r'closest'],
2403 2422 cache=cache):
2404 2423 if succsset:
2405 2424 ui.write(' ')
2406 2425 ui.write(node2str(succsset[0]))
2407 2426 for node in succsset[1:]:
2408 2427 ui.write(' ')
2409 2428 ui.write(node2str(node))
2410 2429 ui.write('\n')
2411 2430
2412 2431 @command('debugtemplate',
2413 2432 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2414 2433 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2415 2434 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2416 2435 optionalrepo=True)
2417 2436 def debugtemplate(ui, repo, tmpl, **opts):
2418 2437 """parse and apply a template
2419 2438
2420 2439 If -r/--rev is given, the template is processed as a log template and
2421 2440 applied to the given changesets. Otherwise, it is processed as a generic
2422 2441 template.
2423 2442
2424 2443 Use --verbose to print the parsed tree.
2425 2444 """
2426 2445 revs = None
2427 2446 if opts[r'rev']:
2428 2447 if repo is None:
2429 2448 raise error.RepoError(_('there is no Mercurial repository here '
2430 2449 '(.hg not found)'))
2431 2450 revs = scmutil.revrange(repo, opts[r'rev'])
2432 2451
2433 2452 props = {}
2434 2453 for d in opts[r'define']:
2435 2454 try:
2436 2455 k, v = (e.strip() for e in d.split('=', 1))
2437 2456 if not k or k == 'ui':
2438 2457 raise ValueError
2439 2458 props[k] = v
2440 2459 except ValueError:
2441 2460 raise error.Abort(_('malformed keyword definition: %s') % d)
2442 2461
2443 2462 if ui.verbose:
2444 2463 aliases = ui.configitems('templatealias')
2445 2464 tree = templater.parse(tmpl)
2446 2465 ui.note(templater.prettyformat(tree), '\n')
2447 2466 newtree = templater.expandaliases(tree, aliases)
2448 2467 if newtree != tree:
2449 2468 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2450 2469
2451 2470 if revs is None:
2452 2471 tres = formatter.templateresources(ui, repo)
2453 2472 t = formatter.maketemplater(ui, tmpl, resources=tres)
2454 2473 ui.write(t.renderdefault(props))
2455 2474 else:
2456 2475 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2457 2476 for r in revs:
2458 2477 displayer.show(repo[r], **pycompat.strkwargs(props))
2459 2478 displayer.close()
2460 2479
2461 2480 @command('debuguigetpass', [
2462 2481 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2463 2482 ], _('[-p TEXT]'), norepo=True)
2464 2483 def debuguigetpass(ui, prompt=''):
2465 2484 """show prompt to type password"""
2466 2485 r = ui.getpass(prompt)
2467 2486 ui.write(('respose: %s\n') % r)
2468 2487
2469 2488 @command('debuguiprompt', [
2470 2489 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2471 2490 ], _('[-p TEXT]'), norepo=True)
2472 2491 def debuguiprompt(ui, prompt=''):
2473 2492 """show plain prompt"""
2474 2493 r = ui.prompt(prompt)
2475 2494 ui.write(('response: %s\n') % r)
2476 2495
2477 2496 @command('debugupdatecaches', [])
2478 2497 def debugupdatecaches(ui, repo, *pats, **opts):
2479 2498 """warm all known caches in the repository"""
2480 2499 with repo.wlock(), repo.lock():
2481 2500 repo.updatecaches(full=True)
2482 2501
2483 2502 @command('debugupgraderepo', [
2484 2503 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2485 2504 ('', 'run', False, _('performs an upgrade')),
2486 2505 ])
2487 2506 def debugupgraderepo(ui, repo, run=False, optimize=None):
2488 2507 """upgrade a repository to use different features
2489 2508
2490 2509 If no arguments are specified, the repository is evaluated for upgrade
2491 2510 and a list of problems and potential optimizations is printed.
2492 2511
2493 2512 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2494 2513 can be influenced via additional arguments. More details will be provided
2495 2514 by the command output when run without ``--run``.
2496 2515
2497 2516 During the upgrade, the repository will be locked and no writes will be
2498 2517 allowed.
2499 2518
2500 2519 At the end of the upgrade, the repository may not be readable while new
2501 2520 repository data is swapped in. This window will be as long as it takes to
2502 2521 rename some directories inside the ``.hg`` directory. On most machines, this
2503 2522 should complete almost instantaneously and the chances of a consumer being
2504 2523 unable to access the repository should be low.
2505 2524 """
2506 2525 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2507 2526
2508 2527 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2509 2528 inferrepo=True)
2510 2529 def debugwalk(ui, repo, *pats, **opts):
2511 2530 """show how files match on given patterns"""
2512 2531 opts = pycompat.byteskwargs(opts)
2513 2532 m = scmutil.match(repo[None], pats, opts)
2514 2533 ui.write(('matcher: %r\n' % m))
2515 2534 items = list(repo[None].walk(m))
2516 2535 if not items:
2517 2536 return
2518 2537 f = lambda fn: fn
2519 2538 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2520 2539 f = lambda fn: util.normpath(fn)
2521 2540 fmt = 'f %%-%ds %%-%ds %%s' % (
2522 2541 max([len(abs) for abs in items]),
2523 2542 max([len(m.rel(abs)) for abs in items]))
2524 2543 for abs in items:
2525 2544 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2526 2545 ui.write("%s\n" % line.rstrip())
2527 2546
2528 2547 @command('debugwhyunstable', [], _('REV'))
2529 2548 def debugwhyunstable(ui, repo, rev):
2530 2549 """explain instabilities of a changeset"""
2531 2550 for entry in obsutil.whyunstable(repo, repo[rev]):
2532 2551 dnodes = ''
2533 2552 if entry.get('divergentnodes'):
2534 2553 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2535 2554 for ctx in entry['divergentnodes']) + ' '
2536 2555 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2537 2556 entry['reason'], entry['node']))
2538 2557
2539 2558 @command('debugwireargs',
2540 2559 [('', 'three', '', 'three'),
2541 2560 ('', 'four', '', 'four'),
2542 2561 ('', 'five', '', 'five'),
2543 2562 ] + cmdutil.remoteopts,
2544 2563 _('REPO [OPTIONS]... [ONE [TWO]]'),
2545 2564 norepo=True)
2546 2565 def debugwireargs(ui, repopath, *vals, **opts):
2547 2566 opts = pycompat.byteskwargs(opts)
2548 2567 repo = hg.peer(ui, opts, repopath)
2549 2568 for opt in cmdutil.remoteopts:
2550 2569 del opts[opt[1]]
2551 2570 args = {}
2552 2571 for k, v in opts.iteritems():
2553 2572 if v:
2554 2573 args[k] = v
2555 2574 args = pycompat.strkwargs(args)
2556 2575 # run twice to check that we don't mess up the stream for the next command
2557 2576 res1 = repo.debugwireargs(*vals, **args)
2558 2577 res2 = repo.debugwireargs(*vals, **args)
2559 2578 ui.write("%s\n" % res1)
2560 2579 if res1 != res2:
2561 2580 ui.warn("%s\n" % res2)
2562 2581
2563 2582 def _parsewirelangblocks(fh):
2564 2583 activeaction = None
2565 2584 blocklines = []
2566 2585
2567 2586 for line in fh:
2568 2587 line = line.rstrip()
2569 2588 if not line:
2570 2589 continue
2571 2590
2572 2591 if line.startswith(b'#'):
2573 2592 continue
2574 2593
2575 2594 if not line.startswith(' '):
2576 2595 # New block. Flush previous one.
2577 2596 if activeaction:
2578 2597 yield activeaction, blocklines
2579 2598
2580 2599 activeaction = line
2581 2600 blocklines = []
2582 2601 continue
2583 2602
2584 2603 # Else we start with an indent.
2585 2604
2586 2605 if not activeaction:
2587 2606 raise error.Abort(_('indented line outside of block'))
2588 2607
2589 2608 blocklines.append(line)
2590 2609
2591 2610 # Flush last block.
2592 2611 if activeaction:
2593 2612 yield activeaction, blocklines
2594 2613
2595 2614 @command('debugwireproto',
2596 2615 [
2597 2616 ('', 'localssh', False, _('start an SSH server for this repo')),
2598 2617 ('', 'peer', '', _('construct a specific version of the peer')),
2599 2618 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2600 2619 ] + cmdutil.remoteopts,
2601 2620 _('[PATH]'),
2602 2621 optionalrepo=True)
2603 2622 def debugwireproto(ui, repo, path=None, **opts):
2604 2623 """send wire protocol commands to a server
2605 2624
2606 2625 This command can be used to issue wire protocol commands to remote
2607 2626 peers and to debug the raw data being exchanged.
2608 2627
2609 2628 ``--localssh`` will start an SSH server against the current repository
2610 2629 and connect to that. By default, the connection will perform a handshake
2611 2630 and establish an appropriate peer instance.
2612 2631
2613 2632 ``--peer`` can be used to bypass the handshake protocol and construct a
2614 2633 peer instance using the specified class type. Valid values are ``raw``,
2615 2634 ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending raw data
2616 2635 payloads and don't support higher-level command actions.
2617 2636
2618 2637 ``--noreadstderr`` can be used to disable automatic reading from stderr
2619 2638 of the peer (for SSH connections only). Disabling automatic reading of
2620 2639 stderr is useful for making output more deterministic.
2621 2640
2622 2641 Commands are issued via a mini language which is specified via stdin.
2623 2642 The language consists of individual actions to perform. An action is
2624 2643 defined by a block. A block is defined as a line with no leading
2625 2644 space followed by 0 or more lines with leading space. Blocks are
2626 2645 effectively a high-level command with additional metadata.
2627 2646
2628 2647 Lines beginning with ``#`` are ignored.
2629 2648
2630 2649 The following sections denote available actions.
2631 2650
2632 2651 raw
2633 2652 ---
2634 2653
2635 2654 Send raw data to the server.
2636 2655
2637 2656 The block payload contains the raw data to send as one atomic send
2638 2657 operation. The data may not actually be delivered in a single system
2639 2658 call: it depends on the abilities of the transport being used.
2640 2659
2641 2660 Each line in the block is de-indented and concatenated. Then, that
2642 2661 value is evaluated as a Python b'' literal. This allows the use of
2643 2662 backslash escaping, etc.
2644 2663
2645 2664 raw+
2646 2665 ----
2647 2666
2648 2667 Behaves like ``raw`` except flushes output afterwards.
2649 2668
2650 2669 command <X>
2651 2670 -----------
2652 2671
2653 2672 Send a request to run a named command, whose name follows the ``command``
2654 2673 string.
2655 2674
2656 2675 Arguments to the command are defined as lines in this block. The format of
2657 2676 each line is ``<key> <value>``. e.g.::
2658 2677
2659 2678 command listkeys
2660 2679 namespace bookmarks
2661 2680
2662 2681 Values are interpreted as Python b'' literals. This allows encoding
2663 2682 special byte sequences via backslash escaping.
2664 2683
2665 2684 The following arguments have special meaning:
2666 2685
2667 2686 ``PUSHFILE``
2668 2687 When defined, the *push* mechanism of the peer will be used instead
2669 2688 of the static request-response mechanism and the content of the
2670 2689 file specified in the value of this argument will be sent as the
2671 2690 command payload.
2672 2691
2673 2692 This can be used to submit a local bundle file to the remote.
2674 2693
2675 2694 batchbegin
2676 2695 ----------
2677 2696
2678 2697 Instruct the peer to begin a batched send.
2679 2698
2680 2699 All ``command`` blocks are queued for execution until the next
2681 2700 ``batchsubmit`` block.
2682 2701
2683 2702 batchsubmit
2684 2703 -----------
2685 2704
2686 2705 Submit previously queued ``command`` blocks as a batch request.
2687 2706
2688 2707 This action MUST be paired with a ``batchbegin`` action.
2689 2708
2690 2709 httprequest <method> <path>
2691 2710 ---------------------------
2692 2711
2693 2712 (HTTP peer only)
2694 2713
2695 2714 Send an HTTP request to the peer.
2696 2715
2697 2716 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2698 2717
2699 2718 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2700 2719 headers to add to the request. e.g. ``Accept: foo``.
2701 2720
2702 2721 The following arguments are special:
2703 2722
2704 2723 ``BODYFILE``
2705 2724 The content of the file defined as the value to this argument will be
2706 2725 transferred verbatim as the HTTP request body.
2707 2726
2708 2727 ``frame <type> <flags> <payload>``
2709 2728 Send a unified protocol frame as part of the request body.
2710 2729
2711 2730 All frames will be collected and sent as the body to the HTTP
2712 2731 request.
2713 2732
2714 2733 close
2715 2734 -----
2716 2735
2717 2736 Close the connection to the server.
2718 2737
2719 2738 flush
2720 2739 -----
2721 2740
2722 2741 Flush data written to the server.
2723 2742
2724 2743 readavailable
2725 2744 -------------
2726 2745
2727 2746 Close the write end of the connection and read all available data from
2728 2747 the server.
2729 2748
2730 2749 If the connection to the server encompasses multiple pipes, we poll both
2731 2750 pipes and read available data.
2732 2751
2733 2752 readline
2734 2753 --------
2735 2754
2736 2755 Read a line of output from the server. If there are multiple output
2737 2756 pipes, reads only the main pipe.
2738 2757
2739 2758 ereadline
2740 2759 ---------
2741 2760
2742 2761 Like ``readline``, but read from the stderr pipe, if available.
2743 2762
2744 2763 read <X>
2745 2764 --------
2746 2765
2747 2766 ``read()`` N bytes from the server's main output pipe.
2748 2767
2749 2768 eread <X>
2750 2769 ---------
2751 2770
2752 2771 ``read()`` N bytes from the server's stderr pipe, if available.
2753 2772
2754 2773 Specifying Unified Frame-Based Protocol Frames
2755 2774 ----------------------------------------------
2756 2775
2757 2776 It is possible to emit a *Unified Frame-Based Protocol* by using special
2758 2777 syntax.
2759 2778
2760 2779 A frame is composed as a type, flags, and payload. These can be parsed
2761 2780 from a string of the form ``<requestid> <type> <flags> <payload>``. That is,
2762 2781 4 space-delimited strings.
2763 2782
2764 2783 ``payload`` is the simplest: it is evaluated as a Python byte string
2765 2784 literal.
2766 2785
2767 2786 ``requestid`` is an integer defining the request identifier.
2768 2787
2769 2788 ``type`` can be an integer value for the frame type or the string name
2770 2789 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2771 2790 ``command-name``.
2772 2791
2773 2792 ``flags`` is a ``|`` delimited list of flag components. Each component
2774 2793 (and there can be just one) can be an integer or a flag name for the
2775 2794 specified frame type. Values are resolved to integers and then bitwise
2776 2795 OR'd together.
2777 2796 """
2778 2797 opts = pycompat.byteskwargs(opts)
2779 2798
2780 2799 if opts['localssh'] and not repo:
2781 2800 raise error.Abort(_('--localssh requires a repository'))
2782 2801
2783 2802 if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'):
2784 2803 raise error.Abort(_('invalid value for --peer'),
2785 2804 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2786 2805
2787 2806 if path and opts['localssh']:
2788 2807 raise error.Abort(_('cannot specify --localssh with an explicit '
2789 2808 'path'))
2790 2809
2791 2810 if ui.interactive():
2792 2811 ui.write(_('(waiting for commands on stdin)\n'))
2793 2812
2794 2813 blocks = list(_parsewirelangblocks(ui.fin))
2795 2814
2796 2815 proc = None
2797 2816 stdin = None
2798 2817 stdout = None
2799 2818 stderr = None
2800 2819 opener = None
2801 2820
2802 2821 if opts['localssh']:
2803 2822 # We start the SSH server in its own process so there is process
2804 2823 # separation. This prevents a whole class of potential bugs around
2805 2824 # shared state from interfering with server operation.
2806 2825 args = procutil.hgcmd() + [
2807 2826 '-R', repo.root,
2808 2827 'debugserve', '--sshstdio',
2809 2828 ]
2810 2829 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2811 2830 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2812 2831 bufsize=0)
2813 2832
2814 2833 stdin = proc.stdin
2815 2834 stdout = proc.stdout
2816 2835 stderr = proc.stderr
2817 2836
2818 2837 # We turn the pipes into observers so we can log I/O.
2819 2838 if ui.verbose or opts['peer'] == 'raw':
2820 2839 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2821 2840 logdata=True)
2822 2841 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2823 2842 logdata=True)
2824 2843 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2825 2844 logdata=True)
2826 2845
2827 2846 # --localssh also implies the peer connection settings.
2828 2847
2829 2848 url = 'ssh://localserver'
2830 2849 autoreadstderr = not opts['noreadstderr']
2831 2850
2832 2851 if opts['peer'] == 'ssh1':
2833 2852 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2834 2853 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2835 2854 None, autoreadstderr=autoreadstderr)
2836 2855 elif opts['peer'] == 'ssh2':
2837 2856 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2838 2857 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2839 2858 None, autoreadstderr=autoreadstderr)
2840 2859 elif opts['peer'] == 'raw':
2841 2860 ui.write(_('using raw connection to peer\n'))
2842 2861 peer = None
2843 2862 else:
2844 2863 ui.write(_('creating ssh peer from handshake results\n'))
2845 2864 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2846 2865 autoreadstderr=autoreadstderr)
2847 2866
2848 2867 elif path:
2849 2868 # We bypass hg.peer() so we can proxy the sockets.
2850 2869 # TODO consider not doing this because we skip
2851 2870 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2852 2871 u = util.url(path)
2853 2872 if u.scheme != 'http':
2854 2873 raise error.Abort(_('only http:// paths are currently supported'))
2855 2874
2856 2875 url, authinfo = u.authinfo()
2857 2876 openerargs = {}
2858 2877
2859 2878 # Turn pipes/sockets into observers so we can log I/O.
2860 2879 if ui.verbose:
2861 2880 openerargs = {
2862 2881 r'loggingfh': ui,
2863 2882 r'loggingname': b's',
2864 2883 r'loggingopts': {
2865 2884 r'logdata': True,
2866 2885 r'logdataapis': False,
2867 2886 },
2868 2887 }
2869 2888
2870 2889 if ui.debugflag:
2871 2890 openerargs[r'loggingopts'][r'logdataapis'] = True
2872 2891
2873 2892 # Don't send default headers when in raw mode. This allows us to
2874 2893 # bypass most of the behavior of our URL handling code so we can
2875 2894 # have near complete control over what's sent on the wire.
2876 2895 if opts['peer'] == 'raw':
2877 2896 openerargs[r'sendaccept'] = False
2878 2897
2879 2898 opener = urlmod.opener(ui, authinfo, **openerargs)
2880 2899
2881 2900 if opts['peer'] == 'raw':
2882 2901 ui.write(_('using raw connection to peer\n'))
2883 2902 peer = None
2884 2903 elif opts['peer']:
2885 2904 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2886 2905 opts['peer'])
2887 2906 else:
2888 2907 peer = httppeer.httppeer(ui, path, url, opener)
2889 2908 peer._fetchcaps()
2890 2909
2891 2910 # We /could/ populate stdin/stdout with sock.makefile()...
2892 2911 else:
2893 2912 raise error.Abort(_('unsupported connection configuration'))
2894 2913
2895 2914 batchedcommands = None
2896 2915
2897 2916 # Now perform actions based on the parsed wire language instructions.
2898 2917 for action, lines in blocks:
2899 2918 if action in ('raw', 'raw+'):
2900 2919 if not stdin:
2901 2920 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2902 2921
2903 2922 # Concatenate the data together.
2904 2923 data = ''.join(l.lstrip() for l in lines)
2905 2924 data = stringutil.unescapestr(data)
2906 2925 stdin.write(data)
2907 2926
2908 2927 if action == 'raw+':
2909 2928 stdin.flush()
2910 2929 elif action == 'flush':
2911 2930 if not stdin:
2912 2931 raise error.Abort(_('cannot call flush on this peer'))
2913 2932 stdin.flush()
2914 2933 elif action.startswith('command'):
2915 2934 if not peer:
2916 2935 raise error.Abort(_('cannot send commands unless peer instance '
2917 2936 'is available'))
2918 2937
2919 2938 command = action.split(' ', 1)[1]
2920 2939
2921 2940 args = {}
2922 2941 for line in lines:
2923 2942 # We need to allow empty values.
2924 2943 fields = line.lstrip().split(' ', 1)
2925 2944 if len(fields) == 1:
2926 2945 key = fields[0]
2927 2946 value = ''
2928 2947 else:
2929 2948 key, value = fields
2930 2949
2931 2950 args[key] = stringutil.unescapestr(value)
2932 2951
2933 2952 if batchedcommands is not None:
2934 2953 batchedcommands.append((command, args))
2935 2954 continue
2936 2955
2937 2956 ui.status(_('sending %s command\n') % command)
2938 2957
2939 2958 if 'PUSHFILE' in args:
2940 2959 with open(args['PUSHFILE'], r'rb') as fh:
2941 2960 del args['PUSHFILE']
2942 2961 res, output = peer._callpush(command, fh,
2943 2962 **pycompat.strkwargs(args))
2944 2963 ui.status(_('result: %s\n') % stringutil.escapedata(res))
2945 2964 ui.status(_('remote output: %s\n') %
2946 2965 stringutil.escapedata(output))
2947 2966 else:
2948 2967 res = peer._call(command, **pycompat.strkwargs(args))
2949 2968 ui.status(_('response: %s\n') % stringutil.escapedata(res))
2950 2969
2951 2970 elif action == 'batchbegin':
2952 2971 if batchedcommands is not None:
2953 2972 raise error.Abort(_('nested batchbegin not allowed'))
2954 2973
2955 2974 batchedcommands = []
2956 2975 elif action == 'batchsubmit':
2957 2976 # There is a batching API we could go through. But it would be
2958 2977 # difficult to normalize requests into function calls. It is easier
2959 2978 # to bypass this layer and normalize to commands + args.
2960 2979 ui.status(_('sending batch with %d sub-commands\n') %
2961 2980 len(batchedcommands))
2962 2981 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
2963 2982 ui.status(_('response #%d: %s\n') %
2964 2983 (i, stringutil.escapedata(chunk)))
2965 2984
2966 2985 batchedcommands = None
2967 2986
2968 2987 elif action.startswith('httprequest '):
2969 2988 if not opener:
2970 2989 raise error.Abort(_('cannot use httprequest without an HTTP '
2971 2990 'peer'))
2972 2991
2973 2992 request = action.split(' ', 2)
2974 2993 if len(request) != 3:
2975 2994 raise error.Abort(_('invalid httprequest: expected format is '
2976 2995 '"httprequest <method> <path>'))
2977 2996
2978 2997 method, httppath = request[1:]
2979 2998 headers = {}
2980 2999 body = None
2981 3000 frames = []
2982 3001 for line in lines:
2983 3002 line = line.lstrip()
2984 3003 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
2985 3004 if m:
2986 3005 headers[m.group(1)] = m.group(2)
2987 3006 continue
2988 3007
2989 3008 if line.startswith(b'BODYFILE '):
2990 3009 with open(line.split(b' ', 1), 'rb') as fh:
2991 3010 body = fh.read()
2992 3011 elif line.startswith(b'frame '):
2993 3012 frame = wireprotoframing.makeframefromhumanstring(
2994 3013 line[len(b'frame '):])
2995 3014
2996 3015 frames.append(frame)
2997 3016 else:
2998 3017 raise error.Abort(_('unknown argument to httprequest: %s') %
2999 3018 line)
3000 3019
3001 3020 url = path + httppath
3002 3021
3003 3022 if frames:
3004 3023 body = b''.join(bytes(f) for f in frames)
3005 3024
3006 3025 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3007 3026
3008 3027 # urllib.Request insists on using has_data() as a proxy for
3009 3028 # determining the request method. Override that to use our
3010 3029 # explicitly requested method.
3011 3030 req.get_method = lambda: method
3012 3031
3013 3032 try:
3014 3033 opener.open(req).read()
3015 3034 except util.urlerr.urlerror as e:
3016 3035 e.read()
3017 3036
3018 3037 elif action == 'close':
3019 3038 peer.close()
3020 3039 elif action == 'readavailable':
3021 3040 if not stdout or not stderr:
3022 3041 raise error.Abort(_('readavailable not available on this peer'))
3023 3042
3024 3043 stdin.close()
3025 3044 stdout.read()
3026 3045 stderr.read()
3027 3046
3028 3047 elif action == 'readline':
3029 3048 if not stdout:
3030 3049 raise error.Abort(_('readline not available on this peer'))
3031 3050 stdout.readline()
3032 3051 elif action == 'ereadline':
3033 3052 if not stderr:
3034 3053 raise error.Abort(_('ereadline not available on this peer'))
3035 3054 stderr.readline()
3036 3055 elif action.startswith('read '):
3037 3056 count = int(action.split(' ', 1)[1])
3038 3057 if not stdout:
3039 3058 raise error.Abort(_('read not available on this peer'))
3040 3059 stdout.read(count)
3041 3060 elif action.startswith('eread '):
3042 3061 count = int(action.split(' ', 1)[1])
3043 3062 if not stderr:
3044 3063 raise error.Abort(_('eread not available on this peer'))
3045 3064 stderr.read(count)
3046 3065 else:
3047 3066 raise error.Abort(_('unknown action: %s') % action)
3048 3067
3049 3068 if batchedcommands is not None:
3050 3069 raise error.Abort(_('unclosed "batchbegin" request'))
3051 3070
3052 3071 if peer:
3053 3072 peer.close()
3054 3073
3055 3074 if proc:
3056 3075 proc.kill()
@@ -1,57 +1,57 b''
1 1 #require execbit
2 2
3 3 b51a8138292a introduced a regression where we would mention in the
4 4 changelog executable files added by the second parent of a merge. Test
5 5 that that doesn't happen anymore
6 6
7 7 $ hg init repo
8 8 $ cd repo
9 9 $ echo foo > foo
10 10 $ hg ci -qAm 'add foo'
11 11
12 12 $ echo bar > bar
13 13 $ chmod +x bar
14 14 $ hg ci -qAm 'add bar'
15 15
16 16 manifest of p2:
17 17
18 18 $ hg manifest
19 19 bar
20 20 foo
21 21
22 22 $ hg up -qC 0
23 23 $ echo >> foo
24 24 $ hg ci -m 'change foo'
25 25 created new head
26 26
27 27 manifest of p1:
28 28
29 29 $ hg manifest
30 30 foo
31 31
32 32 $ hg merge
33 33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 (branch merge, don't forget to commit)
35 35 $ chmod +x foo
36 36 $ hg ci -m 'merge'
37 37
38 38 this should not mention bar but should mention foo:
39 39
40 40 $ hg tip -v
41 41 changeset: 3:c53d17ff3380
42 42 tag: tip
43 43 parent: 2:ed1b79f46b9a
44 44 parent: 1:d394a8db219b
45 45 user: test
46 46 date: Thu Jan 01 00:00:00 1970 +0000
47 47 files: foo
48 48 description:
49 49 merge
50 50
51 51
52 52
53 53 $ hg debugindex bar
54 rev offset length linkrev nodeid p1 p2
55 0 0 5 1 b004912a8510 000000000000 000000000000
54 rev linkrev nodeid p1 p2
55 0 1 b004912a8510 000000000000 000000000000
56 56
57 57 $ cd ..
@@ -1,254 +1,254 b''
1 1 $ hg init test
2 2 $ cd test
3 3
4 4 $ echo 0 >> afile
5 5 $ hg add afile
6 6 $ hg commit -m "0.0"
7 7
8 8 $ echo 1 >> afile
9 9 $ hg commit -m "0.1"
10 10
11 11 $ echo 2 >> afile
12 12 $ hg commit -m "0.2"
13 13
14 14 $ echo 3 >> afile
15 15 $ hg commit -m "0.3"
16 16
17 17 $ hg update -C 0
18 18 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 19
20 20 $ echo 1 >> afile
21 21 $ hg commit -m "1.1"
22 22 created new head
23 23
24 24 $ echo 2 >> afile
25 25 $ hg commit -m "1.2"
26 26
27 27 $ echo a line > fred
28 28 $ echo 3 >> afile
29 29 $ hg add fred
30 30 $ hg commit -m "1.3"
31 31 $ hg mv afile adifferentfile
32 32 $ hg commit -m "1.3m"
33 33
34 34 $ hg update -C 3
35 35 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
36 36
37 37 $ hg mv afile anotherfile
38 38 $ hg commit -m "0.3m"
39 39
40 40 $ hg debugindex -f 1 afile
41 rev flag offset length size link p1 p2 nodeid
42 0 0000 0 3 2 0 -1 -1 362fef284ce2
43 1 0000 3 5 4 1 0 -1 125144f7e028
44 2 0000 8 7 6 2 1 -1 4c982badb186
45 3 0000 15 9 8 3 2 -1 19b1fc555737
41 rev flag size link p1 p2 nodeid
42 0 0000 2 0 -1 -1 362fef284ce2
43 1 0000 4 1 0 -1 125144f7e028
44 2 0000 6 2 1 -1 4c982badb186
45 3 0000 8 3 2 -1 19b1fc555737
46 46
47 47 $ hg debugindex adifferentfile
48 rev offset length linkrev nodeid p1 p2
49 0 0 75 7 2565f3199a74 000000000000 000000000000
48 rev linkrev nodeid p1 p2
49 0 7 2565f3199a74 000000000000 000000000000
50 50
51 51 $ hg debugindex anotherfile
52 rev offset length linkrev nodeid p1 p2
53 0 0 75 8 2565f3199a74 000000000000 000000000000
52 rev linkrev nodeid p1 p2
53 0 8 2565f3199a74 000000000000 000000000000
54 54
55 55 $ hg debugindex fred
56 rev offset length linkrev nodeid p1 p2
57 0 0 8 6 12ab3bcc5ea4 000000000000 000000000000
56 rev linkrev nodeid p1 p2
57 0 6 12ab3bcc5ea4 000000000000 000000000000
58 58
59 59 $ hg debugindex --manifest
60 rev offset length linkrev nodeid p1 p2
61 0 0 48 0 43eadb1d2d06 000000000000 000000000000
62 1 48 48 1 8b89697eba2c 43eadb1d2d06 000000000000
63 2 96 48 2 626a32663c2f 8b89697eba2c 000000000000
64 3 144 48 3 f54c32f13478 626a32663c2f 000000000000
65 4 192 .. 6 de68e904d169 626a32663c2f 000000000000 (re)
66 5 2.. .. 7 09bb521d218d de68e904d169 000000000000 (re)
67 6 3.. 54 8 1fde233dfb0f f54c32f13478 000000000000 (re)
60 rev linkrev nodeid p1 p2
61 0 0 43eadb1d2d06 000000000000 000000000000
62 1 1 8b89697eba2c 43eadb1d2d06 000000000000
63 2 2 626a32663c2f 8b89697eba2c 000000000000
64 3 3 f54c32f13478 626a32663c2f 000000000000
65 4 6 de68e904d169 626a32663c2f 000000000000
66 5 7 09bb521d218d de68e904d169 000000000000
67 6 8 1fde233dfb0f f54c32f13478 000000000000
68 68
69 69 $ hg verify
70 70 checking changesets
71 71 checking manifests
72 72 crosschecking files in changesets and manifests
73 73 checking files
74 74 4 files, 9 changesets, 7 total revisions
75 75
76 76 $ cd ..
77 77
78 78 $ for i in 0 1 2 3 4 5 6 7 8; do
79 79 > echo
80 80 > echo ---- hg clone -r "$i" test test-"$i"
81 81 > hg clone -r "$i" test test-"$i"
82 82 > cd test-"$i"
83 83 > hg verify
84 84 > cd ..
85 85 > done
86 86
87 87 ---- hg clone -r 0 test test-0
88 88 adding changesets
89 89 adding manifests
90 90 adding file changes
91 91 added 1 changesets with 1 changes to 1 files
92 92 new changesets f9ee2f85a263
93 93 updating to branch default
94 94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 95 checking changesets
96 96 checking manifests
97 97 crosschecking files in changesets and manifests
98 98 checking files
99 99 1 files, 1 changesets, 1 total revisions
100 100
101 101 ---- hg clone -r 1 test test-1
102 102 adding changesets
103 103 adding manifests
104 104 adding file changes
105 105 added 2 changesets with 2 changes to 1 files
106 106 new changesets f9ee2f85a263:34c2bf6b0626
107 107 updating to branch default
108 108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 checking changesets
110 110 checking manifests
111 111 crosschecking files in changesets and manifests
112 112 checking files
113 113 1 files, 2 changesets, 2 total revisions
114 114
115 115 ---- hg clone -r 2 test test-2
116 116 adding changesets
117 117 adding manifests
118 118 adding file changes
119 119 added 3 changesets with 3 changes to 1 files
120 120 new changesets f9ee2f85a263:e38ba6f5b7e0
121 121 updating to branch default
122 122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 123 checking changesets
124 124 checking manifests
125 125 crosschecking files in changesets and manifests
126 126 checking files
127 127 1 files, 3 changesets, 3 total revisions
128 128
129 129 ---- hg clone -r 3 test test-3
130 130 adding changesets
131 131 adding manifests
132 132 adding file changes
133 133 added 4 changesets with 4 changes to 1 files
134 134 new changesets f9ee2f85a263:eebf5a27f8ca
135 135 updating to branch default
136 136 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137 checking changesets
138 138 checking manifests
139 139 crosschecking files in changesets and manifests
140 140 checking files
141 141 1 files, 4 changesets, 4 total revisions
142 142
143 143 ---- hg clone -r 4 test test-4
144 144 adding changesets
145 145 adding manifests
146 146 adding file changes
147 147 added 2 changesets with 2 changes to 1 files
148 148 new changesets f9ee2f85a263:095197eb4973
149 149 updating to branch default
150 150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 checking changesets
152 152 checking manifests
153 153 crosschecking files in changesets and manifests
154 154 checking files
155 155 1 files, 2 changesets, 2 total revisions
156 156
157 157 ---- hg clone -r 5 test test-5
158 158 adding changesets
159 159 adding manifests
160 160 adding file changes
161 161 added 3 changesets with 3 changes to 1 files
162 162 new changesets f9ee2f85a263:1bb50a9436a7
163 163 updating to branch default
164 164 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 165 checking changesets
166 166 checking manifests
167 167 crosschecking files in changesets and manifests
168 168 checking files
169 169 1 files, 3 changesets, 3 total revisions
170 170
171 171 ---- hg clone -r 6 test test-6
172 172 adding changesets
173 173 adding manifests
174 174 adding file changes
175 175 added 4 changesets with 5 changes to 2 files
176 176 new changesets f9ee2f85a263:7373c1169842
177 177 updating to branch default
178 178 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 179 checking changesets
180 180 checking manifests
181 181 crosschecking files in changesets and manifests
182 182 checking files
183 183 2 files, 4 changesets, 5 total revisions
184 184
185 185 ---- hg clone -r 7 test test-7
186 186 adding changesets
187 187 adding manifests
188 188 adding file changes
189 189 added 5 changesets with 6 changes to 3 files
190 190 new changesets f9ee2f85a263:a6a34bfa0076
191 191 updating to branch default
192 192 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 193 checking changesets
194 194 checking manifests
195 195 crosschecking files in changesets and manifests
196 196 checking files
197 197 3 files, 5 changesets, 6 total revisions
198 198
199 199 ---- hg clone -r 8 test test-8
200 200 adding changesets
201 201 adding manifests
202 202 adding file changes
203 203 added 5 changesets with 5 changes to 2 files
204 204 new changesets f9ee2f85a263:aa35859c02ea
205 205 updating to branch default
206 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 207 checking changesets
208 208 checking manifests
209 209 crosschecking files in changesets and manifests
210 210 checking files
211 211 2 files, 5 changesets, 5 total revisions
212 212
213 213 $ cd test-8
214 214 $ hg pull ../test-7
215 215 pulling from ../test-7
216 216 searching for changes
217 217 adding changesets
218 218 adding manifests
219 219 adding file changes
220 220 added 4 changesets with 2 changes to 3 files (+1 heads)
221 221 new changesets 095197eb4973:a6a34bfa0076
222 222 (run 'hg heads' to see heads, 'hg merge' to merge)
223 223 $ hg verify
224 224 checking changesets
225 225 checking manifests
226 226 crosschecking files in changesets and manifests
227 227 checking files
228 228 4 files, 9 changesets, 7 total revisions
229 229 $ cd ..
230 230
231 231 $ hg clone test test-9
232 232 updating to branch default
233 233 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 234 $ cd test-9
235 235 $ hg branch foobar
236 236 marked working directory as branch foobar
237 237 (branches are permanent and global, did you want a bookmark?)
238 238 $ echo file2 >> file2
239 239 $ hg add file2
240 240 $ hg commit -m "changeset9"
241 241 $ echo file3 >> file3
242 242 $ hg add file3
243 243 $ hg commit -m "changeset10"
244 244 $ cd ..
245 245 $ hg clone -r 9 -u foobar test-9 test-10
246 246 adding changesets
247 247 adding manifests
248 248 adding file changes
249 249 added 6 changesets with 6 changes to 3 files
250 250 new changesets f9ee2f85a263:7100abb79635
251 251 updating to branch foobar
252 252 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 253
254 254
@@ -1,1288 +1,1288 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [format]
3 3 > usegeneraldelta=yes
4 4 > EOF
5 5
6 6 $ hg init
7 7
8 8 Setup:
9 9
10 10 $ echo a >> a
11 11 $ hg ci -Am 'base'
12 12 adding a
13 13
14 14 Refuse to amend public csets:
15 15
16 16 $ hg phase -r . -p
17 17 $ hg ci --amend
18 18 abort: cannot amend public changesets
19 19 (see 'hg help phases' for details)
20 20 [255]
21 21 $ hg phase -r . -f -d
22 22
23 23 $ echo a >> a
24 24 $ hg ci -Am 'base1'
25 25
26 26 Nothing to amend:
27 27
28 28 $ hg ci --amend -m 'base1'
29 29 nothing changed
30 30 [1]
31 31
32 32 $ cat >> $HGRCPATH <<EOF
33 33 > [hooks]
34 34 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
35 35 > EOF
36 36
37 37 Amending changeset with changes in working dir:
38 38 (and check that --message does not trigger an editor)
39 39
40 40 $ echo a >> a
41 41 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
42 42 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
43 43 43f1ba15f28a tip
44 44 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-5ab4f721-amend.hg
45 45 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
46 46 $ hg diff -c .
47 47 diff -r ad120869acf0 -r 43f1ba15f28a a
48 48 --- a/a Thu Jan 01 00:00:00 1970 +0000
49 49 +++ b/a Thu Jan 01 00:00:00 1970 +0000
50 50 @@ -1,1 +1,3 @@
51 51 a
52 52 +a
53 53 +a
54 54 $ hg log
55 55 changeset: 1:43f1ba15f28a
56 56 tag: tip
57 57 user: test
58 58 date: Thu Jan 01 00:00:00 1970 +0000
59 59 summary: amend base1
60 60
61 61 changeset: 0:ad120869acf0
62 62 user: test
63 63 date: Thu Jan 01 00:00:00 1970 +0000
64 64 summary: base
65 65
66 66
67 67 Check proper abort for empty message
68 68
69 69 $ cat > editor.sh << '__EOF__'
70 70 > #!/bin/sh
71 71 > echo "" > "$1"
72 72 > __EOF__
73 73
74 74 Update the existing file to ensure that the dirstate is not in pending state
75 75 (where the status of some files in the working copy is not known yet). This in
76 76 turn ensures that when the transaction is aborted due to an empty message during
77 77 the amend, there should be no rollback.
78 78 $ echo a >> a
79 79
80 80 $ echo b > b
81 81 $ hg add b
82 82 $ hg summary
83 83 parent: 1:43f1ba15f28a tip
84 84 amend base1
85 85 branch: default
86 86 commit: 1 modified, 1 added, 1 unknown
87 87 update: (current)
88 88 phases: 2 draft
89 89 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
90 90 abort: empty commit message
91 91 [255]
92 92 $ hg summary
93 93 parent: 1:43f1ba15f28a tip
94 94 amend base1
95 95 branch: default
96 96 commit: 1 modified, 1 added, 1 unknown
97 97 update: (current)
98 98 phases: 2 draft
99 99
100 100 Add new file along with modified existing file:
101 101 $ hg ci --amend -m 'amend base1 new file'
102 102 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-007467c2-amend.hg
103 103
104 104 Remove file that was added in amended commit:
105 105 (and test logfile option)
106 106 (and test that logfile option do not trigger an editor)
107 107
108 108 $ hg rm b
109 109 $ echo 'amend base1 remove new file' > ../logfile
110 110 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
111 111 saved backup bundle to $TESTTMP/.hg/strip-backup/c16295aaf401-1ada9901-amend.hg
112 112
113 113 $ hg cat b
114 114 b: no such file in rev 47343646fa3d
115 115 [1]
116 116
117 117 No changes, just a different message:
118 118
119 119 $ hg ci -v --amend -m 'no changes, new message'
120 120 amending changeset 47343646fa3d
121 121 copying changeset 47343646fa3d to ad120869acf0
122 122 committing files:
123 123 a
124 124 committing manifest
125 125 committing changelog
126 126 1 changesets found
127 127 uncompressed size of bundle content:
128 128 254 (changelog)
129 129 163 (manifests)
130 130 131 a
131 131 saved backup bundle to $TESTTMP/.hg/strip-backup/47343646fa3d-c2758885-amend.hg
132 132 1 changesets found
133 133 uncompressed size of bundle content:
134 134 250 (changelog)
135 135 163 (manifests)
136 136 131 a
137 137 adding branch
138 138 adding changesets
139 139 adding manifests
140 140 adding file changes
141 141 added 1 changesets with 1 changes to 1 files
142 142 committed changeset 1:401431e913a1
143 143 $ hg diff -c .
144 144 diff -r ad120869acf0 -r 401431e913a1 a
145 145 --- a/a Thu Jan 01 00:00:00 1970 +0000
146 146 +++ b/a Thu Jan 01 00:00:00 1970 +0000
147 147 @@ -1,1 +1,4 @@
148 148 a
149 149 +a
150 150 +a
151 151 +a
152 152 $ hg log
153 153 changeset: 1:401431e913a1
154 154 tag: tip
155 155 user: test
156 156 date: Thu Jan 01 00:00:00 1970 +0000
157 157 summary: no changes, new message
158 158
159 159 changeset: 0:ad120869acf0
160 160 user: test
161 161 date: Thu Jan 01 00:00:00 1970 +0000
162 162 summary: base
163 163
164 164
165 165 Disable default date on commit so when -d isn't given, the old date is preserved:
166 166
167 167 $ echo '[defaults]' >> $HGRCPATH
168 168 $ echo 'commit=' >> $HGRCPATH
169 169
170 170 Test -u/-d:
171 171
172 172 $ cat > .hg/checkeditform.sh <<EOF
173 173 > env | grep HGEDITFORM
174 174 > true
175 175 > EOF
176 176 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -u foo -d '1 0'
177 177 HGEDITFORM=commit.amend.normal
178 178 saved backup bundle to $TESTTMP/.hg/strip-backup/401431e913a1-5e8e532c-amend.hg
179 179 $ echo a >> a
180 180 $ hg ci --amend -u foo -d '1 0'
181 181 saved backup bundle to $TESTTMP/.hg/strip-backup/d96b1d28ae33-677e0afb-amend.hg
182 182 $ hg log -r .
183 183 changeset: 1:a9a13940fc03
184 184 tag: tip
185 185 user: foo
186 186 date: Thu Jan 01 00:00:01 1970 +0000
187 187 summary: no changes, new message
188 188
189 189
190 190 Open editor with old commit message if a message isn't given otherwise:
191 191
192 192 $ cat > editor.sh << '__EOF__'
193 193 > #!/bin/sh
194 194 > cat $1
195 195 > echo "another precious commit message" > "$1"
196 196 > __EOF__
197 197
198 198 at first, test saving last-message.txt
199 199
200 200 $ cat > .hg/hgrc << '__EOF__'
201 201 > [hooks]
202 202 > pretxncommit.test-saving-last-message = false
203 203 > __EOF__
204 204
205 205 $ rm -f .hg/last-message.txt
206 206 $ hg commit --amend -v -m "message given from command line"
207 207 amending changeset a9a13940fc03
208 208 copying changeset a9a13940fc03 to ad120869acf0
209 209 committing files:
210 210 a
211 211 committing manifest
212 212 committing changelog
213 213 running hook pretxncommit.test-saving-last-message: false
214 214 transaction abort!
215 215 rollback completed
216 216 abort: pretxncommit.test-saving-last-message hook exited with status 1
217 217 [255]
218 218 $ cat .hg/last-message.txt
219 219 message given from command line (no-eol)
220 220
221 221 $ rm -f .hg/last-message.txt
222 222 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
223 223 amending changeset a9a13940fc03
224 224 copying changeset a9a13940fc03 to ad120869acf0
225 225 no changes, new message
226 226
227 227
228 228 HG: Enter commit message. Lines beginning with 'HG:' are removed.
229 229 HG: Leave message empty to abort commit.
230 230 HG: --
231 231 HG: user: foo
232 232 HG: branch 'default'
233 233 HG: changed a
234 234 committing files:
235 235 a
236 236 committing manifest
237 237 committing changelog
238 238 running hook pretxncommit.test-saving-last-message: false
239 239 transaction abort!
240 240 rollback completed
241 241 abort: pretxncommit.test-saving-last-message hook exited with status 1
242 242 [255]
243 243
244 244 $ cat .hg/last-message.txt
245 245 another precious commit message
246 246
247 247 $ cat > .hg/hgrc << '__EOF__'
248 248 > [hooks]
249 249 > pretxncommit.test-saving-last-message =
250 250 > __EOF__
251 251
252 252 then, test editing custom commit message
253 253
254 254 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
255 255 amending changeset a9a13940fc03
256 256 copying changeset a9a13940fc03 to ad120869acf0
257 257 no changes, new message
258 258
259 259
260 260 HG: Enter commit message. Lines beginning with 'HG:' are removed.
261 261 HG: Leave message empty to abort commit.
262 262 HG: --
263 263 HG: user: foo
264 264 HG: branch 'default'
265 265 HG: changed a
266 266 committing files:
267 267 a
268 268 committing manifest
269 269 committing changelog
270 270 1 changesets found
271 271 uncompressed size of bundle content:
272 272 249 (changelog)
273 273 163 (manifests)
274 274 133 a
275 275 saved backup bundle to $TESTTMP/.hg/strip-backup/a9a13940fc03-7c2e8674-amend.hg
276 276 1 changesets found
277 277 uncompressed size of bundle content:
278 278 257 (changelog)
279 279 163 (manifests)
280 280 133 a
281 281 adding branch
282 282 adding changesets
283 283 adding manifests
284 284 adding file changes
285 285 added 1 changesets with 1 changes to 1 files
286 286 committed changeset 1:64a124ba1b44
287 287
288 288 Same, but with changes in working dir (different code path):
289 289
290 290 $ echo a >> a
291 291 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
292 292 amending changeset 64a124ba1b44
293 293 another precious commit message
294 294
295 295
296 296 HG: Enter commit message. Lines beginning with 'HG:' are removed.
297 297 HG: Leave message empty to abort commit.
298 298 HG: --
299 299 HG: user: foo
300 300 HG: branch 'default'
301 301 HG: changed a
302 302 committing files:
303 303 a
304 304 committing manifest
305 305 committing changelog
306 306 1 changesets found
307 307 uncompressed size of bundle content:
308 308 257 (changelog)
309 309 163 (manifests)
310 310 133 a
311 311 saved backup bundle to $TESTTMP/.hg/strip-backup/64a124ba1b44-10374b8f-amend.hg
312 312 1 changesets found
313 313 uncompressed size of bundle content:
314 314 257 (changelog)
315 315 163 (manifests)
316 316 135 a
317 317 adding branch
318 318 adding changesets
319 319 adding manifests
320 320 adding file changes
321 321 added 1 changesets with 1 changes to 1 files
322 322 committed changeset 1:7892795b8e38
323 323
324 324 $ rm editor.sh
325 325 $ hg log -r .
326 326 changeset: 1:7892795b8e38
327 327 tag: tip
328 328 user: foo
329 329 date: Thu Jan 01 00:00:01 1970 +0000
330 330 summary: another precious commit message
331 331
332 332
333 333 Moving bookmarks, preserve active bookmark:
334 334
335 335 $ hg book book1
336 336 $ hg book book2
337 337 $ hg ci --amend -m 'move bookmarks'
338 338 saved backup bundle to $TESTTMP/.hg/strip-backup/7892795b8e38-3fb46217-amend.hg
339 339 $ hg book
340 340 book1 1:8311f17e2616
341 341 * book2 1:8311f17e2616
342 342 $ echo a >> a
343 343 $ hg ci --amend -m 'move bookmarks'
344 344 saved backup bundle to $TESTTMP/.hg/strip-backup/8311f17e2616-f0504fe3-amend.hg
345 345 $ hg book
346 346 book1 1:a3b65065808c
347 347 * book2 1:a3b65065808c
348 348
349 349 abort does not loose bookmarks
350 350
351 351 $ cat > editor.sh << '__EOF__'
352 352 > #!/bin/sh
353 353 > echo "" > "$1"
354 354 > __EOF__
355 355 $ echo a >> a
356 356 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
357 357 abort: empty commit message
358 358 [255]
359 359 $ hg book
360 360 book1 1:a3b65065808c
361 361 * book2 1:a3b65065808c
362 362 $ hg revert -Caq
363 363 $ rm editor.sh
364 364
365 365 $ echo '[defaults]' >> $HGRCPATH
366 366 $ echo "commit=-d '0 0'" >> $HGRCPATH
367 367
368 368 Moving branches:
369 369
370 370 $ hg branch foo
371 371 marked working directory as branch foo
372 372 (branches are permanent and global, did you want a bookmark?)
373 373 $ echo a >> a
374 374 $ hg ci -m 'branch foo'
375 375 $ hg branch default -f
376 376 marked working directory as branch default
377 377 $ hg ci --amend -m 'back to default'
378 378 saved backup bundle to $TESTTMP/.hg/strip-backup/f8339a38efe1-c18453c9-amend.hg
379 379 $ hg branches
380 380 default 2:9c07515f2650
381 381
382 382 Close branch:
383 383
384 384 $ hg up -q 0
385 385 $ echo b >> b
386 386 $ hg branch foo
387 387 marked working directory as branch foo
388 388 (branches are permanent and global, did you want a bookmark?)
389 389 $ hg ci -Am 'fork'
390 390 adding b
391 391 $ echo b >> b
392 392 $ hg ci -mb
393 393 $ hg ci --amend --close-branch -m 'closing branch foo'
394 394 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-54245dc7-amend.hg
395 395
396 396 Same thing, different code path:
397 397
398 398 $ echo b >> b
399 399 $ hg ci -m 'reopen branch'
400 400 reopening closed branch head 4
401 401 $ echo b >> b
402 402 $ hg ci --amend --close-branch
403 403 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-b900d9fa-amend.hg
404 404 $ hg branches
405 405 default 2:9c07515f2650
406 406
407 407 Refuse to amend during a merge:
408 408
409 409 $ hg up -q default
410 410 $ hg merge foo
411 411 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 412 (branch merge, don't forget to commit)
413 413 $ hg ci --amend
414 414 abort: cannot amend while merging
415 415 [255]
416 416 $ hg ci -m 'merge'
417 417
418 418 Refuse to amend if there is a merge conflict (issue5805):
419 419
420 420 $ hg up -q foo
421 421 $ echo c > a
422 422 $ hg up default -t :fail
423 423 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
424 424 use 'hg resolve' to retry unresolved file merges
425 425 [1]
426 426 $ hg resolve -l
427 427 U a
428 428
429 429 $ hg ci --amend
430 430 abort: unresolved merge conflicts (see 'hg help resolve')
431 431 [255]
432 432
433 433 $ hg up -qC .
434 434
435 435 Follow copies/renames:
436 436
437 437 $ hg mv b c
438 438 $ hg ci -m 'b -> c'
439 439 $ hg mv c d
440 440 $ hg ci --amend -m 'b -> d'
441 441 saved backup bundle to $TESTTMP/.hg/strip-backup/42f3f27a067d-f23cc9f7-amend.hg
442 442 $ hg st --rev '.^' --copies d
443 443 A d
444 444 b
445 445 $ hg cp d e
446 446 $ hg ci -m 'e = d'
447 447 $ hg cp e f
448 448 $ hg ci --amend -m 'f = d'
449 449 saved backup bundle to $TESTTMP/.hg/strip-backup/9198f73182d5-251d584a-amend.hg
450 450 $ hg st --rev '.^' --copies f
451 451 A f
452 452 d
453 453
454 454 $ mv f f.orig
455 455 $ hg rm -A f
456 456 $ hg ci -m removef
457 457 $ hg cp a f
458 458 $ mv f.orig f
459 459 $ hg ci --amend -m replacef
460 460 saved backup bundle to $TESTTMP/.hg/strip-backup/f0993ab6b482-eda301bf-amend.hg
461 461 $ hg st --change . --copies
462 462 $ hg log -r . --template "{file_copies}\n"
463 463
464 464
465 465 Move added file (issue3410):
466 466
467 467 $ echo g >> g
468 468 $ hg ci -Am g
469 469 adding g
470 470 $ hg mv g h
471 471 $ hg ci --amend
472 472 saved backup bundle to $TESTTMP/.hg/strip-backup/58585e3f095c-0f5ebcda-amend.hg
473 473 $ hg st --change . --copies h
474 474 A h
475 475 $ hg log -r . --template "{file_copies}\n"
476 476
477 477
478 478 Can't rollback an amend:
479 479
480 480 $ hg rollback
481 481 no rollback information available
482 482 [1]
483 483
484 484 Preserve extra dict (issue3430):
485 485
486 486 $ hg branch a
487 487 marked working directory as branch a
488 488 (branches are permanent and global, did you want a bookmark?)
489 489 $ echo a >> a
490 490 $ hg ci -ma
491 491 $ hg ci --amend -m "a'"
492 492 saved backup bundle to $TESTTMP/.hg/strip-backup/39a162f1d65e-9dfe13d8-amend.hg
493 493 $ hg log -r . --template "{branch}\n"
494 494 a
495 495 $ hg ci --amend -m "a''"
496 496 saved backup bundle to $TESTTMP/.hg/strip-backup/d5ca7b1ac72b-0b4c1a34-amend.hg
497 497 $ hg log -r . --template "{branch}\n"
498 498 a
499 499
500 500 Also preserve other entries in the dict that are in the old commit,
501 501 first graft something so there's an additional entry:
502 502
503 503 $ hg up 0 -q
504 504 $ echo z > z
505 505 $ hg ci -Am 'fork'
506 506 adding z
507 507 created new head
508 508 $ hg up 11
509 509 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
510 510 $ hg graft 12
511 511 grafting 12:2647734878ef "fork" (tip)
512 512 $ hg ci --amend -m 'graft amend'
513 513 saved backup bundle to $TESTTMP/.hg/strip-backup/fe8c6f7957ca-25638666-amend.hg
514 514 $ hg log -r . --debug | grep extra
515 515 extra: amend_source=fe8c6f7957ca1665ed77496ed7a07657d469ac60
516 516 extra: branch=a
517 517 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
518 518
519 519 Preserve phase
520 520
521 521 $ hg phase '.^::.'
522 522 11: draft
523 523 13: draft
524 524 $ hg phase --secret --force .
525 525 $ hg phase '.^::.'
526 526 11: draft
527 527 13: secret
528 528 $ hg commit --amend -m 'amend for phase' -q
529 529 $ hg phase '.^::.'
530 530 11: draft
531 531 13: secret
532 532
533 533 Test amend with obsolete
534 534 ---------------------------
535 535
536 536 Enable obsolete
537 537
538 538 $ cat >> $HGRCPATH << EOF
539 539 > [experimental]
540 540 > evolution.createmarkers=True
541 541 > evolution.allowunstable=True
542 542 > EOF
543 543
544 544 Amend with no files changes
545 545
546 546 $ hg id -n
547 547 13
548 548 $ hg ci --amend -m 'babar'
549 549 $ hg id -n
550 550 14
551 551 $ hg log -Gl 3 --style=compact
552 552 @ 14[tip]:11 682950e85999 1970-01-01 00:00 +0000 test
553 553 | babar
554 554 |
555 555 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
556 556 | | fork
557 557 | ~
558 558 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
559 559 | a''
560 560 ~
561 561 $ hg log -Gl 4 --hidden --style=compact
562 562 @ 14[tip]:11 682950e85999 1970-01-01 00:00 +0000 test
563 563 | babar
564 564 |
565 565 | x 13:11 5167600b0f7a 1970-01-01 00:00 +0000 test
566 566 |/ amend for phase
567 567 |
568 568 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
569 569 | | fork
570 570 | ~
571 571 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
572 572 | a''
573 573 ~
574 574
575 575 Amend with files changes
576 576
577 577 (note: the extra commit over 15 is a temporary junk I would be happy to get
578 578 ride of)
579 579
580 580 $ echo 'babar' >> a
581 581 $ hg commit --amend
582 582 $ hg log -Gl 6 --hidden --style=compact
583 583 @ 15[tip]:11 a5b42b49b0d5 1970-01-01 00:00 +0000 test
584 584 | babar
585 585 |
586 586 | x 14:11 682950e85999 1970-01-01 00:00 +0000 test
587 587 |/ babar
588 588 |
589 589 | x 13:11 5167600b0f7a 1970-01-01 00:00 +0000 test
590 590 |/ amend for phase
591 591 |
592 592 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
593 593 | | fork
594 594 | ~
595 595 o 11 0ddb275cfad1 1970-01-01 00:00 +0000 test
596 596 | a''
597 597 |
598 598 o 10 5fa75032e226 1970-01-01 00:00 +0000 test
599 599 | g
600 600 ~
601 601
602 602
603 603 Test that amend does not make it easy to create obsolescence cycle
604 604 ---------------------------------------------------------------------
605 605
606 606 $ hg id -r 14 --hidden
607 607 682950e85999 (a)
608 608 $ hg revert -ar 14 --hidden
609 609 reverting a
610 610 $ hg commit --amend
611 611 $ hg id
612 612 37973c7e0b61 (a) tip
613 613
614 614 Test that rewriting leaving instability behind is allowed
615 615 ---------------------------------------------------------------------
616 616
617 617 $ hg up '.^'
618 618 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
619 619 $ echo 'b' >> a
620 620 $ hg log --style compact -r 'children(.)'
621 621 16[tip]:11 37973c7e0b61 1970-01-01 00:00 +0000 test
622 622 babar
623 623
624 624 $ hg commit --amend
625 625 1 new orphan changesets
626 626 $ hg log -r 'orphan()'
627 627 changeset: 16:37973c7e0b61
628 628 branch: a
629 629 parent: 11:0ddb275cfad1
630 630 user: test
631 631 date: Thu Jan 01 00:00:00 1970 +0000
632 632 instability: orphan
633 633 summary: babar
634 634
635 635
636 636 Amend a merge changeset (with renames and conflicts from the second parent):
637 637
638 638 $ hg up -q default
639 639 $ hg branch -q bar
640 640 $ hg cp a aa
641 641 $ hg mv z zz
642 642 $ echo cc > cc
643 643 $ hg add cc
644 644 $ hg ci -m aazzcc
645 645 $ hg up -q default
646 646 $ echo a >> a
647 647 $ echo dd > cc
648 648 $ hg add cc
649 649 $ hg ci -m aa
650 650 $ hg merge -q bar
651 651 warning: conflicts while merging cc! (edit, then use 'hg resolve --mark')
652 652 [1]
653 653 $ hg resolve -m cc
654 654 (no more unresolved files)
655 655 $ hg ci -m 'merge bar'
656 656 $ hg log --config diff.git=1 -pr .
657 657 changeset: 20:163cfd7219f7
658 658 tag: tip
659 659 parent: 19:30d96aeaf27b
660 660 parent: 18:1aa437659d19
661 661 user: test
662 662 date: Thu Jan 01 00:00:00 1970 +0000
663 663 summary: merge bar
664 664
665 665 diff --git a/a b/aa
666 666 copy from a
667 667 copy to aa
668 668 diff --git a/cc b/cc
669 669 --- a/cc
670 670 +++ b/cc
671 671 @@ -1,1 +1,5 @@
672 672 +<<<<<<< working copy: 30d96aeaf27b - test: aa
673 673 dd
674 674 +=======
675 675 +cc
676 676 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
677 677 diff --git a/z b/zz
678 678 rename from z
679 679 rename to zz
680 680
681 681 $ hg debugrename aa
682 682 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
683 683 $ hg debugrename zz
684 684 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
685 685 $ hg debugrename cc
686 686 cc not renamed
687 687 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -m 'merge bar (amend message)' --edit
688 688 HGEDITFORM=commit.amend.merge
689 689 $ hg log --config diff.git=1 -pr .
690 690 changeset: 21:bca52d4ed186
691 691 tag: tip
692 692 parent: 19:30d96aeaf27b
693 693 parent: 18:1aa437659d19
694 694 user: test
695 695 date: Thu Jan 01 00:00:00 1970 +0000
696 696 summary: merge bar (amend message)
697 697
698 698 diff --git a/a b/aa
699 699 copy from a
700 700 copy to aa
701 701 diff --git a/cc b/cc
702 702 --- a/cc
703 703 +++ b/cc
704 704 @@ -1,1 +1,5 @@
705 705 +<<<<<<< working copy: 30d96aeaf27b - test: aa
706 706 dd
707 707 +=======
708 708 +cc
709 709 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
710 710 diff --git a/z b/zz
711 711 rename from z
712 712 rename to zz
713 713
714 714 $ hg debugrename aa
715 715 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
716 716 $ hg debugrename zz
717 717 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
718 718 $ hg debugrename cc
719 719 cc not renamed
720 720 $ hg mv zz z
721 721 $ hg ci --amend -m 'merge bar (undo rename)'
722 722 $ hg log --config diff.git=1 -pr .
723 723 changeset: 22:12594a98ca3f
724 724 tag: tip
725 725 parent: 19:30d96aeaf27b
726 726 parent: 18:1aa437659d19
727 727 user: test
728 728 date: Thu Jan 01 00:00:00 1970 +0000
729 729 summary: merge bar (undo rename)
730 730
731 731 diff --git a/a b/aa
732 732 copy from a
733 733 copy to aa
734 734 diff --git a/cc b/cc
735 735 --- a/cc
736 736 +++ b/cc
737 737 @@ -1,1 +1,5 @@
738 738 +<<<<<<< working copy: 30d96aeaf27b - test: aa
739 739 dd
740 740 +=======
741 741 +cc
742 742 +>>>>>>> merge rev: 1aa437659d19 bar - test: aazzcc
743 743
744 744 $ hg debugrename z
745 745 z not renamed
746 746
747 747 Amend a merge changeset (with renames during the merge):
748 748
749 749 $ hg up -q bar
750 750 $ echo x > x
751 751 $ hg add x
752 752 $ hg ci -m x
753 753 $ hg up -q default
754 754 $ hg merge -q bar
755 755 $ hg mv aa aaa
756 756 $ echo aa >> aaa
757 757 $ hg ci -m 'merge bar again'
758 758 $ hg log --config diff.git=1 -pr .
759 759 changeset: 24:dffde028b388
760 760 tag: tip
761 761 parent: 22:12594a98ca3f
762 762 parent: 23:4c94d5bc65f5
763 763 user: test
764 764 date: Thu Jan 01 00:00:00 1970 +0000
765 765 summary: merge bar again
766 766
767 767 diff --git a/aa b/aa
768 768 deleted file mode 100644
769 769 --- a/aa
770 770 +++ /dev/null
771 771 @@ -1,2 +0,0 @@
772 772 -a
773 773 -a
774 774 diff --git a/aaa b/aaa
775 775 new file mode 100644
776 776 --- /dev/null
777 777 +++ b/aaa
778 778 @@ -0,0 +1,3 @@
779 779 +a
780 780 +a
781 781 +aa
782 782 diff --git a/x b/x
783 783 new file mode 100644
784 784 --- /dev/null
785 785 +++ b/x
786 786 @@ -0,0 +1,1 @@
787 787 +x
788 788
789 789 $ hg debugrename aaa
790 790 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
791 791 $ hg mv aaa aa
792 792 $ hg ci --amend -m 'merge bar again (undo rename)'
793 793 $ hg log --config diff.git=1 -pr .
794 794 changeset: 25:18e3ba160489
795 795 tag: tip
796 796 parent: 22:12594a98ca3f
797 797 parent: 23:4c94d5bc65f5
798 798 user: test
799 799 date: Thu Jan 01 00:00:00 1970 +0000
800 800 summary: merge bar again (undo rename)
801 801
802 802 diff --git a/aa b/aa
803 803 --- a/aa
804 804 +++ b/aa
805 805 @@ -1,2 +1,3 @@
806 806 a
807 807 a
808 808 +aa
809 809 diff --git a/x b/x
810 810 new file mode 100644
811 811 --- /dev/null
812 812 +++ b/x
813 813 @@ -0,0 +1,1 @@
814 814 +x
815 815
816 816 $ hg debugrename aa
817 817 aa not renamed
818 818 $ hg debugrename -r '.^' aa
819 819 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
820 820
821 821 Amend a merge changeset (with manifest-level conflicts):
822 822
823 823 $ hg up -q bar
824 824 $ hg rm aa
825 825 $ hg ci -m 'rm aa'
826 826 $ hg up -q default
827 827 $ echo aa >> aa
828 828 $ hg ci -m aa
829 829 $ hg merge -q bar --config ui.interactive=True << EOF
830 830 > c
831 831 > EOF
832 832 local [working copy] changed aa which other [merge rev] deleted
833 833 use (c)hanged version, (d)elete, or leave (u)nresolved? c
834 834 $ hg ci -m 'merge bar (with conflicts)'
835 835 $ hg log --config diff.git=1 -pr .
836 836 changeset: 28:b4c3035e2544
837 837 tag: tip
838 838 parent: 27:4b216ca5ba97
839 839 parent: 26:67db8847a540
840 840 user: test
841 841 date: Thu Jan 01 00:00:00 1970 +0000
842 842 summary: merge bar (with conflicts)
843 843
844 844
845 845 $ hg rm aa
846 846 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
847 847 $ hg log --config diff.git=1 -pr .
848 848 changeset: 29:1205ed810051
849 849 tag: tip
850 850 parent: 27:4b216ca5ba97
851 851 parent: 26:67db8847a540
852 852 user: test
853 853 date: Thu Jan 01 00:00:00 1970 +0000
854 854 summary: merge bar (with conflicts, amended)
855 855
856 856 diff --git a/aa b/aa
857 857 deleted file mode 100644
858 858 --- a/aa
859 859 +++ /dev/null
860 860 @@ -1,4 +0,0 @@
861 861 -a
862 862 -a
863 863 -aa
864 864 -aa
865 865
866 866 Issue 3445: amending with --close-branch a commit that created a new head should fail
867 867 This shouldn't be possible:
868 868
869 869 $ hg up -q default
870 870 $ hg branch closewithamend
871 871 marked working directory as branch closewithamend
872 872 $ echo foo > foo
873 873 $ hg add foo
874 874 $ hg ci -m..
875 875 $ hg ci --amend --close-branch -m 'closing'
876 876 abort: can only close branch heads
877 877 [255]
878 878
879 879 This silliness fails:
880 880
881 881 $ hg branch silliness
882 882 marked working directory as branch silliness
883 883 $ echo b >> b
884 884 $ hg ci --close-branch -m'open and close'
885 885 abort: can only close branch heads
886 886 [255]
887 887
888 888 Test that amend with --secret creates new secret changeset forcibly
889 889 ---------------------------------------------------------------------
890 890
891 891 $ hg phase '.^::.'
892 892 29: draft
893 893 30: draft
894 894 $ hg commit --amend --secret -m 'amend as secret' -q
895 895 $ hg phase '.^::.'
896 896 29: draft
897 897 31: secret
898 898
899 899 Test that amend with --edit invokes editor forcibly
900 900 ---------------------------------------------------
901 901
902 902 $ hg parents --template "{desc}\n"
903 903 amend as secret
904 904 $ HGEDITOR=cat hg commit --amend -m "editor should be suppressed"
905 905 $ hg parents --template "{desc}\n"
906 906 editor should be suppressed
907 907
908 908 $ hg status --rev '.^1::.'
909 909 A foo
910 910 $ HGEDITOR=cat hg commit --amend -m "editor should be invoked" --edit
911 911 editor should be invoked
912 912
913 913
914 914 HG: Enter commit message. Lines beginning with 'HG:' are removed.
915 915 HG: Leave message empty to abort commit.
916 916 HG: --
917 917 HG: user: test
918 918 HG: branch 'silliness'
919 919 HG: added foo
920 920 $ hg parents --template "{desc}\n"
921 921 editor should be invoked
922 922
923 923 Test that "diff()" in committemplate works correctly for amending
924 924 -----------------------------------------------------------------
925 925
926 926 $ cat >> .hg/hgrc <<EOF
927 927 > [committemplate]
928 928 > changeset.commit.amend = {desc}\n
929 929 > HG: M: {file_mods}
930 930 > HG: A: {file_adds}
931 931 > HG: R: {file_dels}
932 932 > {splitlines(diff()) % 'HG: {line}\n'}
933 933 > EOF
934 934
935 935 $ hg parents --template "M: {file_mods}\nA: {file_adds}\nR: {file_dels}\n"
936 936 M:
937 937 A: foo
938 938 R:
939 939 $ hg status -amr
940 940 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo"
941 941 expecting diff of foo
942 942
943 943 HG: M:
944 944 HG: A: foo
945 945 HG: R:
946 946 HG: diff -r 1205ed810051 foo
947 947 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
948 948 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
949 949 HG: @@ -0,0 +1,1 @@
950 950 HG: +foo
951 951
952 952 $ echo y > y
953 953 $ hg add y
954 954 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo and y"
955 955 expecting diff of foo and y
956 956
957 957 HG: M:
958 958 HG: A: foo y
959 959 HG: R:
960 960 HG: diff -r 1205ed810051 foo
961 961 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
962 962 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
963 963 HG: @@ -0,0 +1,1 @@
964 964 HG: +foo
965 965 HG: diff -r 1205ed810051 y
966 966 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
967 967 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
968 968 HG: @@ -0,0 +1,1 @@
969 969 HG: +y
970 970
971 971 $ hg rm a
972 972 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo and y"
973 973 expecting diff of a, foo and y
974 974
975 975 HG: M:
976 976 HG: A: foo y
977 977 HG: R: a
978 978 HG: diff -r 1205ed810051 a
979 979 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
980 980 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
981 981 HG: @@ -1,2 +0,0 @@
982 982 HG: -a
983 983 HG: -a
984 984 HG: diff -r 1205ed810051 foo
985 985 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
986 986 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
987 987 HG: @@ -0,0 +1,1 @@
988 988 HG: +foo
989 989 HG: diff -r 1205ed810051 y
990 990 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
991 991 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
992 992 HG: @@ -0,0 +1,1 @@
993 993 HG: +y
994 994
995 995 $ hg rm x
996 996 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo, x and y"
997 997 expecting diff of a, foo, x and y
998 998
999 999 HG: M:
1000 1000 HG: A: foo y
1001 1001 HG: R: a x
1002 1002 HG: diff -r 1205ed810051 a
1003 1003 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
1004 1004 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1005 1005 HG: @@ -1,2 +0,0 @@
1006 1006 HG: -a
1007 1007 HG: -a
1008 1008 HG: diff -r 1205ed810051 foo
1009 1009 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1010 1010 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
1011 1011 HG: @@ -0,0 +1,1 @@
1012 1012 HG: +foo
1013 1013 HG: diff -r 1205ed810051 x
1014 1014 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
1015 1015 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1016 1016 HG: @@ -1,1 +0,0 @@
1017 1017 HG: -x
1018 1018 HG: diff -r 1205ed810051 y
1019 1019 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1020 1020 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1021 1021 HG: @@ -0,0 +1,1 @@
1022 1022 HG: +y
1023 1023
1024 1024 $ echo cccc >> cc
1025 1025 $ hg status -amr
1026 1026 M cc
1027 1027 $ HGEDITOR=cat hg commit --amend -e -m "cc should be excluded" -X cc
1028 1028 cc should be excluded
1029 1029
1030 1030 HG: M:
1031 1031 HG: A: foo y
1032 1032 HG: R: a x
1033 1033 HG: diff -r 1205ed810051 a
1034 1034 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
1035 1035 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1036 1036 HG: @@ -1,2 +0,0 @@
1037 1037 HG: -a
1038 1038 HG: -a
1039 1039 HG: diff -r 1205ed810051 foo
1040 1040 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1041 1041 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
1042 1042 HG: @@ -0,0 +1,1 @@
1043 1043 HG: +foo
1044 1044 HG: diff -r 1205ed810051 x
1045 1045 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
1046 1046 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1047 1047 HG: @@ -1,1 +0,0 @@
1048 1048 HG: -x
1049 1049 HG: diff -r 1205ed810051 y
1050 1050 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1051 1051 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1052 1052 HG: @@ -0,0 +1,1 @@
1053 1053 HG: +y
1054 1054
1055 1055 Check for issue4405
1056 1056 -------------------
1057 1057
1058 1058 Setup the repo with a file that gets moved in a second commit.
1059 1059 $ hg init repo
1060 1060 $ cd repo
1061 1061 $ touch a0
1062 1062 $ hg add a0
1063 1063 $ hg commit -m a0
1064 1064 $ hg mv a0 a1
1065 1065 $ hg commit -m a1
1066 1066 $ hg up -q 0
1067 1067 $ hg log -G --template '{rev} {desc}'
1068 1068 o 1 a1
1069 1069 |
1070 1070 @ 0 a0
1071 1071
1072 1072
1073 1073 Now we branch the repro, but re-use the file contents, so we have a divergence
1074 1074 in the file revlog topology and the changelog topology.
1075 1075 $ hg revert --rev 1 --all
1076 1076 removing a0
1077 1077 adding a1
1078 1078 $ hg ci -qm 'a1-amend'
1079 1079 $ hg log -G --template '{rev} {desc}'
1080 1080 @ 2 a1-amend
1081 1081 |
1082 1082 | o 1 a1
1083 1083 |/
1084 1084 o 0 a0
1085 1085
1086 1086
1087 1087 The way mercurial does amends is by folding the working copy and old commit
1088 1088 together into another commit (rev 3). During this process, _findlimit is called
1089 1089 to check how far back to look for the transitive closure of file copy
1090 1090 information, but due to the divergence of the filelog and changelog graph
1091 1091 topologies, before _findlimit was fixed, it returned a rev which was not far
1092 1092 enough back in this case.
1093 1093 $ hg mv a1 a2
1094 1094 $ hg status --copies --rev 0
1095 1095 A a2
1096 1096 a0
1097 1097 R a0
1098 1098 $ hg ci --amend -q
1099 1099 $ hg log -G --template '{rev} {desc}'
1100 1100 @ 3 a1-amend
1101 1101 |
1102 1102 | o 1 a1
1103 1103 |/
1104 1104 o 0 a0
1105 1105
1106 1106
1107 1107 Before the fix, the copy information was lost.
1108 1108 $ hg status --copies --rev 0
1109 1109 A a2
1110 1110 a0
1111 1111 R a0
1112 1112 $ cd ..
1113 1113
1114 1114 Check that amend properly preserve rename from directory rename (issue-4516)
1115 1115
1116 1116 If a parent of the merge renames a full directory, any files added to the old
1117 1117 directory in the other parent will be renamed to the new directory. For some
1118 1118 reason, the rename metadata was when amending such merge. This test ensure we
1119 1119 do not regress. We have a dedicated repo because it needs a setup with renamed
1120 1120 directory)
1121 1121
1122 1122 $ hg init issue4516
1123 1123 $ cd issue4516
1124 1124 $ mkdir olddirname
1125 1125 $ echo line1 > olddirname/commonfile.py
1126 1126 $ hg add olddirname/commonfile.py
1127 1127 $ hg ci -m first
1128 1128
1129 1129 $ hg branch newdirname
1130 1130 marked working directory as branch newdirname
1131 1131 (branches are permanent and global, did you want a bookmark?)
1132 1132 $ hg mv olddirname newdirname
1133 1133 moving olddirname/commonfile.py to newdirname/commonfile.py
1134 1134 $ hg ci -m rename
1135 1135
1136 1136 $ hg update default
1137 1137 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1138 1138 $ echo line1 > olddirname/newfile.py
1139 1139 $ hg add olddirname/newfile.py
1140 1140 $ hg ci -m log
1141 1141
1142 1142 $ hg up newdirname
1143 1143 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1144 1144 $ # create newdirname/newfile.py
1145 1145 $ hg merge default
1146 1146 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1147 1147 (branch merge, don't forget to commit)
1148 1148 $ hg ci -m add
1149 1149 $
1150 1150 $ hg debugrename newdirname/newfile.py
1151 1151 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def
1152 1152 $ hg status -C --change .
1153 1153 A newdirname/newfile.py
1154 1154 $ hg status -C --rev 1
1155 1155 A newdirname/newfile.py
1156 1156 $ hg status -C --rev 2
1157 1157 A newdirname/commonfile.py
1158 1158 olddirname/commonfile.py
1159 1159 A newdirname/newfile.py
1160 1160 olddirname/newfile.py
1161 1161 R olddirname/commonfile.py
1162 1162 R olddirname/newfile.py
1163 1163 $ hg debugindex newdirname/newfile.py
1164 rev offset length linkrev nodeid p1 p2
1165 0 0 89 3 34a4d536c0c0 000000000000 000000000000
1164 rev linkrev nodeid p1 p2
1165 0 3 34a4d536c0c0 000000000000 000000000000
1166 1166
1167 1167 $ echo a >> newdirname/commonfile.py
1168 1168 $ hg ci --amend -m bug
1169 1169 $ hg debugrename newdirname/newfile.py
1170 1170 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def
1171 1171 $ hg debugindex newdirname/newfile.py
1172 rev offset length linkrev nodeid p1 p2
1173 0 0 89 3 34a4d536c0c0 000000000000 000000000000
1172 rev linkrev nodeid p1 p2
1173 0 3 34a4d536c0c0 000000000000 000000000000
1174 1174
1175 1175 #if execbit
1176 1176
1177 1177 Test if amend preserves executable bit changes
1178 1178 $ chmod +x newdirname/commonfile.py
1179 1179 $ hg ci -m chmod
1180 1180 $ hg ci --amend -m "chmod amended"
1181 1181 $ hg ci --amend -m "chmod amended second time"
1182 1182 $ hg log -p --git -r .
1183 1183 changeset: 7:b1326f52dddf
1184 1184 branch: newdirname
1185 1185 tag: tip
1186 1186 parent: 4:7fd235f7cb2f
1187 1187 user: test
1188 1188 date: Thu Jan 01 00:00:00 1970 +0000
1189 1189 summary: chmod amended second time
1190 1190
1191 1191 diff --git a/newdirname/commonfile.py b/newdirname/commonfile.py
1192 1192 old mode 100644
1193 1193 new mode 100755
1194 1194
1195 1195 #endif
1196 1196
1197 1197 Test amend with file inclusion options
1198 1198 --------------------------------------
1199 1199
1200 1200 These tests ensure that we are always amending some files that were part of the
1201 1201 pre-amend commit. We want to test that the remaining files in the pre-amend
1202 1202 commit were not changed in the amended commit. We do so by performing a diff of
1203 1203 the amended commit against its parent commit.
1204 1204 $ cd ..
1205 1205 $ hg init testfileinclusions
1206 1206 $ cd testfileinclusions
1207 1207 $ echo a > a
1208 1208 $ echo b > b
1209 1209 $ hg commit -Aqm "Adding a and b"
1210 1210
1211 1211 Only add changes to a particular file
1212 1212 $ echo a >> a
1213 1213 $ echo b >> b
1214 1214 $ hg commit --amend -I a
1215 1215 $ hg diff --git -r null -r .
1216 1216 diff --git a/a b/a
1217 1217 new file mode 100644
1218 1218 --- /dev/null
1219 1219 +++ b/a
1220 1220 @@ -0,0 +1,2 @@
1221 1221 +a
1222 1222 +a
1223 1223 diff --git a/b b/b
1224 1224 new file mode 100644
1225 1225 --- /dev/null
1226 1226 +++ b/b
1227 1227 @@ -0,0 +1,1 @@
1228 1228 +b
1229 1229
1230 1230 $ echo a >> a
1231 1231 $ hg commit --amend b
1232 1232 $ hg diff --git -r null -r .
1233 1233 diff --git a/a b/a
1234 1234 new file mode 100644
1235 1235 --- /dev/null
1236 1236 +++ b/a
1237 1237 @@ -0,0 +1,2 @@
1238 1238 +a
1239 1239 +a
1240 1240 diff --git a/b b/b
1241 1241 new file mode 100644
1242 1242 --- /dev/null
1243 1243 +++ b/b
1244 1244 @@ -0,0 +1,2 @@
1245 1245 +b
1246 1246 +b
1247 1247
1248 1248 Exclude changes to a particular file
1249 1249 $ echo b >> b
1250 1250 $ hg commit --amend -X a
1251 1251 $ hg diff --git -r null -r .
1252 1252 diff --git a/a b/a
1253 1253 new file mode 100644
1254 1254 --- /dev/null
1255 1255 +++ b/a
1256 1256 @@ -0,0 +1,2 @@
1257 1257 +a
1258 1258 +a
1259 1259 diff --git a/b b/b
1260 1260 new file mode 100644
1261 1261 --- /dev/null
1262 1262 +++ b/b
1263 1263 @@ -0,0 +1,3 @@
1264 1264 +b
1265 1265 +b
1266 1266 +b
1267 1267
1268 1268 Check the addremove flag
1269 1269 $ echo c > c
1270 1270 $ rm a
1271 1271 $ hg commit --amend -A
1272 1272 removing a
1273 1273 adding c
1274 1274 $ hg diff --git -r null -r .
1275 1275 diff --git a/b b/b
1276 1276 new file mode 100644
1277 1277 --- /dev/null
1278 1278 +++ b/b
1279 1279 @@ -0,0 +1,3 @@
1280 1280 +b
1281 1281 +b
1282 1282 +b
1283 1283 diff --git a/c b/c
1284 1284 new file mode 100644
1285 1285 --- /dev/null
1286 1286 +++ b/c
1287 1287 @@ -0,0 +1,1 @@
1288 1288 +c
@@ -1,833 +1,833 b''
1 1 commit date test
2 2
3 3 $ hg init test
4 4 $ cd test
5 5 $ echo foo > foo
6 6 $ hg add foo
7 7 $ cat > $TESTTMP/checkeditform.sh <<EOF
8 8 > env | grep HGEDITFORM
9 9 > true
10 10 > EOF
11 11 $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg commit -m ""
12 12 HGEDITFORM=commit.normal.normal
13 13 abort: empty commit message
14 14 [255]
15 15 $ hg commit -d '0 0' -m commit-1
16 16 $ echo foo >> foo
17 17 $ hg commit -d '1 4444444' -m commit-3
18 18 hg: parse error: impossible time zone offset: 4444444
19 19 [255]
20 20 $ hg commit -d '1 15.1' -m commit-4
21 21 hg: parse error: invalid date: '1\t15.1'
22 22 [255]
23 23 $ hg commit -d 'foo bar' -m commit-5
24 24 hg: parse error: invalid date: 'foo bar'
25 25 [255]
26 26 $ hg commit -d ' 1 4444' -m commit-6
27 27 $ hg commit -d '111111111111 0' -m commit-7
28 28 hg: parse error: date exceeds 32 bits: 111111111111
29 29 [255]
30 30 $ hg commit -d '-111111111111 0' -m commit-7
31 31 hg: parse error: date exceeds 32 bits: -111111111111
32 32 [255]
33 33 $ echo foo >> foo
34 34 $ hg commit -d '1901-12-13 20:45:52 +0000' -m commit-7-2
35 35 $ echo foo >> foo
36 36 $ hg commit -d '-2147483648 0' -m commit-7-3
37 37 $ hg log -T '{rev} {date|isodatesec}\n' -l2
38 38 3 1901-12-13 20:45:52 +0000
39 39 2 1901-12-13 20:45:52 +0000
40 40 $ hg commit -d '1901-12-13 20:45:51 +0000' -m commit-7
41 41 hg: parse error: date exceeds 32 bits: -2147483649
42 42 [255]
43 43 $ hg commit -d '-2147483649 0' -m commit-7
44 44 hg: parse error: date exceeds 32 bits: -2147483649
45 45 [255]
46 46
47 47 commit added file that has been deleted
48 48
49 49 $ echo bar > bar
50 50 $ hg add bar
51 51 $ rm bar
52 52 $ hg commit -m commit-8
53 53 nothing changed (1 missing files, see 'hg status')
54 54 [1]
55 55 $ hg commit -m commit-8-2 bar
56 56 abort: bar: file not found!
57 57 [255]
58 58
59 59 $ hg -q revert -a --no-backup
60 60
61 61 $ mkdir dir
62 62 $ echo boo > dir/file
63 63 $ hg add
64 64 adding dir/file
65 65 $ hg -v commit -m commit-9 dir
66 66 committing files:
67 67 dir/file
68 68 committing manifest
69 69 committing changelog
70 70 committed changeset 4:1957363f1ced
71 71
72 72 $ echo > dir.file
73 73 $ hg add
74 74 adding dir.file
75 75 $ hg commit -m commit-10 dir dir.file
76 76 abort: dir: no match under directory!
77 77 [255]
78 78
79 79 $ echo >> dir/file
80 80 $ mkdir bleh
81 81 $ mkdir dir2
82 82 $ cd bleh
83 83 $ hg commit -m commit-11 .
84 84 abort: bleh: no match under directory!
85 85 [255]
86 86 $ hg commit -m commit-12 ../dir ../dir2
87 87 abort: dir2: no match under directory!
88 88 [255]
89 89 $ hg -v commit -m commit-13 ../dir
90 90 committing files:
91 91 dir/file
92 92 committing manifest
93 93 committing changelog
94 94 committed changeset 5:a31d8f87544a
95 95 $ cd ..
96 96
97 97 $ hg commit -m commit-14 does-not-exist
98 98 abort: does-not-exist: * (glob)
99 99 [255]
100 100
101 101 #if symlink
102 102 $ ln -s foo baz
103 103 $ hg commit -m commit-15 baz
104 104 abort: baz: file not tracked!
105 105 [255]
106 106 $ rm baz
107 107 #endif
108 108
109 109 $ touch quux
110 110 $ hg commit -m commit-16 quux
111 111 abort: quux: file not tracked!
112 112 [255]
113 113 $ echo >> dir/file
114 114 $ hg -v commit -m commit-17 dir/file
115 115 committing files:
116 116 dir/file
117 117 committing manifest
118 118 committing changelog
119 119 committed changeset 6:32d054c9d085
120 120
121 121 An empty date was interpreted as epoch origin
122 122
123 123 $ echo foo >> foo
124 124 $ hg commit -d '' -m commit-no-date --config devel.default-date=
125 125 $ hg tip --template '{date|isodate}\n' | grep '1970'
126 126 [1]
127 127
128 128 Using the advanced --extra flag
129 129
130 130 $ echo "[extensions]" >> $HGRCPATH
131 131 $ echo "commitextras=" >> $HGRCPATH
132 132 $ hg status
133 133 ? quux
134 134 $ hg add quux
135 135 $ hg commit -m "adding internal used extras" --extra amend_source=hash
136 136 abort: key 'amend_source' is used internally, can't be set manually
137 137 [255]
138 138 $ hg commit -m "special chars in extra" --extra id@phab=214
139 139 abort: keys can only contain ascii letters, digits, '_' and '-'
140 140 [255]
141 141 $ hg commit -m "empty key" --extra =value
142 142 abort: unable to parse '=value', keys can't be empty
143 143 [255]
144 144 $ hg commit -m "adding extras" --extra sourcehash=foo --extra oldhash=bar
145 145 $ hg log -r . -T '{extras % "{extra}\n"}'
146 146 branch=default
147 147 oldhash=bar
148 148 sourcehash=foo
149 149
150 150 Failed commit with --addremove should not update dirstate
151 151
152 152 $ echo foo > newfile
153 153 $ hg status
154 154 ? newfile
155 155 $ HGEDITOR=false hg ci --addremove
156 156 adding newfile
157 157 abort: edit failed: false exited with status 1
158 158 [255]
159 159 $ hg status
160 160 ? newfile
161 161
162 162 Make sure we do not obscure unknown requires file entries (issue2649)
163 163
164 164 $ echo foo >> foo
165 165 $ echo fake >> .hg/requires
166 166 $ hg commit -m bla
167 167 abort: repository requires features unknown to this Mercurial: fake!
168 168 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
169 169 [255]
170 170
171 171 $ cd ..
172 172
173 173
174 174 partial subdir commit test
175 175
176 176 $ hg init test2
177 177 $ cd test2
178 178 $ mkdir foo
179 179 $ echo foo > foo/foo
180 180 $ mkdir bar
181 181 $ echo bar > bar/bar
182 182 $ hg add
183 183 adding bar/bar
184 184 adding foo/foo
185 185 $ HGEDITOR=cat hg ci -e -m commit-subdir-1 foo
186 186 commit-subdir-1
187 187
188 188
189 189 HG: Enter commit message. Lines beginning with 'HG:' are removed.
190 190 HG: Leave message empty to abort commit.
191 191 HG: --
192 192 HG: user: test
193 193 HG: branch 'default'
194 194 HG: added foo/foo
195 195
196 196
197 197 $ hg ci -m commit-subdir-2 bar
198 198
199 199 subdir log 1
200 200
201 201 $ hg log -v foo
202 202 changeset: 0:f97e73a25882
203 203 user: test
204 204 date: Thu Jan 01 00:00:00 1970 +0000
205 205 files: foo/foo
206 206 description:
207 207 commit-subdir-1
208 208
209 209
210 210
211 211 subdir log 2
212 212
213 213 $ hg log -v bar
214 214 changeset: 1:aa809156d50d
215 215 tag: tip
216 216 user: test
217 217 date: Thu Jan 01 00:00:00 1970 +0000
218 218 files: bar/bar
219 219 description:
220 220 commit-subdir-2
221 221
222 222
223 223
224 224 full log
225 225
226 226 $ hg log -v
227 227 changeset: 1:aa809156d50d
228 228 tag: tip
229 229 user: test
230 230 date: Thu Jan 01 00:00:00 1970 +0000
231 231 files: bar/bar
232 232 description:
233 233 commit-subdir-2
234 234
235 235
236 236 changeset: 0:f97e73a25882
237 237 user: test
238 238 date: Thu Jan 01 00:00:00 1970 +0000
239 239 files: foo/foo
240 240 description:
241 241 commit-subdir-1
242 242
243 243
244 244 $ cd ..
245 245
246 246
247 247 dot and subdir commit test
248 248
249 249 $ hg init test3
250 250 $ echo commit-foo-subdir > commit-log-test
251 251 $ cd test3
252 252 $ mkdir foo
253 253 $ echo foo content > foo/plain-file
254 254 $ hg add foo/plain-file
255 255 $ HGEDITOR=cat hg ci --edit -l ../commit-log-test foo
256 256 commit-foo-subdir
257 257
258 258
259 259 HG: Enter commit message. Lines beginning with 'HG:' are removed.
260 260 HG: Leave message empty to abort commit.
261 261 HG: --
262 262 HG: user: test
263 263 HG: branch 'default'
264 264 HG: added foo/plain-file
265 265
266 266
267 267 $ echo modified foo content > foo/plain-file
268 268 $ hg ci -m commit-foo-dot .
269 269
270 270 full log
271 271
272 272 $ hg log -v
273 273 changeset: 1:95b38e3a5b2e
274 274 tag: tip
275 275 user: test
276 276 date: Thu Jan 01 00:00:00 1970 +0000
277 277 files: foo/plain-file
278 278 description:
279 279 commit-foo-dot
280 280
281 281
282 282 changeset: 0:65d4e9386227
283 283 user: test
284 284 date: Thu Jan 01 00:00:00 1970 +0000
285 285 files: foo/plain-file
286 286 description:
287 287 commit-foo-subdir
288 288
289 289
290 290
291 291 subdir log
292 292
293 293 $ cd foo
294 294 $ hg log .
295 295 changeset: 1:95b38e3a5b2e
296 296 tag: tip
297 297 user: test
298 298 date: Thu Jan 01 00:00:00 1970 +0000
299 299 summary: commit-foo-dot
300 300
301 301 changeset: 0:65d4e9386227
302 302 user: test
303 303 date: Thu Jan 01 00:00:00 1970 +0000
304 304 summary: commit-foo-subdir
305 305
306 306 $ cd ..
307 307 $ cd ..
308 308
309 309 Issue1049: Hg permits partial commit of merge without warning
310 310
311 311 $ hg init issue1049
312 312 $ cd issue1049
313 313 $ echo a > a
314 314 $ hg ci -Ama
315 315 adding a
316 316 $ echo a >> a
317 317 $ hg ci -mb
318 318 $ hg up 0
319 319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
320 320 $ echo b >> a
321 321 $ hg ci -mc
322 322 created new head
323 323 $ HGMERGE=true hg merge
324 324 merging a
325 325 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
326 326 (branch merge, don't forget to commit)
327 327
328 328 should fail because we are specifying a file name
329 329
330 330 $ hg ci -mmerge a
331 331 abort: cannot partially commit a merge (do not specify files or patterns)
332 332 [255]
333 333
334 334 should fail because we are specifying a pattern
335 335
336 336 $ hg ci -mmerge -I a
337 337 abort: cannot partially commit a merge (do not specify files or patterns)
338 338 [255]
339 339
340 340 should succeed
341 341
342 342 $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg ci -mmerge --edit
343 343 HGEDITFORM=commit.normal.merge
344 344 $ cd ..
345 345
346 346
347 347 test commit message content
348 348
349 349 $ hg init commitmsg
350 350 $ cd commitmsg
351 351 $ echo changed > changed
352 352 $ echo removed > removed
353 353 $ hg book activebookmark
354 354 $ hg ci -qAm init
355 355
356 356 $ hg rm removed
357 357 $ echo changed >> changed
358 358 $ echo added > added
359 359 $ hg add added
360 360 $ HGEDITOR=cat hg ci -A
361 361
362 362
363 363 HG: Enter commit message. Lines beginning with 'HG:' are removed.
364 364 HG: Leave message empty to abort commit.
365 365 HG: --
366 366 HG: user: test
367 367 HG: branch 'default'
368 368 HG: bookmark 'activebookmark'
369 369 HG: added added
370 370 HG: changed changed
371 371 HG: removed removed
372 372 abort: empty commit message
373 373 [255]
374 374
375 375 test saving last-message.txt
376 376
377 377 $ hg init sub
378 378 $ echo a > sub/a
379 379 $ hg -R sub add sub/a
380 380 $ cat > sub/.hg/hgrc <<EOF
381 381 > [hooks]
382 382 > precommit.test-saving-last-message = false
383 383 > EOF
384 384
385 385 $ echo 'sub = sub' > .hgsub
386 386 $ hg add .hgsub
387 387
388 388 $ cat > $TESTTMP/editor.sh <<EOF
389 389 > echo "==== before editing:"
390 390 > cat \$1
391 391 > echo "===="
392 392 > echo "test saving last-message.txt" >> \$1
393 393 > EOF
394 394
395 395 $ rm -f .hg/last-message.txt
396 396 $ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -S -q
397 397 ==== before editing:
398 398
399 399
400 400 HG: Enter commit message. Lines beginning with 'HG:' are removed.
401 401 HG: Leave message empty to abort commit.
402 402 HG: --
403 403 HG: user: test
404 404 HG: branch 'default'
405 405 HG: bookmark 'activebookmark'
406 406 HG: subrepo sub
407 407 HG: added .hgsub
408 408 HG: added added
409 409 HG: changed .hgsubstate
410 410 HG: changed changed
411 411 HG: removed removed
412 412 ====
413 413 abort: precommit.test-saving-last-message hook exited with status 1 (in subrepository "sub")
414 414 [255]
415 415 $ cat .hg/last-message.txt
416 416
417 417
418 418 test saving last-message.txt
419 419
420 420 test that '[committemplate] changeset' definition and commit log
421 421 specific template keywords work well
422 422
423 423 $ cat >> .hg/hgrc <<EOF
424 424 > [committemplate]
425 425 > changeset.commit.normal = 'HG: this is "commit.normal" template
426 426 > HG: {extramsg}
427 427 > {if(activebookmark,
428 428 > "HG: bookmark '{activebookmark}' is activated\n",
429 429 > "HG: no bookmark is activated\n")}{subrepos %
430 430 > "HG: subrepo '{subrepo}' is changed\n"}'
431 431 >
432 432 > changeset.commit = HG: this is "commit" template
433 433 > HG: {extramsg}
434 434 > {if(activebookmark,
435 435 > "HG: bookmark '{activebookmark}' is activated\n",
436 436 > "HG: no bookmark is activated\n")}{subrepos %
437 437 > "HG: subrepo '{subrepo}' is changed\n"}
438 438 >
439 439 > changeset = HG: this is customized commit template
440 440 > HG: {extramsg}
441 441 > {if(activebookmark,
442 442 > "HG: bookmark '{activebookmark}' is activated\n",
443 443 > "HG: no bookmark is activated\n")}{subrepos %
444 444 > "HG: subrepo '{subrepo}' is changed\n"}
445 445 > EOF
446 446
447 447 $ hg init sub2
448 448 $ echo a > sub2/a
449 449 $ hg -R sub2 add sub2/a
450 450 $ echo 'sub2 = sub2' >> .hgsub
451 451
452 452 $ HGEDITOR=cat hg commit -S -q
453 453 HG: this is "commit.normal" template
454 454 HG: Leave message empty to abort commit.
455 455 HG: bookmark 'activebookmark' is activated
456 456 HG: subrepo 'sub' is changed
457 457 HG: subrepo 'sub2' is changed
458 458 abort: empty commit message
459 459 [255]
460 460
461 461 $ cat >> .hg/hgrc <<EOF
462 462 > [committemplate]
463 463 > changeset.commit.normal =
464 464 > # now, "changeset.commit" should be chosen for "hg commit"
465 465 > EOF
466 466
467 467 $ hg bookmark --inactive activebookmark
468 468 $ hg forget .hgsub
469 469 $ HGEDITOR=cat hg commit -q
470 470 HG: this is "commit" template
471 471 HG: Leave message empty to abort commit.
472 472 HG: no bookmark is activated
473 473 abort: empty commit message
474 474 [255]
475 475
476 476 $ cat >> .hg/hgrc <<EOF
477 477 > [committemplate]
478 478 > changeset.commit =
479 479 > # now, "changeset" should be chosen for "hg commit"
480 480 > EOF
481 481
482 482 $ HGEDITOR=cat hg commit -q
483 483 HG: this is customized commit template
484 484 HG: Leave message empty to abort commit.
485 485 HG: no bookmark is activated
486 486 abort: empty commit message
487 487 [255]
488 488
489 489 $ cat >> .hg/hgrc <<EOF
490 490 > [committemplate]
491 491 > changeset = {desc}
492 492 > HG: mods={file_mods}
493 493 > HG: adds={file_adds}
494 494 > HG: dels={file_dels}
495 495 > HG: files={files}
496 496 > HG:
497 497 > {splitlines(diff()) % 'HG: {line}\n'
498 498 > }HG:
499 499 > HG: mods={file_mods}
500 500 > HG: adds={file_adds}
501 501 > HG: dels={file_dels}
502 502 > HG: files={files}\n
503 503 > EOF
504 504 $ hg status -amr
505 505 M changed
506 506 A added
507 507 R removed
508 508 $ HGEDITOR=cat hg commit -q -e -m "foo bar" changed
509 509 foo bar
510 510 HG: mods=changed
511 511 HG: adds=
512 512 HG: dels=
513 513 HG: files=changed
514 514 HG:
515 515 HG: --- a/changed Thu Jan 01 00:00:00 1970 +0000
516 516 HG: +++ b/changed Thu Jan 01 00:00:00 1970 +0000
517 517 HG: @@ -1,1 +1,2 @@
518 518 HG: changed
519 519 HG: +changed
520 520 HG:
521 521 HG: mods=changed
522 522 HG: adds=
523 523 HG: dels=
524 524 HG: files=changed
525 525 $ hg status -amr
526 526 A added
527 527 R removed
528 528 $ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
529 529 M changed
530 530 A
531 531 R
532 532 $ hg rollback -q
533 533
534 534 $ cat >> .hg/hgrc <<EOF
535 535 > [committemplate]
536 536 > changeset = {desc}
537 537 > HG: mods={file_mods}
538 538 > HG: adds={file_adds}
539 539 > HG: dels={file_dels}
540 540 > HG: files={files}
541 541 > HG:
542 542 > {splitlines(diff("changed")) % 'HG: {line}\n'
543 543 > }HG:
544 544 > HG: mods={file_mods}
545 545 > HG: adds={file_adds}
546 546 > HG: dels={file_dels}
547 547 > HG: files={files}
548 548 > HG:
549 549 > {splitlines(diff("added")) % 'HG: {line}\n'
550 550 > }HG:
551 551 > HG: mods={file_mods}
552 552 > HG: adds={file_adds}
553 553 > HG: dels={file_dels}
554 554 > HG: files={files}
555 555 > HG:
556 556 > {splitlines(diff("removed")) % 'HG: {line}\n'
557 557 > }HG:
558 558 > HG: mods={file_mods}
559 559 > HG: adds={file_adds}
560 560 > HG: dels={file_dels}
561 561 > HG: files={files}\n
562 562 > EOF
563 563 $ HGEDITOR=cat hg commit -q -e -m "foo bar" added removed
564 564 foo bar
565 565 HG: mods=
566 566 HG: adds=added
567 567 HG: dels=removed
568 568 HG: files=added removed
569 569 HG:
570 570 HG:
571 571 HG: mods=
572 572 HG: adds=added
573 573 HG: dels=removed
574 574 HG: files=added removed
575 575 HG:
576 576 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
577 577 HG: +++ b/added Thu Jan 01 00:00:00 1970 +0000
578 578 HG: @@ -0,0 +1,1 @@
579 579 HG: +added
580 580 HG:
581 581 HG: mods=
582 582 HG: adds=added
583 583 HG: dels=removed
584 584 HG: files=added removed
585 585 HG:
586 586 HG: --- a/removed Thu Jan 01 00:00:00 1970 +0000
587 587 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
588 588 HG: @@ -1,1 +0,0 @@
589 589 HG: -removed
590 590 HG:
591 591 HG: mods=
592 592 HG: adds=added
593 593 HG: dels=removed
594 594 HG: files=added removed
595 595 $ hg status -amr
596 596 M changed
597 597 $ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
598 598 M
599 599 A added
600 600 R removed
601 601 $ hg rollback -q
602 602
603 603 $ cat >> .hg/hgrc <<EOF
604 604 > # disable customizing for subsequent tests
605 605 > [committemplate]
606 606 > changeset =
607 607 > EOF
608 608
609 609 $ cd ..
610 610
611 611
612 612 commit copy
613 613
614 614 $ hg init dir2
615 615 $ cd dir2
616 616 $ echo bleh > bar
617 617 $ hg add bar
618 618 $ hg ci -m 'add bar'
619 619
620 620 $ hg cp bar foo
621 621 $ echo >> bar
622 622 $ hg ci -m 'cp bar foo; change bar'
623 623
624 624 $ hg debugrename foo
625 625 foo renamed from bar:26d3ca0dfd18e44d796b564e38dd173c9668d3a9
626 626 $ hg debugindex bar
627 rev offset length linkrev nodeid p1 p2
628 0 0 6 0 26d3ca0dfd18 000000000000 000000000000
629 1 6 7 1 d267bddd54f7 26d3ca0dfd18 000000000000
627 rev linkrev nodeid p1 p2
628 0 0 26d3ca0dfd18 000000000000 000000000000
629 1 1 d267bddd54f7 26d3ca0dfd18 000000000000
630 630
631 631 Test making empty commits
632 632 $ hg commit --config ui.allowemptycommit=True -m "empty commit"
633 633 $ hg log -r . -v --stat
634 634 changeset: 2:d809f3644287
635 635 tag: tip
636 636 user: test
637 637 date: Thu Jan 01 00:00:00 1970 +0000
638 638 description:
639 639 empty commit
640 640
641 641
642 642
643 643 verify pathauditor blocks evil filepaths
644 644 $ cat > evil-commit.py <<EOF
645 645 > from __future__ import absolute_import
646 646 > from mercurial import context, hg, node, ui as uimod
647 647 > notrc = u".h\u200cg".encode('utf-8') + b'/hgrc'
648 648 > u = uimod.ui.load()
649 649 > r = hg.repository(u, b'.')
650 650 > def filectxfn(repo, memctx, path):
651 651 > return context.memfilectx(repo, memctx, path,
652 652 > b'[hooks]\nupdate = echo owned')
653 653 > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
654 654 > b'evil', [notrc], filectxfn, 0)
655 655 > r.commitctx(c)
656 656 > EOF
657 657 $ $PYTHON evil-commit.py
658 658 #if windows
659 659 $ hg co --clean tip
660 660 abort: path contains illegal component: .h\xe2\x80\x8cg\\hgrc (esc)
661 661 [255]
662 662 #else
663 663 $ hg co --clean tip
664 664 abort: path contains illegal component: .h\xe2\x80\x8cg/hgrc (esc)
665 665 [255]
666 666 #endif
667 667
668 668 $ hg rollback -f
669 669 repository tip rolled back to revision 2 (undo commit)
670 670 $ cat > evil-commit.py <<EOF
671 671 > from __future__ import absolute_import
672 672 > from mercurial import context, hg, node, ui as uimod
673 673 > notrc = b"HG~1/hgrc"
674 674 > u = uimod.ui.load()
675 675 > r = hg.repository(u, b'.')
676 676 > def filectxfn(repo, memctx, path):
677 677 > return context.memfilectx(repo, memctx, path,
678 678 > b'[hooks]\nupdate = echo owned')
679 679 > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
680 680 > b'evil', [notrc], filectxfn, 0)
681 681 > r.commitctx(c)
682 682 > EOF
683 683 $ $PYTHON evil-commit.py
684 684 $ hg co --clean tip
685 685 abort: path contains illegal component: HG~1/hgrc
686 686 [255]
687 687
688 688 $ hg rollback -f
689 689 repository tip rolled back to revision 2 (undo commit)
690 690 $ cat > evil-commit.py <<EOF
691 691 > from __future__ import absolute_import
692 692 > from mercurial import context, hg, node, ui as uimod
693 693 > notrc = b"HG8B6C~2/hgrc"
694 694 > u = uimod.ui.load()
695 695 > r = hg.repository(u, b'.')
696 696 > def filectxfn(repo, memctx, path):
697 697 > return context.memfilectx(repo, memctx, path,
698 698 > b'[hooks]\nupdate = echo owned')
699 699 > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
700 700 > b'evil', [notrc], filectxfn, 0)
701 701 > r.commitctx(c)
702 702 > EOF
703 703 $ $PYTHON evil-commit.py
704 704 $ hg co --clean tip
705 705 abort: path contains illegal component: HG8B6C~2/hgrc
706 706 [255]
707 707
708 708 # test that an unmodified commit template message aborts
709 709
710 710 $ hg init unmodified_commit_template
711 711 $ cd unmodified_commit_template
712 712 $ echo foo > foo
713 713 $ hg add foo
714 714 $ hg commit -m "foo"
715 715 $ cat >> .hg/hgrc <<EOF
716 716 > [committemplate]
717 717 > changeset.commit = HI THIS IS NOT STRIPPED
718 718 > HG: this is customized commit template
719 719 > HG: {extramsg}
720 720 > {if(activebookmark,
721 721 > "HG: bookmark '{activebookmark}' is activated\n",
722 722 > "HG: no bookmark is activated\n")}{subrepos %
723 723 > "HG: subrepo '{subrepo}' is changed\n"}
724 724 > EOF
725 725 $ cat > $TESTTMP/notouching.sh <<EOF
726 726 > true
727 727 > EOF
728 728 $ echo foo2 > foo2
729 729 $ hg add foo2
730 730 $ HGEDITOR="sh $TESTTMP/notouching.sh" hg commit
731 731 abort: commit message unchanged
732 732 [255]
733 733
734 734 test that text below the --- >8 --- special string is ignored
735 735
736 736 $ cat <<'EOF' > $TESTTMP/lowercaseline.sh
737 737 > cat $1 | sed s/LINE/line/ | tee $1.new
738 738 > mv $1.new $1
739 739 > EOF
740 740
741 741 $ hg init ignore_below_special_string
742 742 $ cd ignore_below_special_string
743 743 $ echo foo > foo
744 744 $ hg add foo
745 745 $ hg commit -m "foo"
746 746 $ cat >> .hg/hgrc <<EOF
747 747 > [committemplate]
748 748 > changeset.commit = first LINE
749 749 > HG: this is customized commit template
750 750 > HG: {extramsg}
751 751 > HG: ------------------------ >8 ------------------------
752 752 > {diff()}
753 753 > EOF
754 754 $ echo foo2 > foo2
755 755 $ hg add foo2
756 756 $ HGEDITOR="sh $TESTTMP/notouching.sh" hg ci
757 757 abort: commit message unchanged
758 758 [255]
759 759 $ HGEDITOR="sh $TESTTMP/lowercaseline.sh" hg ci
760 760 first line
761 761 HG: this is customized commit template
762 762 HG: Leave message empty to abort commit.
763 763 HG: ------------------------ >8 ------------------------
764 764 diff -r e63c23eaa88a foo2
765 765 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
766 766 +++ b/foo2 Thu Jan 01 00:00:00 1970 +0000
767 767 @@ -0,0 +1,1 @@
768 768 +foo2
769 769 $ hg log -T '{desc}\n' -r .
770 770 first line
771 771
772 772 test that the special string --- >8 --- isn't used when not at the beginning of
773 773 a line
774 774
775 775 $ cat >> .hg/hgrc <<EOF
776 776 > [committemplate]
777 777 > changeset.commit = first LINE2
778 778 > another line HG: ------------------------ >8 ------------------------
779 779 > HG: this is customized commit template
780 780 > HG: {extramsg}
781 781 > HG: ------------------------ >8 ------------------------
782 782 > {diff()}
783 783 > EOF
784 784 $ echo foo >> foo
785 785 $ HGEDITOR="sh $TESTTMP/lowercaseline.sh" hg ci
786 786 first line2
787 787 another line HG: ------------------------ >8 ------------------------
788 788 HG: this is customized commit template
789 789 HG: Leave message empty to abort commit.
790 790 HG: ------------------------ >8 ------------------------
791 791 diff -r 3661b22b0702 foo
792 792 --- a/foo Thu Jan 01 00:00:00 1970 +0000
793 793 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
794 794 @@ -1,1 +1,2 @@
795 795 foo
796 796 +foo
797 797 $ hg log -T '{desc}\n' -r .
798 798 first line2
799 799 another line HG: ------------------------ >8 ------------------------
800 800
801 801 also test that this special string isn't accepted when there is some extra text
802 802 at the end
803 803
804 804 $ cat >> .hg/hgrc <<EOF
805 805 > [committemplate]
806 806 > changeset.commit = first LINE3
807 807 > HG: ------------------------ >8 ------------------------foobar
808 808 > second line
809 809 > HG: this is customized commit template
810 810 > HG: {extramsg}
811 811 > HG: ------------------------ >8 ------------------------
812 812 > {diff()}
813 813 > EOF
814 814 $ echo foo >> foo
815 815 $ HGEDITOR="sh $TESTTMP/lowercaseline.sh" hg ci
816 816 first line3
817 817 HG: ------------------------ >8 ------------------------foobar
818 818 second line
819 819 HG: this is customized commit template
820 820 HG: Leave message empty to abort commit.
821 821 HG: ------------------------ >8 ------------------------
822 822 diff -r ce648f5f066f foo
823 823 --- a/foo Thu Jan 01 00:00:00 1970 +0000
824 824 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
825 825 @@ -1,2 +1,3 @@
826 826 foo
827 827 foo
828 828 +foo
829 829 $ hg log -T '{desc}\n' -r .
830 830 first line3
831 831 second line
832 832
833 833 $ cd ..
@@ -1,250 +1,250 b''
1 1 # enable bundle2 in advance
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [format]
5 5 > usegeneraldelta=yes
6 6 > EOF
7 7
8 8 $ mkdir part1
9 9 $ cd part1
10 10
11 11 $ hg init
12 12 $ echo a > a
13 13 $ hg add a
14 14 $ hg commit -m "1"
15 15 $ hg status
16 16 $ hg copy a b
17 17 $ hg --config ui.portablefilenames=abort copy a con.xml
18 18 abort: filename contains 'con', which is reserved on Windows: con.xml
19 19 [255]
20 20 $ hg status
21 21 A b
22 22 $ hg sum
23 23 parent: 0:c19d34741b0a tip
24 24 1
25 25 branch: default
26 26 commit: 1 copied
27 27 update: (current)
28 28 phases: 1 draft
29 29 $ hg --debug commit -m "2"
30 30 committing files:
31 31 b
32 32 b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
33 33 committing manifest
34 34 committing changelog
35 35 updating the branch cache
36 36 committed changeset 1:93580a2c28a50a56f63526fb305067e6fbf739c4
37 37
38 38 we should see two history entries
39 39
40 40 $ hg history -v
41 41 changeset: 1:93580a2c28a5
42 42 tag: tip
43 43 user: test
44 44 date: Thu Jan 01 00:00:00 1970 +0000
45 45 files: b
46 46 description:
47 47 2
48 48
49 49
50 50 changeset: 0:c19d34741b0a
51 51 user: test
52 52 date: Thu Jan 01 00:00:00 1970 +0000
53 53 files: a
54 54 description:
55 55 1
56 56
57 57
58 58
59 59 we should see one log entry for a
60 60
61 61 $ hg log a
62 62 changeset: 0:c19d34741b0a
63 63 user: test
64 64 date: Thu Jan 01 00:00:00 1970 +0000
65 65 summary: 1
66 66
67 67
68 68 this should show a revision linked to changeset 0
69 69
70 70 $ hg debugindex a
71 rev offset length linkrev nodeid p1 p2
72 0 0 3 0 b789fdd96dc2 000000000000 000000000000
71 rev linkrev nodeid p1 p2
72 0 0 b789fdd96dc2 000000000000 000000000000
73 73
74 74 we should see one log entry for b
75 75
76 76 $ hg log b
77 77 changeset: 1:93580a2c28a5
78 78 tag: tip
79 79 user: test
80 80 date: Thu Jan 01 00:00:00 1970 +0000
81 81 summary: 2
82 82
83 83
84 84 this should show a revision linked to changeset 1
85 85
86 86 $ hg debugindex b
87 rev offset length linkrev nodeid p1 p2
88 0 0 65 1 37d9b5d994ea 000000000000 000000000000
87 rev linkrev nodeid p1 p2
88 0 1 37d9b5d994ea 000000000000 000000000000
89 89
90 90 this should show the rename information in the metadata
91 91
92 92 $ hg debugdata b 0 | head -3 | tail -2
93 93 copy: a
94 94 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
95 95
96 96 $ md5sum.py .hg/store/data/b.i
97 97 44913824c8f5890ae218f9829535922e .hg/store/data/b.i
98 98 $ hg cat b > bsum
99 99 $ md5sum.py bsum
100 100 60b725f10c9c85c70d97880dfe8191b3 bsum
101 101 $ hg cat a > asum
102 102 $ md5sum.py asum
103 103 60b725f10c9c85c70d97880dfe8191b3 asum
104 104 $ hg verify
105 105 checking changesets
106 106 checking manifests
107 107 crosschecking files in changesets and manifests
108 108 checking files
109 109 2 files, 2 changesets, 2 total revisions
110 110
111 111 $ cd ..
112 112
113 113
114 114 $ mkdir part2
115 115 $ cd part2
116 116
117 117 $ hg init
118 118 $ echo foo > foo
119 119 should fail - foo is not managed
120 120 $ hg mv foo bar
121 121 foo: not copying - file is not managed
122 122 abort: no files to copy
123 123 [255]
124 124 $ hg st -A
125 125 ? foo
126 126 $ hg add foo
127 127 dry-run; print a warning that this is not a real copy; foo is added
128 128 $ hg mv --dry-run foo bar
129 129 foo has not been committed yet, so no copy data will be stored for bar.
130 130 $ hg st -A
131 131 A foo
132 132 should print a warning that this is not a real copy; bar is added
133 133 $ hg mv foo bar
134 134 foo has not been committed yet, so no copy data will be stored for bar.
135 135 $ hg st -A
136 136 A bar
137 137 should print a warning that this is not a real copy; foo is added
138 138 $ hg cp bar foo
139 139 bar has not been committed yet, so no copy data will be stored for foo.
140 140 $ hg rm -f bar
141 141 $ rm bar
142 142 $ hg st -A
143 143 A foo
144 144 $ hg commit -m1
145 145
146 146 moving a missing file
147 147 $ rm foo
148 148 $ hg mv foo foo3
149 149 foo: deleted in working directory
150 150 foo3 does not exist!
151 151 $ hg up -qC .
152 152
153 153 copy --after to a nonexistent target filename
154 154 $ hg cp -A foo dummy
155 155 foo: not recording copy - dummy does not exist
156 156
157 157 dry-run; should show that foo is clean
158 158 $ hg copy --dry-run foo bar
159 159 $ hg st -A
160 160 C foo
161 161 should show copy
162 162 $ hg copy foo bar
163 163 $ hg st -C
164 164 A bar
165 165 foo
166 166
167 167 shouldn't show copy
168 168 $ hg commit -m2
169 169 $ hg st -C
170 170
171 171 should match
172 172 $ hg debugindex foo
173 rev offset length linkrev nodeid p1 p2
174 0 0 5 0 2ed2a3912a0b 000000000000 000000000000
173 rev linkrev nodeid p1 p2
174 0 0 2ed2a3912a0b 000000000000 000000000000
175 175 $ hg debugrename bar
176 176 bar renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
177 177
178 178 $ echo bleah > foo
179 179 $ echo quux > bar
180 180 $ hg commit -m3
181 181
182 182 should not be renamed
183 183 $ hg debugrename bar
184 184 bar not renamed
185 185
186 186 $ hg copy -f foo bar
187 187 should show copy
188 188 $ hg st -C
189 189 M bar
190 190 foo
191 191
192 192 XXX: filtering lfilesrepo.status() in 3.3-rc causes the copy source to not be
193 193 displayed.
194 194 $ hg st -C --config extensions.largefiles=
195 195 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
196 196 M bar
197 197 foo
198 198
199 199 $ hg commit -m3
200 200
201 201 should show no parents for tip
202 202 $ hg debugindex bar
203 rev offset length linkrev nodeid p1 p2
204 0 0 69 1 7711d36246cc 000000000000 000000000000
205 1 69 6 2 bdf70a2b8d03 7711d36246cc 000000000000
206 2 75 71 3 b2558327ea8d 000000000000 000000000000
203 rev linkrev nodeid p1 p2
204 0 1 7711d36246cc 000000000000 000000000000
205 1 2 bdf70a2b8d03 7711d36246cc 000000000000
206 2 3 b2558327ea8d 000000000000 000000000000
207 207 should match
208 208 $ hg debugindex foo
209 rev offset length linkrev nodeid p1 p2
210 0 0 5 0 2ed2a3912a0b 000000000000 000000000000
211 1 5 7 2 dd12c926cf16 2ed2a3912a0b 000000000000
209 rev linkrev nodeid p1 p2
210 0 0 2ed2a3912a0b 000000000000 000000000000
211 1 2 dd12c926cf16 2ed2a3912a0b 000000000000
212 212 $ hg debugrename bar
213 213 bar renamed from foo:dd12c926cf165e3eb4cf87b084955cb617221c17
214 214
215 215 should show no copies
216 216 $ hg st -C
217 217
218 218 copy --after on an added file
219 219 $ cp bar baz
220 220 $ hg add baz
221 221 $ hg cp -A bar baz
222 222 $ hg st -C
223 223 A baz
224 224 bar
225 225
226 226 foo was clean:
227 227 $ hg st -AC foo
228 228 C foo
229 229 Trying to copy on top of an existing file fails,
230 230 $ hg copy -A bar foo
231 231 foo: not overwriting - file already committed
232 232 (hg copy --after --force to replace the file by recording a copy)
233 233 same error without the --after, so the user doesn't have to go through
234 234 two hints:
235 235 $ hg copy bar foo
236 236 foo: not overwriting - file already committed
237 237 (hg copy --force to replace the file by recording a copy)
238 238 but it's considered modified after a copy --after --force
239 239 $ hg copy -Af bar foo
240 240 $ hg st -AC foo
241 241 M foo
242 242 bar
243 243 The hint for a file that exists but is not in file history doesn't
244 244 mention --force:
245 245 $ touch xyzzy
246 246 $ hg cp bar xyzzy
247 247 xyzzy: not overwriting - file exists
248 248 (hg copy --after to record the copy)
249 249
250 250 $ cd ..
@@ -1,406 +1,417 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [ui]
3 3 > interactive=yes
4 4 > [format]
5 5 > usegeneraldelta=yes
6 6 > EOF
7 7
8 8 $ hg init debugrevlog
9 9 $ cd debugrevlog
10 10 $ echo a > a
11 11 $ hg ci -Am adda
12 12 adding a
13 13 $ hg debugrevlog -m
14 14 format : 1
15 15 flags : inline, generaldelta
16 16
17 17 revisions : 1
18 18 merges : 0 ( 0.00%)
19 19 normal : 1 (100.00%)
20 20 revisions : 1
21 21 full : 1 (100.00%)
22 22 deltas : 0 ( 0.00%)
23 23 revision size : 44
24 24 full : 44 (100.00%)
25 25 deltas : 0 ( 0.00%)
26 26
27 27 chunks : 1
28 28 0x75 (u) : 1 (100.00%)
29 29 chunks size : 44
30 30 0x75 (u) : 44 (100.00%)
31 31
32 32 avg chain length : 0
33 33 max chain length : 0
34 34 max chain reach : 44
35 35 compression ratio : 0
36 36
37 37 uncompressed data size (min/max/avg) : 43 / 43 / 43
38 38 full revision size (min/max/avg) : 44 / 44 / 44
39 39 delta size (min/max/avg) : 0 / 0 / 0
40 40
41 Test debugindex, with and without the --debug flag
41 Test debugindex, with and without the --verbose/--debug flag
42 42 $ hg debugindex a
43 rev linkrev nodeid p1 p2
44 0 0 b789fdd96dc2 000000000000 000000000000
45
46 $ hg --verbose debugindex a
43 47 rev offset length linkrev nodeid p1 p2
44 48 0 0 3 0 b789fdd96dc2 000000000000 000000000000
49
45 50 $ hg --debug debugindex a
46 51 rev offset length linkrev nodeid p1 p2
47 52 0 0 3 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
53
48 54 $ hg debugindex -f 1 a
55 rev flag size link p1 p2 nodeid
56 0 0000 2 0 -1 -1 b789fdd96dc2
57
58 $ hg --verbose debugindex -f 1 a
49 59 rev flag offset length size link p1 p2 nodeid
50 60 0 0000 0 3 2 0 -1 -1 b789fdd96dc2
61
51 62 $ hg --debug debugindex -f 1 a
52 63 rev flag offset length size link p1 p2 nodeid
53 64 0 0000 0 3 2 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
54 65
55 66 debugdelta chain basic output
56 67
57 68 $ hg debugdeltachain -m
58 69 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
59 70 0 1 1 -1 base 44 43 44 1.02326 44 0 0.00000
60 71
61 72 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
62 73 0 1 1
63 74
64 75 $ hg debugdeltachain -m -Tjson
65 76 [
66 77 {
67 78 "chainid": 1,
68 79 "chainlen": 1,
69 80 "chainratio": 1.02325581395,
70 81 "chainsize": 44,
71 82 "compsize": 44,
72 83 "deltatype": "base",
73 84 "extradist": 0,
74 85 "extraratio": 0.0,
75 86 "lindist": 44,
76 87 "prevrev": -1,
77 88 "rev": 0,
78 89 "uncompsize": 43
79 90 }
80 91 ]
81 92
82 93 debugdelta chain with sparse read enabled
83 94
84 95 $ cat >> $HGRCPATH <<EOF
85 96 > [experimental]
86 97 > sparse-read = True
87 98 > EOF
88 99 $ hg debugdeltachain -m
89 100 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
90 101 0 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
91 102
92 103 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
93 104 0 1 1 44 44 1.0
94 105
95 106 $ hg debugdeltachain -m -Tjson
96 107 [
97 108 {
98 109 "chainid": 1,
99 110 "chainlen": 1,
100 111 "chainratio": 1.02325581395,
101 112 "chainsize": 44,
102 113 "compsize": 44,
103 114 "deltatype": "base",
104 115 "extradist": 0,
105 116 "extraratio": 0.0,
106 117 "largestblock": 44,
107 118 "lindist": 44,
108 119 "prevrev": -1,
109 120 "readdensity": 1.0,
110 121 "readsize": 44,
111 122 "rev": 0,
112 123 "srchunks": 1,
113 124 "uncompsize": 43
114 125 }
115 126 ]
116 127
117 128 $ printf "This test checks things.\n" >> a
118 129 $ hg ci -m a
119 130 $ hg branch other
120 131 marked working directory as branch other
121 132 (branches are permanent and global, did you want a bookmark?)
122 133 $ for i in `$TESTDIR/seq.py 5`; do
123 134 > printf "shorter ${i}" >> a
124 135 > hg ci -m "a other:$i"
125 136 > hg up -q default
126 137 > printf "for the branch default we want longer chains: ${i}" >> a
127 138 > hg ci -m "a default:$i"
128 139 > hg up -q other
129 140 > done
130 141 $ hg debugdeltachain a -T '{rev} {srchunks}\n' \
131 142 > --config experimental.sparse-read.density-threshold=0.50 \
132 143 > --config experimental.sparse-read.min-gap-size=0
133 144 0 1
134 145 1 1
135 146 2 1
136 147 3 1
137 148 4 1
138 149 5 1
139 150 6 1
140 151 7 1
141 152 8 1
142 153 9 1
143 154 10 2
144 155 11 1
145 156 $ hg --config extensions.strip= strip --no-backup -r 1
146 157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 158
148 159 Test max chain len
149 160 $ cat >> $HGRCPATH << EOF
150 161 > [format]
151 162 > maxchainlen=4
152 163 > EOF
153 164
154 165 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
155 166 $ hg ci -m a
156 167 $ printf "b\n" >> a
157 168 $ hg ci -m a
158 169 $ printf "c\n" >> a
159 170 $ hg ci -m a
160 171 $ printf "d\n" >> a
161 172 $ hg ci -m a
162 173 $ printf "e\n" >> a
163 174 $ hg ci -m a
164 175 $ printf "f\n" >> a
165 176 $ hg ci -m a
166 177 $ printf 'g\n' >> a
167 178 $ hg ci -m a
168 179 $ printf 'h\n' >> a
169 180 $ hg ci -m a
170 181 $ hg debugrevlog -d a
171 182 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
172 183 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
173 184 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
174 185 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
175 186 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
176 187 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
177 188 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
178 189 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
179 190 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
180 191 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
181 192
182 193 Test debuglocks command:
183 194
184 195 $ hg debuglocks
185 196 lock: free
186 197 wlock: free
187 198
188 199 * Test setting the lock
189 200
190 201 waitlock <file> will wait for file to be created. If it isn't in a reasonable
191 202 amount of time, displays error message and returns 1
192 203 $ waitlock() {
193 204 > start=`date +%s`
194 205 > timeout=5
195 206 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do
196 207 > now=`date +%s`
197 208 > if [ "`expr $now - $start`" -gt $timeout ]; then
198 209 > echo "timeout: $1 was not created in $timeout seconds"
199 210 > return 1
200 211 > fi
201 212 > sleep 0.1
202 213 > done
203 214 > }
204 215 $ dolock() {
205 216 > {
206 217 > waitlock .hg/unlock
207 218 > rm -f .hg/unlock
208 219 > echo y
209 220 > } | hg debuglocks "$@" > /dev/null
210 221 > }
211 222 $ dolock -s &
212 223 $ waitlock .hg/store/lock
213 224
214 225 $ hg debuglocks
215 226 lock: user *, process * (*s) (glob)
216 227 wlock: free
217 228 [1]
218 229 $ touch .hg/unlock
219 230 $ wait
220 231 $ [ -f .hg/store/lock ] || echo "There is no lock"
221 232 There is no lock
222 233
223 234 * Test setting the wlock
224 235
225 236 $ dolock -S &
226 237 $ waitlock .hg/wlock
227 238
228 239 $ hg debuglocks
229 240 lock: free
230 241 wlock: user *, process * (*s) (glob)
231 242 [1]
232 243 $ touch .hg/unlock
233 244 $ wait
234 245 $ [ -f .hg/wlock ] || echo "There is no wlock"
235 246 There is no wlock
236 247
237 248 * Test setting both locks
238 249
239 250 $ dolock -Ss &
240 251 $ waitlock .hg/wlock && waitlock .hg/store/lock
241 252
242 253 $ hg debuglocks
243 254 lock: user *, process * (*s) (glob)
244 255 wlock: user *, process * (*s) (glob)
245 256 [2]
246 257
247 258 * Test failing to set a lock
248 259
249 260 $ hg debuglocks -s
250 261 abort: lock is already held
251 262 [255]
252 263
253 264 $ hg debuglocks -S
254 265 abort: wlock is already held
255 266 [255]
256 267
257 268 $ touch .hg/unlock
258 269 $ wait
259 270
260 271 $ hg debuglocks
261 272 lock: free
262 273 wlock: free
263 274
264 275 * Test forcing the lock
265 276
266 277 $ dolock -s &
267 278 $ waitlock .hg/store/lock
268 279
269 280 $ hg debuglocks
270 281 lock: user *, process * (*s) (glob)
271 282 wlock: free
272 283 [1]
273 284
274 285 $ hg debuglocks -L
275 286
276 287 $ hg debuglocks
277 288 lock: free
278 289 wlock: free
279 290
280 291 $ touch .hg/unlock
281 292 $ wait
282 293
283 294 * Test forcing the wlock
284 295
285 296 $ dolock -S &
286 297 $ waitlock .hg/wlock
287 298
288 299 $ hg debuglocks
289 300 lock: free
290 301 wlock: user *, process * (*s) (glob)
291 302 [1]
292 303
293 304 $ hg debuglocks -W
294 305
295 306 $ hg debuglocks
296 307 lock: free
297 308 wlock: free
298 309
299 310 $ touch .hg/unlock
300 311 $ wait
301 312
302 313 Test WdirUnsupported exception
303 314
304 315 $ hg debugdata -c ffffffffffffffffffffffffffffffffffffffff
305 316 abort: working directory revision cannot be specified
306 317 [255]
307 318
308 319 Test cache warming command
309 320
310 321 $ rm -rf .hg/cache/
311 322 $ hg debugupdatecaches --debug
312 323 updating the branch cache
313 324 $ ls -r .hg/cache/*
314 325 .hg/cache/rbc-revs-v1
315 326 .hg/cache/rbc-names-v1
316 327 .hg/cache/branch2-served
317 328
318 329 $ cd ..
319 330
320 331 Test internal debugstacktrace command
321 332
322 333 $ cat > debugstacktrace.py << EOF
323 334 > from __future__ import absolute_import
324 335 > import sys
325 336 > from mercurial import util
326 337 > def f():
327 338 > util.debugstacktrace(f=sys.stdout)
328 339 > g()
329 340 > def g():
330 341 > util.dst('hello from g\\n', skip=1)
331 342 > h()
332 343 > def h():
333 344 > util.dst('hi ...\\nfrom h hidden in g', 1, depth=2)
334 345 > f()
335 346 > EOF
336 347 $ $PYTHON debugstacktrace.py
337 348 stacktrace at:
338 349 debugstacktrace.py:12 in * (glob)
339 350 debugstacktrace.py:5 in f
340 351 hello from g at:
341 352 debugstacktrace.py:12 in * (glob)
342 353 debugstacktrace.py:6 in f
343 354 hi ...
344 355 from h hidden in g at:
345 356 debugstacktrace.py:6 in f
346 357 debugstacktrace.py:9 in g
347 358
348 359 Test debugcapabilities command:
349 360
350 361 $ hg debugcapabilities ./debugrevlog/
351 362 Main capabilities:
352 363 branchmap
353 364 $USUAL_BUNDLE2_CAPS$
354 365 getbundle
355 366 known
356 367 lookup
357 368 pushkey
358 369 unbundle
359 370 Bundle2 capabilities:
360 371 HG20
361 372 bookmarks
362 373 changegroup
363 374 01
364 375 02
365 376 digests
366 377 md5
367 378 sha1
368 379 sha512
369 380 error
370 381 abort
371 382 unsupportedcontent
372 383 pushraced
373 384 pushkey
374 385 hgtagsfnodes
375 386 listkeys
376 387 phases
377 388 heads
378 389 pushkey
379 390 remote-changegroup
380 391 http
381 392 https
382 393 rev-branch-cache
383 394 stream
384 395 v2
385 396
386 397 Test debugpeer
387 398
388 399 $ hg --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" debugpeer ssh://user@dummy/debugrevlog
389 400 url: ssh://user@dummy/debugrevlog
390 401 local: no
391 402 pushable: yes
392 403
393 404 $ hg --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" --debug debugpeer ssh://user@dummy/debugrevlog
394 405 running "*" "*/tests/dummyssh" 'user@dummy' 'hg -R debugrevlog serve --stdio' (glob) (no-windows !)
395 406 running "*" "*\tests/dummyssh" "user@dummy" "hg -R debugrevlog serve --stdio" (glob) (windows !)
396 407 devel-peer-request: hello
397 408 sending hello command
398 409 devel-peer-request: between
399 410 devel-peer-request: pairs: 81 bytes
400 411 sending between command
401 412 remote: 403
402 413 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN batch
403 414 remote: 1
404 415 url: ssh://user@dummy/debugrevlog
405 416 local: no
406 417 pushable: yes
@@ -1,101 +1,101 b''
1 1 $ hg init
2 2
3 3 $ echo foo > a
4 4 $ echo foo > b
5 5 $ hg add a b
6 6
7 7 $ hg ci -m "test"
8 8
9 9 $ echo blah > a
10 10
11 11 $ hg ci -m "branch a"
12 12
13 13 $ hg co 0
14 14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15
16 16 $ echo blah > b
17 17
18 18 $ hg ci -m "branch b"
19 19 created new head
20 20 $ HGMERGE=true hg merge 1
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 (branch merge, don't forget to commit)
23 23
24 24 $ hg ci -m "merge b/a -> blah"
25 25
26 26 $ hg co 1
27 27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 28 $ HGMERGE=true hg merge 2
29 29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 30 (branch merge, don't forget to commit)
31 31 $ hg ci -m "merge a/b -> blah"
32 32 created new head
33 33
34 34 $ hg log
35 35 changeset: 4:2ee31f665a86
36 36 tag: tip
37 37 parent: 1:96155394af80
38 38 parent: 2:92cc4c306b19
39 39 user: test
40 40 date: Thu Jan 01 00:00:00 1970 +0000
41 41 summary: merge a/b -> blah
42 42
43 43 changeset: 3:e16a66a37edd
44 44 parent: 2:92cc4c306b19
45 45 parent: 1:96155394af80
46 46 user: test
47 47 date: Thu Jan 01 00:00:00 1970 +0000
48 48 summary: merge b/a -> blah
49 49
50 50 changeset: 2:92cc4c306b19
51 51 parent: 0:5e0375449e74
52 52 user: test
53 53 date: Thu Jan 01 00:00:00 1970 +0000
54 54 summary: branch b
55 55
56 56 changeset: 1:96155394af80
57 57 user: test
58 58 date: Thu Jan 01 00:00:00 1970 +0000
59 59 summary: branch a
60 60
61 61 changeset: 0:5e0375449e74
62 62 user: test
63 63 date: Thu Jan 01 00:00:00 1970 +0000
64 64 summary: test
65 65
66 66 $ hg debugindex --changelog
67 rev offset length linkrev nodeid p1 p2
68 0 0 60 0 5e0375449e74 000000000000 000000000000
69 1 60 62 1 96155394af80 5e0375449e74 000000000000
70 2 122 62 2 92cc4c306b19 5e0375449e74 000000000000
71 3 184 69 3 e16a66a37edd 92cc4c306b19 96155394af80
72 4 253 69 4 2ee31f665a86 96155394af80 92cc4c306b19
67 rev linkrev nodeid p1 p2
68 0 0 5e0375449e74 000000000000 000000000000
69 1 1 96155394af80 5e0375449e74 000000000000
70 2 2 92cc4c306b19 5e0375449e74 000000000000
71 3 3 e16a66a37edd 92cc4c306b19 96155394af80
72 4 4 2ee31f665a86 96155394af80 92cc4c306b19
73 73
74 74 revision 1
75 75 $ hg manifest --debug 1
76 76 79d7492df40aa0fa093ec4209be78043c181f094 644 a
77 77 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 b
78 78 revision 2
79 79 $ hg manifest --debug 2
80 80 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 a
81 81 79d7492df40aa0fa093ec4209be78043c181f094 644 b
82 82 revision 3
83 83 $ hg manifest --debug 3
84 84 79d7492df40aa0fa093ec4209be78043c181f094 644 a
85 85 79d7492df40aa0fa093ec4209be78043c181f094 644 b
86 86 revision 4
87 87 $ hg manifest --debug 4
88 88 79d7492df40aa0fa093ec4209be78043c181f094 644 a
89 89 79d7492df40aa0fa093ec4209be78043c181f094 644 b
90 90
91 91 $ hg debugindex a
92 rev offset length linkrev nodeid p1 p2
93 0 0 5 0 2ed2a3912a0b 000000000000 000000000000
94 1 5 6 1 79d7492df40a 2ed2a3912a0b 000000000000
92 rev linkrev nodeid p1 p2
93 0 0 2ed2a3912a0b 000000000000 000000000000
94 1 1 79d7492df40a 2ed2a3912a0b 000000000000
95 95
96 96 $ hg verify
97 97 checking changesets
98 98 checking manifests
99 99 crosschecking files in changesets and manifests
100 100 checking files
101 101 2 files, 5 changesets, 4 total revisions
@@ -1,21 +1,21 b''
1 1 Issue351: mq: qrefresh can create extra revlog entry
2 2
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "mq=" >> $HGRCPATH
5 5
6 6 $ hg init
7 7 $ hg qinit
8 8
9 9 $ echo b > b
10 10 $ hg ci -A -m foo
11 11 adding b
12 12
13 13 $ echo cc > b
14 14 $ hg qnew -f foo.diff
15 15 $ echo b > b
16 16 $ hg qrefresh
17 17
18 18 $ hg debugindex b
19 rev offset length linkrev nodeid p1 p2
20 0 0 3 0 1e88685f5dde 000000000000 000000000000
19 rev linkrev nodeid p1 p2
20 0 0 1e88685f5dde 000000000000 000000000000
21 21
@@ -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 44 $ hg debugstate --nodates | 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 rev offset length linkrev nodeid p1 p2
77 0 0 73 0 cdca01651b96 000000000000 000000000000
78 1 73 68 1 f6718a9cb7f3 cdca01651b96 000000000000
79 2 141 68 2 bdd988058d16 cdca01651b96 000000000000
80 3 209 66 3 d8a521142a3c f6718a9cb7f3 bdd988058d16
76 rev linkrev nodeid p1 p2
77 0 0 cdca01651b96 000000000000 000000000000
78 1 1 f6718a9cb7f3 cdca01651b96 000000000000
79 2 2 bdd988058d16 cdca01651b96 000000000000
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 rev offset length linkrev nodeid p1 p2
101 0 0 3 0 b8e02f643373 000000000000 000000000000
102 1 3 4 1 2ffeddde1b65 b8e02f643373 000000000000
103 2 7 4 2 33d1fb69067a b8e02f643373 000000000000
104 3 11 4 3 aa27919ee430 2ffeddde1b65 33d1fb69067a
100 rev linkrev nodeid p1 p2
101 0 0 b8e02f643373 000000000000 000000000000
102 1 1 2ffeddde1b65 b8e02f643373 000000000000
103 2 2 33d1fb69067a b8e02f643373 000000000000
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 rev offset length linkrev nodeid p1 p2
110 0 0 3 0 b8e02f643373 000000000000 000000000000
111 1 3 4 2 33d1fb69067a b8e02f643373 000000000000
109 rev linkrev nodeid p1 p2
110 0 0 b8e02f643373 000000000000 000000000000
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 rev offset length linkrev nodeid p1 p2
117 0 0 3 0 b8e02f643373 000000000000 000000000000
118 1 3 4 1 2ffeddde1b65 b8e02f643373 000000000000
116 rev linkrev nodeid p1 p2
117 0 0 b8e02f643373 000000000000 000000000000
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 rev offset length linkrev nodeid p1 p2
124 0 0 3 0 b8e02f643373 000000000000 000000000000
125 1 3 5 3 6128c0f33108 b8e02f643373 000000000000
123 rev linkrev nodeid p1 p2
124 0 0 b8e02f643373 000000000000 000000000000
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 4 files, 4 changesets, 10 total revisions
145 145
146 146 $ cd ..
@@ -1,157 +1,157 b''
1 1 #require execbit
2 2
3 3 $ umask 027
4 4
5 5 $ hg init test1
6 6 $ cd test1
7 7 $ touch a b
8 8 $ hg add a b
9 9 $ hg ci -m "added a b"
10 10
11 11 $ cd ..
12 12 $ hg clone test1 test3
13 13 updating to branch default
14 14 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15
16 16 $ hg init test2
17 17 $ cd test2
18 18 $ hg pull ../test1
19 19 pulling from ../test1
20 20 requesting all changes
21 21 adding changesets
22 22 adding manifests
23 23 adding file changes
24 24 added 1 changesets with 2 changes to 2 files
25 25 new changesets 22a449e20da5
26 26 (run 'hg update' to get a working copy)
27 27 $ hg co
28 28 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 29 $ chmod +x a
30 30 $ hg ci -m "chmod +x a"
31 31
32 32 the changelog should mention file a:
33 33
34 34 $ hg tip --template '{files}\n'
35 35 a
36 36
37 37 $ cd ../test1
38 38 $ echo 123 >>a
39 39 $ hg ci -m "a updated"
40 40
41 41 $ hg pull ../test2
42 42 pulling from ../test2
43 43 searching for changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 1 changesets with 0 changes to 0 files (+1 heads)
48 48 new changesets 7f4313b42a34
49 49 (run 'hg heads' to see heads, 'hg merge' to merge)
50 50 $ hg heads
51 51 changeset: 2:7f4313b42a34
52 52 tag: tip
53 53 parent: 0:22a449e20da5
54 54 user: test
55 55 date: Thu Jan 01 00:00:00 1970 +0000
56 56 summary: chmod +x a
57 57
58 58 changeset: 1:c6ecefc45368
59 59 user: test
60 60 date: Thu Jan 01 00:00:00 1970 +0000
61 61 summary: a updated
62 62
63 63 $ hg history
64 64 changeset: 2:7f4313b42a34
65 65 tag: tip
66 66 parent: 0:22a449e20da5
67 67 user: test
68 68 date: Thu Jan 01 00:00:00 1970 +0000
69 69 summary: chmod +x a
70 70
71 71 changeset: 1:c6ecefc45368
72 72 user: test
73 73 date: Thu Jan 01 00:00:00 1970 +0000
74 74 summary: a updated
75 75
76 76 changeset: 0:22a449e20da5
77 77 user: test
78 78 date: Thu Jan 01 00:00:00 1970 +0000
79 79 summary: added a b
80 80
81 81
82 82 $ hg -v merge
83 83 resolving manifests
84 84 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 85 (branch merge, don't forget to commit)
86 86 $ cat a
87 87 123
88 88 $ [ -x a ]
89 89
90 90 $ cd ../test3
91 91 $ echo 123 >>b
92 92 $ hg ci -m "b updated"
93 93
94 94 $ hg pull ../test2
95 95 pulling from ../test2
96 96 searching for changes
97 97 adding changesets
98 98 adding manifests
99 99 adding file changes
100 100 added 1 changesets with 0 changes to 0 files (+1 heads)
101 101 new changesets 7f4313b42a34
102 102 (run 'hg heads' to see heads, 'hg merge' to merge)
103 103 $ hg heads
104 104 changeset: 2:7f4313b42a34
105 105 tag: tip
106 106 parent: 0:22a449e20da5
107 107 user: test
108 108 date: Thu Jan 01 00:00:00 1970 +0000
109 109 summary: chmod +x a
110 110
111 111 changeset: 1:dc57ead75f79
112 112 user: test
113 113 date: Thu Jan 01 00:00:00 1970 +0000
114 114 summary: b updated
115 115
116 116 $ hg history
117 117 changeset: 2:7f4313b42a34
118 118 tag: tip
119 119 parent: 0:22a449e20da5
120 120 user: test
121 121 date: Thu Jan 01 00:00:00 1970 +0000
122 122 summary: chmod +x a
123 123
124 124 changeset: 1:dc57ead75f79
125 125 user: test
126 126 date: Thu Jan 01 00:00:00 1970 +0000
127 127 summary: b updated
128 128
129 129 changeset: 0:22a449e20da5
130 130 user: test
131 131 date: Thu Jan 01 00:00:00 1970 +0000
132 132 summary: added a b
133 133
134 134
135 135 $ hg -v merge
136 136 resolving manifests
137 137 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 138 (branch merge, don't forget to commit)
139 139
140 140 $ ls -l ../test[123]/a > foo
141 141 $ cut -b 1-10 < foo
142 142 -rwxr-x---
143 143 -rwxr-x---
144 144 -rwxr-x---
145 145
146 146 $ hg debugindex a
147 rev offset length linkrev nodeid p1 p2
148 0 0 0 0 b80de5d13875 000000000000 000000000000
147 rev linkrev nodeid p1 p2
148 0 0 b80de5d13875 000000000000 000000000000
149 149 $ hg debugindex -R ../test2 a
150 rev offset length linkrev nodeid p1 p2
151 0 0 0 0 b80de5d13875 000000000000 000000000000
150 rev linkrev nodeid p1 p2
151 0 0 b80de5d13875 000000000000 000000000000
152 152 $ hg debugindex -R ../test1 a
153 rev offset length linkrev nodeid p1 p2
154 0 0 0 0 b80de5d13875 000000000000 000000000000
155 1 0 5 1 7fe919cc0336 b80de5d13875 000000000000
153 rev linkrev nodeid p1 p2
154 0 0 b80de5d13875 000000000000 000000000000
155 1 1 7fe919cc0336 b80de5d13875 000000000000
156 156
157 157 $ cd ..
@@ -1,55 +1,55 b''
1 1 https://bz.mercurial-scm.org/522
2 2
3 3 In the merge below, the file "foo" has the same contents in both
4 4 parents, but if we look at the file-level history, we'll notice that
5 5 the version in p1 is an ancestor of the version in p2. This test makes
6 6 sure that we'll use the version from p2 in the manifest of the merge
7 7 revision.
8 8
9 9 $ hg init
10 10
11 11 $ echo foo > foo
12 12 $ hg ci -qAm 'add foo'
13 13
14 14 $ echo bar >> foo
15 15 $ hg ci -m 'change foo'
16 16
17 17 $ hg backout -r tip -m 'backout changed foo'
18 18 reverting foo
19 19 changeset 2:4d9e78aaceee backs out changeset 1:b515023e500e
20 20
21 21 $ hg up -C 0
22 22 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 23
24 24 $ touch bar
25 25 $ hg ci -qAm 'add bar'
26 26
27 27 $ hg merge --debug
28 28 searching for copies back to rev 1
29 29 unmatched files in local:
30 30 bar
31 31 resolving manifests
32 32 branchmerge: True, force: False, partial: False
33 33 ancestor: bbd179dfa0a7, local: 71766447bdbb+, remote: 4d9e78aaceee
34 34 foo: remote is newer -> g
35 35 getting foo
36 36 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 37 (branch merge, don't forget to commit)
38 38
39 39 $ hg debugstate | grep foo
40 40 m 0 -2 unset foo
41 41
42 42 $ hg st -A foo
43 43 M foo
44 44
45 45 $ hg ci -m 'merge'
46 46
47 47 $ hg manifest --debug | grep foo
48 48 c6fc755d7e68f49f880599da29f15add41f42f5a 644 foo
49 49
50 50 $ hg debugindex foo
51 rev offset length linkrev nodeid p1 p2
52 0 0 5 0 2ed2a3912a0b 000000000000 000000000000
53 1 5 9 1 6f4310b00b9a 2ed2a3912a0b 000000000000
54 2 14 5 2 c6fc755d7e68 6f4310b00b9a 000000000000
51 rev linkrev nodeid p1 p2
52 0 0 2ed2a3912a0b 000000000000 000000000000
53 1 1 6f4310b00b9a 2ed2a3912a0b 000000000000
54 2 2 c6fc755d7e68 6f4310b00b9a 000000000000
55 55
@@ -1,185 +1,185 b''
1 1 Check that renames are correctly saved by a commit after a merge
2 2
3 3 Test with the merge on 3 having the rename on the local parent
4 4
5 5 $ hg init a
6 6 $ cd a
7 7
8 8 $ echo line1 > foo
9 9 $ hg add foo
10 10 $ hg ci -m '0: add foo'
11 11
12 12 $ echo line2 >> foo
13 13 $ hg ci -m '1: change foo'
14 14
15 15 $ hg up -C 0
16 16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 17
18 18 $ hg mv foo bar
19 19 $ rm bar
20 20 $ echo line0 > bar
21 21 $ echo line1 >> bar
22 22 $ hg ci -m '2: mv foo bar; change bar'
23 23 created new head
24 24
25 25 $ hg merge 1
26 26 merging bar and foo to bar
27 27 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
28 28 (branch merge, don't forget to commit)
29 29
30 30 $ cat bar
31 31 line0
32 32 line1
33 33 line2
34 34
35 35 $ hg ci -m '3: merge with local rename'
36 36
37 37 $ hg debugindex bar
38 rev offset length linkrev nodeid p1 p2
39 0 0 77 2 d35118874825 000000000000 000000000000
40 1 77 76 3 5345f5ab8abd 000000000000 d35118874825
38 rev linkrev nodeid p1 p2
39 0 2 d35118874825 000000000000 000000000000
40 1 3 5345f5ab8abd 000000000000 d35118874825
41 41
42 42 $ hg debugrename bar
43 43 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
44 44
45 45 $ hg debugindex foo
46 rev offset length linkrev nodeid p1 p2
47 0 0 7 0 690b295714ae 000000000000 000000000000
48 1 7 13 1 9e25c27b8757 690b295714ae 000000000000
46 rev linkrev nodeid p1 p2
47 0 0 690b295714ae 000000000000 000000000000
48 1 1 9e25c27b8757 690b295714ae 000000000000
49 49
50 50
51 51 Revert the content change from rev 2:
52 52
53 53 $ hg up -C 2
54 54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 55 $ rm bar
56 56 $ echo line1 > bar
57 57 $ hg ci -m '4: revert content change from rev 2'
58 58 created new head
59 59
60 60 $ hg log --template '{rev}:{node|short} {parents}\n'
61 61 4:2263c1be0967 2:0f2ff26688b9
62 62 3:0555950ead28 2:0f2ff26688b9 1:5cd961e4045d
63 63 2:0f2ff26688b9 0:2665aaee66e9
64 64 1:5cd961e4045d
65 65 0:2665aaee66e9
66 66
67 67 This should use bar@rev2 as the ancestor:
68 68
69 69 $ hg --debug merge 3
70 70 searching for copies back to rev 1
71 71 resolving manifests
72 72 branchmerge: True, force: False, partial: False
73 73 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 0555950ead28
74 74 preserving bar for resolve of bar
75 75 starting 4 threads for background file closing (?)
76 76 bar: versions differ -> m (premerge)
77 77 picked tool ':merge' for bar (binary False symlink False changedelete False)
78 78 merging bar
79 79 my bar@2263c1be0967+ other bar@0555950ead28 ancestor bar@0f2ff26688b9
80 80 premerge successful
81 81 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
82 82 (branch merge, don't forget to commit)
83 83
84 84 $ cat bar
85 85 line1
86 86 line2
87 87
88 88 $ hg ci -m '5: merge'
89 89
90 90 $ hg debugindex bar
91 rev offset length linkrev nodeid p1 p2
92 0 0 77 2 d35118874825 000000000000 000000000000
93 1 77 76 3 5345f5ab8abd 000000000000 d35118874825
94 2 153 7 4 ff4b45017382 d35118874825 000000000000
95 3 160 13 5 3701b4893544 ff4b45017382 5345f5ab8abd
91 rev linkrev nodeid p1 p2
92 0 2 d35118874825 000000000000 000000000000
93 1 3 5345f5ab8abd 000000000000 d35118874825
94 2 4 ff4b45017382 d35118874825 000000000000
95 3 5 3701b4893544 ff4b45017382 5345f5ab8abd
96 96
97 97
98 98 Same thing, but with the merge on 3 having the rename
99 99 on the remote parent:
100 100
101 101 $ cd ..
102 102 $ hg clone -U -r 1 -r 2 a b
103 103 adding changesets
104 104 adding manifests
105 105 adding file changes
106 106 added 3 changesets with 3 changes to 2 files (+1 heads)
107 107 new changesets 2665aaee66e9:0f2ff26688b9
108 108 $ cd b
109 109
110 110 $ hg up -C 1
111 111 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 112
113 113 $ hg merge 2
114 114 merging foo and bar to bar
115 115 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
116 116 (branch merge, don't forget to commit)
117 117
118 118 $ cat bar
119 119 line0
120 120 line1
121 121 line2
122 122
123 123 $ hg ci -m '3: merge with remote rename'
124 124
125 125 $ hg debugindex bar
126 rev offset length linkrev nodeid p1 p2
127 0 0 77 2 d35118874825 000000000000 000000000000
128 1 77 76 3 5345f5ab8abd 000000000000 d35118874825
126 rev linkrev nodeid p1 p2
127 0 2 d35118874825 000000000000 000000000000
128 1 3 5345f5ab8abd 000000000000 d35118874825
129 129
130 130 $ hg debugrename bar
131 131 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
132 132
133 133 $ hg debugindex foo
134 rev offset length linkrev nodeid p1 p2
135 0 0 7 0 690b295714ae 000000000000 000000000000
136 1 7 13 1 9e25c27b8757 690b295714ae 000000000000
134 rev linkrev nodeid p1 p2
135 0 0 690b295714ae 000000000000 000000000000
136 1 1 9e25c27b8757 690b295714ae 000000000000
137 137
138 138
139 139 Revert the content change from rev 2:
140 140
141 141 $ hg up -C 2
142 142 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 143 $ rm bar
144 144 $ echo line1 > bar
145 145 $ hg ci -m '4: revert content change from rev 2'
146 146 created new head
147 147
148 148 $ hg log --template '{rev}:{node|short} {parents}\n'
149 149 4:2263c1be0967 2:0f2ff26688b9
150 150 3:3ffa6b9e35f0 1:5cd961e4045d 2:0f2ff26688b9
151 151 2:0f2ff26688b9 0:2665aaee66e9
152 152 1:5cd961e4045d
153 153 0:2665aaee66e9
154 154
155 155 This should use bar@rev2 as the ancestor:
156 156
157 157 $ hg --debug merge 3
158 158 searching for copies back to rev 1
159 159 resolving manifests
160 160 branchmerge: True, force: False, partial: False
161 161 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 3ffa6b9e35f0
162 162 preserving bar for resolve of bar
163 163 starting 4 threads for background file closing (?)
164 164 bar: versions differ -> m (premerge)
165 165 picked tool ':merge' for bar (binary False symlink False changedelete False)
166 166 merging bar
167 167 my bar@2263c1be0967+ other bar@3ffa6b9e35f0 ancestor bar@0f2ff26688b9
168 168 premerge successful
169 169 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
170 170 (branch merge, don't forget to commit)
171 171
172 172 $ cat bar
173 173 line1
174 174 line2
175 175
176 176 $ hg ci -m '5: merge'
177 177
178 178 $ hg debugindex bar
179 rev offset length linkrev nodeid p1 p2
180 0 0 77 2 d35118874825 000000000000 000000000000
181 1 77 76 3 5345f5ab8abd 000000000000 d35118874825
182 2 153 7 4 ff4b45017382 d35118874825 000000000000
183 3 160 13 5 3701b4893544 ff4b45017382 5345f5ab8abd
179 rev linkrev nodeid p1 p2
180 0 2 d35118874825 000000000000 000000000000
181 1 3 5345f5ab8abd 000000000000 d35118874825
182 2 4 ff4b45017382 d35118874825 000000000000
183 3 5 3701b4893544 ff4b45017382 5345f5ab8abd
184 184
185 185 $ cd ..
@@ -1,151 +1,151 b''
1 1 initial
2 2 $ hg init test-a
3 3 $ cd test-a
4 4 $ cat >test.txt <<"EOF"
5 5 > 1
6 6 > 2
7 7 > 3
8 8 > EOF
9 9 $ hg add test.txt
10 10 $ hg commit -m "Initial"
11 11
12 12 clone
13 13 $ cd ..
14 14 $ hg clone test-a test-b
15 15 updating to branch default
16 16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 17
18 18 change test-a
19 19 $ cd test-a
20 20 $ cat >test.txt <<"EOF"
21 21 > one
22 22 > two
23 23 > three
24 24 > EOF
25 25 $ hg commit -m "Numbers as words"
26 26
27 27 change test-b
28 28 $ cd ../test-b
29 29 $ cat >test.txt <<"EOF"
30 30 > 1
31 31 > 2.5
32 32 > 3
33 33 > EOF
34 34 $ hg commit -m "2 -> 2.5"
35 35
36 36 now pull and merge from test-a
37 37 $ hg pull ../test-a
38 38 pulling from ../test-a
39 39 searching for changes
40 40 adding changesets
41 41 adding manifests
42 42 adding file changes
43 43 added 1 changesets with 1 changes to 1 files (+1 heads)
44 44 new changesets 96b70246a118
45 45 (run 'hg heads' to see heads, 'hg merge' to merge)
46 46 $ hg merge
47 47 merging test.txt
48 48 warning: conflicts while merging test.txt! (edit, then use 'hg resolve --mark')
49 49 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
50 50 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
51 51 [1]
52 52 resolve conflict
53 53 $ cat >test.txt <<"EOF"
54 54 > one
55 55 > two-point-five
56 56 > three
57 57 > EOF
58 58 $ rm -f *.orig
59 59 $ hg resolve -m test.txt
60 60 (no more unresolved files)
61 61 $ hg commit -m "Merge 1"
62 62
63 63 change test-a again
64 64 $ cd ../test-a
65 65 $ cat >test.txt <<"EOF"
66 66 > one
67 67 > two-point-one
68 68 > three
69 69 > EOF
70 70 $ hg commit -m "two -> two-point-one"
71 71
72 72 pull and merge from test-a again
73 73 $ cd ../test-b
74 74 $ hg pull ../test-a
75 75 pulling from ../test-a
76 76 searching for changes
77 77 adding changesets
78 78 adding manifests
79 79 adding file changes
80 80 added 1 changesets with 1 changes to 1 files (+1 heads)
81 81 new changesets 40d11a4173a8
82 82 (run 'hg heads' to see heads, 'hg merge' to merge)
83 83 $ hg merge --debug
84 84 searching for copies back to rev 1
85 85 resolving manifests
86 86 branchmerge: True, force: False, partial: False
87 87 ancestor: 96b70246a118, local: 50c3a7e29886+, remote: 40d11a4173a8
88 88 preserving test.txt for resolve of test.txt
89 89 starting 4 threads for background file closing (?)
90 90 test.txt: versions differ -> m (premerge)
91 91 picked tool ':merge' for test.txt (binary False symlink False changedelete False)
92 92 merging test.txt
93 93 my test.txt@50c3a7e29886+ other test.txt@40d11a4173a8 ancestor test.txt@96b70246a118
94 94 test.txt: versions differ -> m (merge)
95 95 picked tool ':merge' for test.txt (binary False symlink False changedelete False)
96 96 my test.txt@50c3a7e29886+ other test.txt@40d11a4173a8 ancestor test.txt@96b70246a118
97 97 warning: conflicts while merging test.txt! (edit, then use 'hg resolve --mark')
98 98 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
99 99 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
100 100 [1]
101 101
102 102 $ cat test.txt
103 103 one
104 104 <<<<<<< working copy: 50c3a7e29886 - test: Merge 1
105 105 two-point-five
106 106 =======
107 107 two-point-one
108 108 >>>>>>> merge rev: 40d11a4173a8 - test: two -> two-point-one
109 109 three
110 110
111 111 $ hg debugindex test.txt
112 rev offset length linkrev nodeid p1 p2
113 0 0 7 0 01365c4cca56 000000000000 000000000000
114 1 7 9 1 7b013192566a 01365c4cca56 000000000000
115 2 16 15 2 8fe46a3eb557 01365c4cca56 000000000000
116 3 31 2. 3 fc3148072371 7b013192566a 8fe46a3eb557 (re)
117 4 5. 25 4 d40249267ae3 8fe46a3eb557 000000000000 (re)
112 rev linkrev nodeid p1 p2
113 0 0 01365c4cca56 000000000000 000000000000
114 1 1 7b013192566a 01365c4cca56 000000000000
115 2 2 8fe46a3eb557 01365c4cca56 000000000000
116 3 3 fc3148072371 7b013192566a 8fe46a3eb557
117 4 4 d40249267ae3 8fe46a3eb557 000000000000
118 118
119 119 $ hg log
120 120 changeset: 4:40d11a4173a8
121 121 tag: tip
122 122 parent: 2:96b70246a118
123 123 user: test
124 124 date: Thu Jan 01 00:00:00 1970 +0000
125 125 summary: two -> two-point-one
126 126
127 127 changeset: 3:50c3a7e29886
128 128 parent: 1:d1e159716d41
129 129 parent: 2:96b70246a118
130 130 user: test
131 131 date: Thu Jan 01 00:00:00 1970 +0000
132 132 summary: Merge 1
133 133
134 134 changeset: 2:96b70246a118
135 135 parent: 0:b1832b9d912a
136 136 user: test
137 137 date: Thu Jan 01 00:00:00 1970 +0000
138 138 summary: Numbers as words
139 139
140 140 changeset: 1:d1e159716d41
141 141 user: test
142 142 date: Thu Jan 01 00:00:00 1970 +0000
143 143 summary: 2 -> 2.5
144 144
145 145 changeset: 0:b1832b9d912a
146 146 user: test
147 147 date: Thu Jan 01 00:00:00 1970 +0000
148 148 summary: Initial
149 149
150 150
151 151 $ cd ..
@@ -1,43 +1,43 b''
1 1 $ . "$TESTDIR/narrow-library.sh"
2 2 $ hg init repo
3 3 $ cd repo
4 4 $ cat << EOF > .hg/narrowspec
5 5 > [includes]
6 6 > path:foo
7 7 > [excludes]
8 8 > EOF
9 9 $ echo treemanifest >> .hg/requires
10 10 $ echo narrowhg-experimental >> .hg/requires
11 11 $ mkdir -p foo/bar
12 12 $ echo b > foo/f
13 13 $ echo c > foo/bar/f
14 14 $ hg commit -Am hi
15 15 adding foo/bar/f
16 16 adding foo/f
17 17 $ hg debugindex -m
18 rev offset length linkrev nodeid p1 p2
19 0 0 47 0 14a5d056d75a 000000000000 000000000000
18 rev linkrev nodeid p1 p2
19 0 0 14a5d056d75a 000000000000 000000000000
20 20 $ hg debugindex --dir foo
21 rev offset length linkrev nodeid p1 p2
22 0 0 77 0 e635c7857aef 000000000000 000000000000
21 rev linkrev nodeid p1 p2
22 0 0 e635c7857aef 000000000000 000000000000
23 23 $ hg debugindex --dir foo/
24 rev offset length linkrev nodeid p1 p2
25 0 0 77 0 e635c7857aef 000000000000 000000000000
24 rev linkrev nodeid p1 p2
25 0 0 e635c7857aef 000000000000 000000000000
26 26 $ hg debugindex --dir foo/bar
27 rev offset length linkrev nodeid p1 p2
28 0 0 44 0 e091d4224761 000000000000 000000000000
27 rev linkrev nodeid p1 p2
28 0 0 e091d4224761 000000000000 000000000000
29 29 $ hg debugindex --dir foo/bar/
30 rev offset length linkrev nodeid p1 p2
31 0 0 44 0 e091d4224761 000000000000 000000000000
30 rev linkrev nodeid p1 p2
31 0 0 e091d4224761 000000000000 000000000000
32 32 $ hg debugdata -m 0
33 33 foo\x00e635c7857aef92ac761ce5741a99da159abbbb24t (esc)
34 34 $ hg debugdata --dir foo 0
35 35 bar\x00e091d42247613adff5d41b67f15fe7189ee97b39t (esc)
36 36 f\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc)
37 37 $ hg debugdata --dir foo/ 0
38 38 bar\x00e091d42247613adff5d41b67f15fe7189ee97b39t (esc)
39 39 f\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc)
40 40 $ hg debugdata --dir foo/bar 0
41 41 f\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
42 42 $ hg debugdata --dir foo/bar/ 0
43 43 f\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
@@ -1,76 +1,76 b''
1 1
2 2 $ . "$TESTDIR/narrow-library.sh"
3 3
4 4 create full repo
5 5
6 6 $ hg init master
7 7 $ cd master
8 8 $ echo init > init
9 9 $ hg ci -Aqm 'initial'
10 10
11 11 $ mkdir inside
12 12 $ echo inside > inside/f1
13 13 $ mkdir outside
14 14 $ echo outside > outside/f1
15 15 $ hg ci -Aqm 'add inside and outside'
16 16
17 17 $ echo modified > inside/f1
18 18 $ hg ci -qm 'modify inside'
19 19
20 20 $ echo modified > outside/f1
21 21 $ hg ci -qm 'modify outside'
22 22
23 23 $ cd ..
24 24
25 25 $ hg clone --narrow ssh://user@dummy/master narrow --include inside
26 26 requesting all changes
27 27 adding changesets
28 28 adding manifests
29 29 adding file changes
30 30 added 4 changesets with 2 changes to 1 files
31 31 new changesets *:* (glob)
32 32 updating to branch default
33 33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 $ cd narrow
35 35 $ hg debugindex -c
36 rev offset length linkrev nodeid p1 p2
37 0 0 64 0 9958b1af2add 000000000000 000000000000
38 1 64 81 1 2db4ce2a3bfe 9958b1af2add 000000000000
39 2 145 75 2 0980ee31a742 2db4ce2a3bfe 000000000000
40 3 220 (76|77) 3 4410145019b7 0980ee31a742 000000000000 (re)
36 rev linkrev nodeid p1 p2
37 0 0 9958b1af2add 000000000000 000000000000
38 1 1 2db4ce2a3bfe 9958b1af2add 000000000000
39 2 2 0980ee31a742 2db4ce2a3bfe 000000000000
40 3 3 4410145019b7 0980ee31a742 000000000000
41 41
42 42 $ hg update -q 0
43 43
44 44 Can update to revision with changes inside
45 45
46 46 $ hg update -q 'desc("add inside and outside")'
47 47 $ hg update -q 'desc("modify inside")'
48 48 $ find *
49 49 inside
50 50 inside/f1
51 51 $ cat inside/f1
52 52 modified
53 53
54 54 Can update to revision with changes outside
55 55
56 56 $ hg update -q 'desc("modify outside")'
57 57 $ find *
58 58 inside
59 59 inside/f1
60 60 $ cat inside/f1
61 61 modified
62 62
63 63 Can update with a deleted file inside
64 64
65 65 $ hg rm inside/f1
66 66 $ hg update -q 'desc("modify inside")'
67 67 $ hg update -q 'desc("modify outside")'
68 68 $ hg update -q 'desc("initial")'
69 69 $ hg update -q 'desc("modify inside")'
70 70
71 71 Can update with a moved file inside
72 72
73 73 $ hg mv inside/f1 inside/f2
74 74 $ hg update -q 'desc("modify outside")'
75 75 $ hg update -q 'desc("initial")'
76 76 $ hg update -q 'desc("modify inside")'
@@ -1,203 +1,203 b''
1 1 revlog.parseindex must be able to parse the index file even if
2 2 an index entry is split between two 64k blocks. The ideal test
3 3 would be to create an index file with inline data where
4 4 64k < size < 64k + 64 (64k is the size of the read buffer, 64 is
5 5 the size of an index entry) and with an index entry starting right
6 6 before the 64k block boundary, and try to read it.
7 7 We approximate that by reducing the read buffer to 1 byte.
8 8
9 9 $ hg init a
10 10 $ cd a
11 11 $ echo abc > foo
12 12 $ hg add foo
13 13 $ hg commit -m 'add foo'
14 14 $ echo >> foo
15 15 $ hg commit -m 'change foo'
16 16 $ hg log -r 0:
17 17 changeset: 0:7c31755bf9b5
18 18 user: test
19 19 date: Thu Jan 01 00:00:00 1970 +0000
20 20 summary: add foo
21 21
22 22 changeset: 1:26333235a41c
23 23 tag: tip
24 24 user: test
25 25 date: Thu Jan 01 00:00:00 1970 +0000
26 26 summary: change foo
27 27
28 28 $ cat >> test.py << EOF
29 29 > from mercurial import changelog, vfs
30 30 > from mercurial.node import *
31 31 >
32 32 > class singlebyteread(object):
33 33 > def __init__(self, real):
34 34 > self.real = real
35 35 >
36 36 > def read(self, size=-1):
37 37 > if size == 65536:
38 38 > size = 1
39 39 > return self.real.read(size)
40 40 >
41 41 > def __getattr__(self, key):
42 42 > return getattr(self.real, key)
43 43 >
44 44 > def __enter__(self):
45 45 > self.real.__enter__()
46 46 > return self
47 47 >
48 48 > def __exit__(self, *args, **kwargs):
49 49 > return self.real.__exit__(*args, **kwargs)
50 50 >
51 51 > def opener(*args):
52 52 > o = vfs.vfs(*args)
53 53 > def wrapper(*a, **kwargs):
54 54 > f = o(*a, **kwargs)
55 55 > return singlebyteread(f)
56 56 > return wrapper
57 57 >
58 58 > cl = changelog.changelog(opener('.hg/store'))
59 59 > print len(cl), 'revisions:'
60 60 > for r in cl:
61 61 > print short(cl.node(r))
62 62 > EOF
63 63 $ $PYTHON test.py
64 64 2 revisions:
65 65 7c31755bf9b5
66 66 26333235a41c
67 67
68 68 $ cd ..
69 69
70 70 #if no-pure
71 71
72 72 Test SEGV caused by bad revision passed to reachableroots() (issue4775):
73 73
74 74 $ cd a
75 75
76 76 $ $PYTHON <<EOF
77 77 > from mercurial import changelog, vfs
78 78 > cl = changelog.changelog(vfs.vfs('.hg/store'))
79 79 > print 'good heads:'
80 80 > for head in [0, len(cl) - 1, -1]:
81 81 > print'%s: %r' % (head, cl.reachableroots(0, [head], [0]))
82 82 > print 'bad heads:'
83 83 > for head in [len(cl), 10000, -2, -10000, None]:
84 84 > print '%s:' % head,
85 85 > try:
86 86 > cl.reachableroots(0, [head], [0])
87 87 > print 'uncaught buffer overflow?'
88 88 > except (IndexError, TypeError) as inst:
89 89 > print inst
90 90 > print 'good roots:'
91 91 > for root in [0, len(cl) - 1, -1]:
92 92 > print '%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root]))
93 93 > print 'out-of-range roots are ignored:'
94 94 > for root in [len(cl), 10000, -2, -10000]:
95 95 > print '%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root]))
96 96 > print 'bad roots:'
97 97 > for root in [None]:
98 98 > print '%s:' % root,
99 99 > try:
100 100 > cl.reachableroots(root, [len(cl) - 1], [root])
101 101 > print 'uncaught error?'
102 102 > except TypeError as inst:
103 103 > print inst
104 104 > EOF
105 105 good heads:
106 106 0: [0]
107 107 1: [0]
108 108 -1: []
109 109 bad heads:
110 110 2: head out of range
111 111 10000: head out of range
112 112 -2: head out of range
113 113 -10000: head out of range
114 114 None: an integer is required
115 115 good roots:
116 116 0: [0]
117 117 1: [1]
118 118 -1: [-1]
119 119 out-of-range roots are ignored:
120 120 2: []
121 121 10000: []
122 122 -2: []
123 123 -10000: []
124 124 bad roots:
125 125 None: an integer is required
126 126
127 127 $ cd ..
128 128
129 129 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
130 130
131 131 $ mkdir invalidparent
132 132 $ cd invalidparent
133 133
134 134 $ hg clone --pull -q --config phases.publish=False ../a limit
135 135 $ hg clone --pull -q --config phases.publish=False ../a segv
136 136 $ rm -R limit/.hg/cache segv/.hg/cache
137 137
138 138 $ $PYTHON <<EOF
139 139 > data = open("limit/.hg/store/00changelog.i", "rb").read()
140 140 > for n, p in [('limit', '\0\0\0\x02'), ('segv', '\0\x01\0\0')]:
141 141 > # corrupt p1 at rev0 and p2 at rev1
142 142 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
143 143 > open(n + "/.hg/store/00changelog.i", "wb").write(d)
144 144 > EOF
145 145
146 146 $ hg -R limit debugindex -f1 -c
147 rev flag offset length size link p1 p2 nodeid
148 0 0000 0 63 62 0 2 -1 7c31755bf9b5
149 1 0000 63 66 65 1 0 2 26333235a41c
147 rev flag size link p1 p2 nodeid
148 0 0000 62 0 2 -1 7c31755bf9b5
149 1 0000 65 1 0 2 26333235a41c
150 150
151 151 $ hg -R limit debugdeltachain -c
152 152 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
153 153 0 1 1 -1 base 63 62 63 1.01613 63 0 0.00000
154 154 1 2 1 -1 base 66 65 66 1.01538 66 0 0.00000
155 155
156 156 $ hg -R segv debugindex -f1 -c
157 rev flag offset length size link p1 p2 nodeid
158 0 0000 0 63 62 0 65536 -1 7c31755bf9b5
159 1 0000 63 66 65 1 0 65536 26333235a41c
157 rev flag size link p1 p2 nodeid
158 0 0000 62 0 65536 -1 7c31755bf9b5
159 1 0000 65 1 0 65536 26333235a41c
160 160
161 161 $ hg -R segv debugdeltachain -c
162 162 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
163 163 0 1 1 -1 base 63 62 63 1.01613 63 0 0.00000
164 164 1 2 1 -1 base 66 65 66 1.01538 66 0 0.00000
165 165
166 166 $ cat <<EOF > test.py
167 167 > import sys
168 168 > from mercurial import changelog, vfs
169 169 > cl = changelog.changelog(vfs.vfs(sys.argv[1]))
170 170 > n0, n1 = cl.node(0), cl.node(1)
171 171 > ops = [
172 172 > ('reachableroots',
173 173 > lambda: cl.index.reachableroots2(0, [1], [0], False)),
174 174 > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])),
175 175 > ('index_headrevs', lambda: cl.headrevs()),
176 176 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)),
177 177 > ('find_deepest', lambda: cl.ancestor(n0, n1)),
178 178 > ]
179 179 > for l, f in ops:
180 180 > print l + ':',
181 181 > try:
182 182 > f()
183 183 > print 'uncaught buffer overflow?'
184 184 > except ValueError, inst:
185 185 > print inst
186 186 > EOF
187 187
188 188 $ $PYTHON test.py limit/.hg/store
189 189 reachableroots: parent out of range
190 190 compute_phases_map_sets: parent out of range
191 191 index_headrevs: parent out of range
192 192 find_gca_candidates: parent out of range
193 193 find_deepest: parent out of range
194 194 $ $PYTHON test.py segv/.hg/store
195 195 reachableroots: parent out of range
196 196 compute_phases_map_sets: parent out of range
197 197 index_headrevs: parent out of range
198 198 find_gca_candidates: parent out of range
199 199 find_deepest: parent out of range
200 200
201 201 $ cd ..
202 202
203 203 #endif
@@ -1,188 +1,188 b''
1 1 $ hg init
2 2
3 3 $ echo "[merge]" >> .hg/hgrc
4 4 $ echo "followcopies = 1" >> .hg/hgrc
5 5
6 6 $ echo foo > a
7 7 $ echo foo > a2
8 8 $ hg add a a2
9 9 $ hg ci -m "start"
10 10
11 11 $ hg mv a b
12 12 $ hg mv a2 b2
13 13 $ hg ci -m "rename"
14 14
15 15 $ hg co 0
16 16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
17 17
18 18 $ echo blahblah > a
19 19 $ echo blahblah > a2
20 20 $ hg mv a2 c2
21 21 $ hg ci -m "modify"
22 22 created new head
23 23
24 24 $ hg merge -y --debug
25 25 searching for copies back to rev 1
26 26 unmatched files in local:
27 27 c2
28 28 unmatched files in other:
29 29 b
30 30 b2
31 31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 32 src: 'a' -> dst: 'b' *
33 33 src: 'a2' -> dst: 'b2' !
34 34 src: 'a2' -> dst: 'c2' !
35 35 checking for directory renames
36 36 resolving manifests
37 37 branchmerge: True, force: False, partial: False
38 38 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
39 39 note: possible conflict - a2 was renamed multiple times to:
40 40 c2
41 41 b2
42 42 preserving a for resolve of b
43 43 removing a
44 44 b2: remote created -> g
45 45 getting b2
46 46 b: remote moved from a -> m (premerge)
47 47 picked tool ':merge' for b (binary False symlink False changedelete False)
48 48 merging a and b to b
49 49 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
50 50 premerge successful
51 51 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
52 52 (branch merge, don't forget to commit)
53 53
54 54 $ hg status -AC
55 55 M b
56 56 a
57 57 M b2
58 58 R a
59 59 C c2
60 60
61 61 $ cat b
62 62 blahblah
63 63
64 64 $ hg ci -m "merge"
65 65
66 66 $ hg debugindex b
67 rev offset length linkrev nodeid p1 p2
68 0 0 67 1 57eacc201a7f 000000000000 000000000000
69 1 67 72 3 4727ba907962 000000000000 57eacc201a7f
67 rev linkrev nodeid p1 p2
68 0 1 57eacc201a7f 000000000000 000000000000
69 1 3 4727ba907962 000000000000 57eacc201a7f
70 70
71 71 $ hg debugrename b
72 72 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
73 73
74 74 This used to trigger a "divergent renames" warning, despite no renames
75 75
76 76 $ hg cp b b3
77 77 $ hg cp b b4
78 78 $ hg ci -A -m 'copy b twice'
79 79 $ hg up eb92d88a9712
80 80 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
81 81 $ hg up
82 82 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 83 $ hg rm b3 b4
84 84 $ hg ci -m 'clean up a bit of our mess'
85 85
86 86 We'd rather not warn on divergent renames done in the same changeset (issue2113)
87 87
88 88 $ hg cp b b3
89 89 $ hg mv b b4
90 90 $ hg ci -A -m 'divergent renames in same changeset'
91 91 $ hg up c761c6948de0
92 92 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
93 93 $ hg up
94 94 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
95 95
96 96 Check for issue2642
97 97
98 98 $ hg init t
99 99 $ cd t
100 100
101 101 $ echo c0 > f1
102 102 $ hg ci -Aqm0
103 103
104 104 $ hg up null -q
105 105 $ echo c1 > f1 # backport
106 106 $ hg ci -Aqm1
107 107 $ hg mv f1 f2
108 108 $ hg ci -qm2
109 109
110 110 $ hg up 0 -q
111 111 $ hg merge 1 -q --tool internal:local
112 112 $ hg ci -qm3
113 113
114 114 $ hg merge 2
115 115 merging f1 and f2 to f2
116 116 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
117 117 (branch merge, don't forget to commit)
118 118
119 119 $ cat f2
120 120 c0
121 121
122 122 $ cd ..
123 123
124 124 Check for issue2089
125 125
126 126 $ hg init repo2089
127 127 $ cd repo2089
128 128
129 129 $ echo c0 > f1
130 130 $ hg ci -Aqm0
131 131
132 132 $ hg up null -q
133 133 $ echo c1 > f1
134 134 $ hg ci -Aqm1
135 135
136 136 $ hg up 0 -q
137 137 $ hg merge 1 -q --tool internal:local
138 138 $ echo c2 > f1
139 139 $ hg ci -qm2
140 140
141 141 $ hg up 1 -q
142 142 $ hg mv f1 f2
143 143 $ hg ci -Aqm3
144 144
145 145 $ hg up 2 -q
146 146 $ hg merge 3
147 147 merging f1 and f2 to f2
148 148 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
149 149 (branch merge, don't forget to commit)
150 150
151 151 $ cat f2
152 152 c2
153 153
154 154 $ cd ..
155 155
156 156 Check for issue3074
157 157
158 158 $ hg init repo3074
159 159 $ cd repo3074
160 160 $ echo foo > file
161 161 $ hg add file
162 162 $ hg commit -m "added file"
163 163 $ hg mv file newfile
164 164 $ hg commit -m "renamed file"
165 165 $ hg update 0
166 166 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
167 167 $ hg rm file
168 168 $ hg commit -m "deleted file"
169 169 created new head
170 170 $ hg merge --debug
171 171 searching for copies back to rev 1
172 172 unmatched files in other:
173 173 newfile
174 174 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
175 175 src: 'file' -> dst: 'newfile' %
176 176 checking for directory renames
177 177 resolving manifests
178 178 branchmerge: True, force: False, partial: False
179 179 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
180 180 note: possible conflict - file was deleted and renamed to:
181 181 newfile
182 182 newfile: remote created -> g
183 183 getting newfile
184 184 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
185 185 (branch merge, don't forget to commit)
186 186 $ hg status
187 187 M newfile
188 188 $ cd ..
@@ -1,23 +1,23 b''
1 1 $ hg init repo
2 2 $ cd repo
3 3
4 4 $ touch foo
5 5 $ hg ci -Am 'add foo'
6 6 adding foo
7 7
8 8 $ hg up -C null
9 9 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
10 10
11 11 this should be stored as a delta against rev 0
12 12
13 13 $ echo foo bar baz > foo
14 14 $ hg ci -Am 'add foo again'
15 15 adding foo
16 16 created new head
17 17
18 18 $ hg debugindex foo
19 rev offset length linkrev nodeid p1 p2
20 0 0 0 0 b80de5d13875 000000000000 000000000000
21 1 0 13 1 0376abec49b8 000000000000 000000000000
19 rev linkrev nodeid p1 p2
20 0 0 b80de5d13875 000000000000 000000000000
21 1 1 0376abec49b8 000000000000 000000000000
22 22
23 23 $ cd ..
@@ -1,47 +1,47 b''
1 1 $ hg init empty-repo
2 2 $ cd empty-repo
3 3
4 4 Flags on revlog version 0 are rejected
5 5
6 6 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
7 7 ... fh.write(b'\x00\x01\x00\x00')
8 8
9 9 $ hg log
10 10 abort: unknown flags (0x01) in version 0 revlog 00changelog.i!
11 11 [255]
12 12
13 13 Unknown flags on revlog version 1 are rejected
14 14
15 15 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
16 16 ... fh.write(b'\x00\x04\x00\x01')
17 17
18 18 $ hg log
19 19 abort: unknown flags (0x04) in version 1 revlog 00changelog.i!
20 20 [255]
21 21
22 22 Unknown version is rejected
23 23
24 24 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
25 25 ... fh.write(b'\x00\x00\x00\x02')
26 26
27 27 $ hg log
28 28 abort: unknown version (2) in revlog 00changelog.i!
29 29 [255]
30 30
31 31 $ cd ..
32 32
33 33 Test for CVE-2016-3630
34 34
35 35 $ hg init
36 36
37 37 >>> open("a.i", "wb").write(
38 38 ... b"""eJxjYGZgZIAAYQYGxhgom+k/FMx8YKx9ZUaKSOyqo4cnuKb8mbqHV5cBCVTMWb1Cwqkhe4Gsg9AD
39 39 ... Joa3dYtcYYYBAQ8Qr4OqZAYRICPTSr5WKd/42rV36d+8/VmrNpv7NP1jQAXrQE4BqQUARngwVA=="""
40 40 ... .decode("base64").decode("zlib"))
41 41
42 42 $ hg debugindex a.i
43 rev offset length linkrev nodeid p1 p2
44 0 0 19 2 99e0332bd498 000000000000 000000000000
45 1 19 12 3 6674f57a23d8 99e0332bd498 000000000000
43 rev linkrev nodeid p1 p2
44 0 2 99e0332bd498 000000000000 000000000000
45 1 3 6674f57a23d8 99e0332bd498 000000000000
46 46 $ hg debugdata a.i 1 2>&1 | egrep 'Error:.*decoded'
47 47 (mercurial\.\w+\.mpatch\.)?mpatchError: patch cannot be decoded (re)
@@ -1,143 +1,143 b''
1 1 test stripping of filelogs where the linkrev doesn't always increase
2 2
3 3 $ echo '[extensions]' >> $HGRCPATH
4 4 $ echo 'strip =' >> $HGRCPATH
5 5 $ hg init orig
6 6 $ cd orig
7 7 $ commit()
8 8 > {
9 9 > hg up -qC null
10 10 > count=1
11 11 > for i in "$@"; do
12 12 > for f in $i; do
13 13 > echo $count > $f
14 14 > done
15 15 > count=`expr $count + 1`
16 16 > done
17 17 > hg commit -qAm "$*"
18 18 > }
19 19
20 20 2 1 0 2 0 1 2
21 21
22 22 $ commit '201 210'
23 23 $ commit '102 120' '210'
24 24 $ commit '021'
25 25 $ commit '201' '021 120'
26 26 $ commit '012 021' '102 201' '120 210'
27 27 $ commit 'manifest-file'
28 28 $ commit '102 120' '012 210' '021 201'
29 29 $ commit '201 210' '021 120' '012 102'
30 30 $ HGUSER=another-user; export HGUSER
31 31 $ commit 'manifest-file'
32 32 $ commit '012' 'manifest-file'
33 33 $ cd ..
34 34 $ hg clone -q -U -r -1 -r -2 -r -3 -r -4 -r -6 orig crossed
35 35 $ cd crossed
36 36 $ hg debugindex --manifest
37 rev offset length linkrev nodeid p1 p2
38 0 0 112 0 6f105cbb914d 000000000000 000000000000
39 1 112 56 3 1b55917b3699 000000000000 000000000000
40 2 168 123 1 8f3d04e263e5 000000000000 000000000000
41 3 291 122 2 f0ef8726ac4f 000000000000 000000000000
42 4 413 87 4 0b76e38b4070 000000000000 000000000000
37 rev linkrev nodeid p1 p2
38 0 0 6f105cbb914d 000000000000 000000000000
39 1 3 1b55917b3699 000000000000 000000000000
40 2 1 8f3d04e263e5 000000000000 000000000000
41 3 2 f0ef8726ac4f 000000000000 000000000000
42 4 4 0b76e38b4070 000000000000 000000000000
43 43
44 44 $ for i in 012 021 102 120 201 210 manifest-file; do
45 45 > echo $i
46 46 > hg debugindex $i
47 47 > echo
48 48 > done
49 49 012
50 rev offset length linkrev nodeid p1 p2
51 0 0 3 0 b8e02f643373 000000000000 000000000000
52 1 3 3 1 5d9299349fc0 000000000000 000000000000
53 2 6 3 2 2661d26c6496 000000000000 000000000000
50 rev linkrev nodeid p1 p2
51 0 0 b8e02f643373 000000000000 000000000000
52 1 1 5d9299349fc0 000000000000 000000000000
53 2 2 2661d26c6496 000000000000 000000000000
54 54
55 55 021
56 rev offset length linkrev nodeid p1 p2
57 0 0 3 0 b8e02f643373 000000000000 000000000000
58 1 3 3 2 5d9299349fc0 000000000000 000000000000
59 2 6 3 1 2661d26c6496 000000000000 000000000000
56 rev linkrev nodeid p1 p2
57 0 0 b8e02f643373 000000000000 000000000000
58 1 2 5d9299349fc0 000000000000 000000000000
59 2 1 2661d26c6496 000000000000 000000000000
60 60
61 61 102
62 rev offset length linkrev nodeid p1 p2
63 0 0 3 1 b8e02f643373 000000000000 000000000000
64 1 3 3 0 5d9299349fc0 000000000000 000000000000
65 2 6 3 2 2661d26c6496 000000000000 000000000000
62 rev linkrev nodeid p1 p2
63 0 1 b8e02f643373 000000000000 000000000000
64 1 0 5d9299349fc0 000000000000 000000000000
65 2 2 2661d26c6496 000000000000 000000000000
66 66
67 67 120
68 rev offset length linkrev nodeid p1 p2
69 0 0 3 1 b8e02f643373 000000000000 000000000000
70 1 3 3 2 5d9299349fc0 000000000000 000000000000
71 2 6 3 0 2661d26c6496 000000000000 000000000000
68 rev linkrev nodeid p1 p2
69 0 1 b8e02f643373 000000000000 000000000000
70 1 2 5d9299349fc0 000000000000 000000000000
71 2 0 2661d26c6496 000000000000 000000000000
72 72
73 73 201
74 rev offset length linkrev nodeid p1 p2
75 0 0 3 2 b8e02f643373 000000000000 000000000000
76 1 3 3 0 5d9299349fc0 000000000000 000000000000
77 2 6 3 1 2661d26c6496 000000000000 000000000000
74 rev linkrev nodeid p1 p2
75 0 2 b8e02f643373 000000000000 000000000000
76 1 0 5d9299349fc0 000000000000 000000000000
77 2 1 2661d26c6496 000000000000 000000000000
78 78
79 79 210
80 rev offset length linkrev nodeid p1 p2
81 0 0 3 2 b8e02f643373 000000000000 000000000000
82 1 3 3 1 5d9299349fc0 000000000000 000000000000
83 2 6 3 0 2661d26c6496 000000000000 000000000000
80 rev linkrev nodeid p1 p2
81 0 2 b8e02f643373 000000000000 000000000000
82 1 1 5d9299349fc0 000000000000 000000000000
83 2 0 2661d26c6496 000000000000 000000000000
84 84
85 85 manifest-file
86 rev offset length linkrev nodeid p1 p2
87 0 0 3 3 b8e02f643373 000000000000 000000000000
88 1 3 3 4 5d9299349fc0 000000000000 000000000000
86 rev linkrev nodeid p1 p2
87 0 3 b8e02f643373 000000000000 000000000000
88 1 4 5d9299349fc0 000000000000 000000000000
89 89
90 90 $ cd ..
91 91 $ for i in 0 1 2 3 4; do
92 92 > hg clone -q -U --pull crossed $i
93 93 > echo "% Trying to strip revision $i"
94 94 > hg --cwd $i strip $i
95 95 > echo "% Verifying"
96 96 > hg --cwd $i verify
97 97 > echo
98 98 > done
99 99 % Trying to strip revision 0
100 100 saved backup bundle to $TESTTMP/0/.hg/strip-backup/*-backup.hg (glob)
101 101 % Verifying
102 102 checking changesets
103 103 checking manifests
104 104 crosschecking files in changesets and manifests
105 105 checking files
106 106 7 files, 4 changesets, 15 total revisions
107 107
108 108 % Trying to strip revision 1
109 109 saved backup bundle to $TESTTMP/1/.hg/strip-backup/*-backup.hg (glob)
110 110 % Verifying
111 111 checking changesets
112 112 checking manifests
113 113 crosschecking files in changesets and manifests
114 114 checking files
115 115 7 files, 4 changesets, 14 total revisions
116 116
117 117 % Trying to strip revision 2
118 118 saved backup bundle to $TESTTMP/2/.hg/strip-backup/*-backup.hg (glob)
119 119 % Verifying
120 120 checking changesets
121 121 checking manifests
122 122 crosschecking files in changesets and manifests
123 123 checking files
124 124 7 files, 4 changesets, 14 total revisions
125 125
126 126 % Trying to strip revision 3
127 127 saved backup bundle to $TESTTMP/3/.hg/strip-backup/*-backup.hg (glob)
128 128 % Verifying
129 129 checking changesets
130 130 checking manifests
131 131 crosschecking files in changesets and manifests
132 132 checking files
133 133 7 files, 4 changesets, 19 total revisions
134 134
135 135 % Trying to strip revision 4
136 136 saved backup bundle to $TESTTMP/4/.hg/strip-backup/*-backup.hg (glob)
137 137 % Verifying
138 138 checking changesets
139 139 checking manifests
140 140 crosschecking files in changesets and manifests
141 141 checking files
142 142 7 files, 4 changesets, 19 total revisions
143 143
@@ -1,876 +1,876 b''
1 1 #require killdaemons
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [format]
5 5 > usegeneraldelta=yes
6 6 > [ui]
7 7 > ssh=$PYTHON "$TESTDIR/dummyssh"
8 8 > EOF
9 9
10 10 Set up repo
11 11
12 12 $ hg --config experimental.treemanifest=True init repo
13 13 $ cd repo
14 14
15 15 Requirements get set on init
16 16
17 17 $ grep treemanifest .hg/requires
18 18 treemanifest
19 19
20 20 Without directories, looks like any other repo
21 21
22 22 $ echo 0 > a
23 23 $ echo 0 > b
24 24 $ hg ci -Aqm initial
25 25 $ hg debugdata -m 0
26 26 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
27 27 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
28 28
29 29 Submanifest is stored in separate revlog
30 30
31 31 $ mkdir dir1
32 32 $ echo 1 > dir1/a
33 33 $ echo 1 > dir1/b
34 34 $ echo 1 > e
35 35 $ hg ci -Aqm 'add dir1'
36 36 $ hg debugdata -m 1
37 37 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
38 38 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
39 39 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
40 40 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
41 41 $ hg debugdata --dir dir1 0
42 42 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
43 43 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
44 44
45 45 Can add nested directories
46 46
47 47 $ mkdir dir1/dir1
48 48 $ echo 2 > dir1/dir1/a
49 49 $ echo 2 > dir1/dir1/b
50 50 $ mkdir dir1/dir2
51 51 $ echo 2 > dir1/dir2/a
52 52 $ echo 2 > dir1/dir2/b
53 53 $ hg ci -Aqm 'add dir1/dir1'
54 54 $ hg files -r .
55 55 a
56 56 b
57 57 dir1/a
58 58 dir1/b
59 59 dir1/dir1/a
60 60 dir1/dir1/b
61 61 dir1/dir2/a
62 62 dir1/dir2/b
63 63 e
64 64
65 65 The manifest command works
66 66
67 67 $ hg manifest
68 68 a
69 69 b
70 70 dir1/a
71 71 dir1/b
72 72 dir1/dir1/a
73 73 dir1/dir1/b
74 74 dir1/dir2/a
75 75 dir1/dir2/b
76 76 e
77 77
78 78 Revision is not created for unchanged directory
79 79
80 80 $ mkdir dir2
81 81 $ echo 3 > dir2/a
82 82 $ hg add dir2
83 83 adding dir2/a
84 84 $ hg debugindex --dir dir1 > before
85 85 $ hg ci -qm 'add dir2'
86 86 $ hg debugindex --dir dir1 > after
87 87 $ diff before after
88 88 $ rm before after
89 89
90 90 Removing directory does not create an revlog entry
91 91
92 92 $ hg rm dir1/dir1
93 93 removing dir1/dir1/a
94 94 removing dir1/dir1/b
95 95 $ hg debugindex --dir dir1/dir1 > before
96 96 $ hg ci -qm 'remove dir1/dir1'
97 97 $ hg debugindex --dir dir1/dir1 > after
98 98 $ diff before after
99 99 $ rm before after
100 100
101 101 Check that hg files (calls treemanifest.walk()) works
102 102 without loading all directory revlogs
103 103
104 104 $ hg co 'desc("add dir2")'
105 105 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 106 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
107 107 $ hg files -r . dir1
108 108 dir1/a
109 109 dir1/b
110 110 dir1/dir1/a
111 111 dir1/dir1/b
112 112 dir1/dir2/a
113 113 dir1/dir2/b
114 114
115 115 Check that status between revisions works (calls treemanifest.matches())
116 116 without loading all directory revlogs
117 117
118 118 $ hg status --rev 'desc("add dir1")' --rev . dir1
119 119 A dir1/dir1/a
120 120 A dir1/dir1/b
121 121 A dir1/dir2/a
122 122 A dir1/dir2/b
123 123 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
124 124
125 125 Merge creates 2-parent revision of directory revlog
126 126
127 127 $ echo 5 > dir1/a
128 128 $ hg ci -Aqm 'modify dir1/a'
129 129 $ hg co '.^'
130 130 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 131 $ echo 6 > dir1/b
132 132 $ hg ci -Aqm 'modify dir1/b'
133 133 $ hg merge 'desc("modify dir1/a")'
134 134 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 135 (branch merge, don't forget to commit)
136 136 $ hg ci -m 'conflict-free merge involving dir1/'
137 137 $ cat dir1/a
138 138 5
139 139 $ cat dir1/b
140 140 6
141 141 $ hg debugindex --dir dir1
142 rev offset length linkrev nodeid p1 p2
143 0 0 54 1 8b3ffd73f901 000000000000 000000000000
144 1 54 68 2 68e9d057c5a8 8b3ffd73f901 000000000000
145 2 122 12 4 4698198d2624 68e9d057c5a8 000000000000
146 3 134 55 5 44844058ccce 68e9d057c5a8 000000000000
147 4 189 55 6 bf3d9b744927 68e9d057c5a8 000000000000
148 5 244 55 7 dde7c0af2a03 bf3d9b744927 44844058ccce
142 rev linkrev nodeid p1 p2
143 0 1 8b3ffd73f901 000000000000 000000000000
144 1 2 68e9d057c5a8 8b3ffd73f901 000000000000
145 2 4 4698198d2624 68e9d057c5a8 000000000000
146 3 5 44844058ccce 68e9d057c5a8 000000000000
147 4 6 bf3d9b744927 68e9d057c5a8 000000000000
148 5 7 dde7c0af2a03 bf3d9b744927 44844058ccce
149 149
150 150 Merge keeping directory from parent 1 does not create revlog entry. (Note that
151 151 dir1's manifest does change, but only because dir1/a's filelog changes.)
152 152
153 153 $ hg co 'desc("add dir2")'
154 154 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 155 $ echo 8 > dir2/a
156 156 $ hg ci -m 'modify dir2/a'
157 157 created new head
158 158
159 159 $ hg debugindex --dir dir2 > before
160 160 $ hg merge 'desc("modify dir1/a")'
161 161 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 162 (branch merge, don't forget to commit)
163 163 $ hg revert -r 'desc("modify dir2/a")' .
164 164 reverting dir1/a
165 165 $ hg ci -m 'merge, keeping parent 1'
166 166 $ hg debugindex --dir dir2 > after
167 167 $ diff before after
168 168 $ rm before after
169 169
170 170 Merge keeping directory from parent 2 does not create revlog entry. (Note that
171 171 dir2's manifest does change, but only because dir2/a's filelog changes.)
172 172
173 173 $ hg co 'desc("modify dir2/a")'
174 174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 175 $ hg debugindex --dir dir1 > before
176 176 $ hg merge 'desc("modify dir1/a")'
177 177 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 178 (branch merge, don't forget to commit)
179 179 $ hg revert -r 'desc("modify dir1/a")' .
180 180 reverting dir2/a
181 181 $ hg ci -m 'merge, keeping parent 2'
182 182 created new head
183 183 $ hg debugindex --dir dir1 > after
184 184 $ diff before after
185 185 $ rm before after
186 186
187 187 Create flat source repo for tests with mixed flat/tree manifests
188 188
189 189 $ cd ..
190 190 $ hg init repo-flat
191 191 $ cd repo-flat
192 192
193 193 Create a few commits with flat manifest
194 194
195 195 $ echo 0 > a
196 196 $ echo 0 > b
197 197 $ echo 0 > e
198 198 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
199 199 > do
200 200 > mkdir $d
201 201 > echo 0 > $d/a
202 202 > echo 0 > $d/b
203 203 > done
204 204 $ hg ci -Aqm initial
205 205
206 206 $ echo 1 > a
207 207 $ echo 1 > dir1/a
208 208 $ echo 1 > dir1/dir1/a
209 209 $ hg ci -Aqm 'modify on branch 1'
210 210
211 211 $ hg co 0
212 212 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 213 $ echo 2 > b
214 214 $ echo 2 > dir1/b
215 215 $ echo 2 > dir1/dir1/b
216 216 $ hg ci -Aqm 'modify on branch 2'
217 217
218 218 $ hg merge 1
219 219 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 220 (branch merge, don't forget to commit)
221 221 $ hg ci -m 'merge of flat manifests to new flat manifest'
222 222
223 223 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
224 224 $ cat hg.pid >> $DAEMON_PIDS
225 225
226 226 Create clone with tree manifests enabled
227 227
228 228 $ cd ..
229 229 $ hg clone --config experimental.treemanifest=1 \
230 230 > http://localhost:$HGPORT repo-mixed -r 1
231 231 adding changesets
232 232 adding manifests
233 233 adding file changes
234 234 added 2 changesets with 14 changes to 11 files
235 235 new changesets 5b02a3e8db7e:581ef6037d8b
236 236 updating to branch default
237 237 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 238 $ cd repo-mixed
239 239 $ test -d .hg/store/meta
240 240 [1]
241 241 $ grep treemanifest .hg/requires
242 242 treemanifest
243 243
244 244 Should be possible to push updates from flat to tree manifest repo
245 245
246 246 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
247 247 pushing to ssh://user@dummy/repo-mixed
248 248 searching for changes
249 249 remote: adding changesets
250 250 remote: adding manifests
251 251 remote: adding file changes
252 252 remote: added 2 changesets with 3 changes to 3 files
253 253
254 254 Commit should store revlog per directory
255 255
256 256 $ hg co 1
257 257 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 258 $ echo 3 > a
259 259 $ echo 3 > dir1/a
260 260 $ echo 3 > dir1/dir1/a
261 261 $ hg ci -m 'first tree'
262 262 created new head
263 263 $ find .hg/store/meta | sort
264 264 .hg/store/meta
265 265 .hg/store/meta/dir1
266 266 .hg/store/meta/dir1/00manifest.i
267 267 .hg/store/meta/dir1/dir1
268 268 .hg/store/meta/dir1/dir1/00manifest.i
269 269 .hg/store/meta/dir1/dir2
270 270 .hg/store/meta/dir1/dir2/00manifest.i
271 271 .hg/store/meta/dir2
272 272 .hg/store/meta/dir2/00manifest.i
273 273
274 274 Merge of two trees
275 275
276 276 $ hg co 2
277 277 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 278 $ hg merge 1
279 279 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 280 (branch merge, don't forget to commit)
281 281 $ hg ci -m 'merge of flat manifests to new tree manifest'
282 282 created new head
283 283 $ hg diff -r 3
284 284
285 285 Parent of tree root manifest should be flat manifest, and two for merge
286 286
287 287 $ hg debugindex -m
288 rev offset length linkrev nodeid p1 p2
289 0 0 80 0 40536115ed9e 000000000000 000000000000
290 1 80 83 1 f3376063c255 40536115ed9e 000000000000
291 2 163 89 2 5d9b9da231a2 40536115ed9e 000000000000
292 3 252 83 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
293 4 335 124 4 51e32a8c60ee f3376063c255 000000000000
294 5 459 126 5 cc5baa78b230 5d9b9da231a2 f3376063c255
288 rev linkrev nodeid p1 p2
289 0 0 40536115ed9e 000000000000 000000000000
290 1 1 f3376063c255 40536115ed9e 000000000000
291 2 2 5d9b9da231a2 40536115ed9e 000000000000
292 3 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
293 4 4 51e32a8c60ee f3376063c255 000000000000
294 5 5 cc5baa78b230 5d9b9da231a2 f3376063c255
295 295
296 296
297 297 Status across flat/tree boundary should work
298 298
299 299 $ hg status --rev '.^' --rev .
300 300 M a
301 301 M dir1/a
302 302 M dir1/dir1/a
303 303
304 304
305 305 Turning off treemanifest config has no effect
306 306
307 307 $ hg debugindex --dir dir1
308 rev offset length linkrev nodeid p1 p2
309 0 0 127 4 064927a0648a 000000000000 000000000000
310 1 127 111 5 25ecb8cb8618 000000000000 000000000000
308 rev linkrev nodeid p1 p2
309 0 4 064927a0648a 000000000000 000000000000
310 1 5 25ecb8cb8618 000000000000 000000000000
311 311 $ echo 2 > dir1/a
312 312 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
313 313 $ hg debugindex --dir dir1
314 rev offset length linkrev nodeid p1 p2
315 0 0 127 4 064927a0648a 000000000000 000000000000
316 1 127 111 5 25ecb8cb8618 000000000000 000000000000
317 2 238 55 6 5b16163a30c6 25ecb8cb8618 000000000000
314 rev linkrev nodeid p1 p2
315 0 4 064927a0648a 000000000000 000000000000
316 1 5 25ecb8cb8618 000000000000 000000000000
317 2 6 5b16163a30c6 25ecb8cb8618 000000000000
318 318
319 319 Stripping and recovering changes should work
320 320
321 321 $ hg st --change tip
322 322 M dir1/a
323 323 $ hg --config extensions.strip= strip tip
324 324 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
325 325 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg
326 326 $ hg debugindex --dir dir1
327 rev offset length linkrev nodeid p1 p2
328 0 0 127 4 064927a0648a 000000000000 000000000000
329 1 127 111 5 25ecb8cb8618 000000000000 000000000000
327 rev linkrev nodeid p1 p2
328 0 4 064927a0648a 000000000000 000000000000
329 1 5 25ecb8cb8618 000000000000 000000000000
330 330 $ hg incoming .hg/strip-backup/*
331 331 comparing with .hg/strip-backup/*-backup.hg (glob)
332 332 searching for changes
333 333 changeset: 6:51cfd7b1e13b
334 334 tag: tip
335 335 user: test
336 336 date: Thu Jan 01 00:00:00 1970 +0000
337 337 summary: modify dir1/a
338 338
339 339 $ hg pull .hg/strip-backup/*
340 340 pulling from .hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg
341 341 searching for changes
342 342 adding changesets
343 343 adding manifests
344 344 adding file changes
345 345 added 1 changesets with 1 changes to 1 files
346 346 new changesets 51cfd7b1e13b
347 347 (run 'hg update' to get a working copy)
348 348 $ hg --config extensions.strip= strip tip
349 349 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/*-backup.hg (glob)
350 350 $ hg unbundle -q .hg/strip-backup/*
351 351 $ hg debugindex --dir dir1
352 rev offset length linkrev nodeid p1 p2
353 0 0 127 4 064927a0648a 000000000000 000000000000
354 1 127 111 5 25ecb8cb8618 000000000000 000000000000
355 2 238 55 6 5b16163a30c6 25ecb8cb8618 000000000000
352 rev linkrev nodeid p1 p2
353 0 4 064927a0648a 000000000000 000000000000
354 1 5 25ecb8cb8618 000000000000 000000000000
355 2 6 5b16163a30c6 25ecb8cb8618 000000000000
356 356 $ hg st --change tip
357 357 M dir1/a
358 358
359 359 Shelving and unshelving should work
360 360
361 361 $ echo foo >> dir1/a
362 362 $ hg --config extensions.shelve= shelve
363 363 shelved as default
364 364 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
365 365 $ hg --config extensions.shelve= unshelve
366 366 unshelving change 'default'
367 367 $ hg diff --nodates
368 368 diff -r 708a273da119 dir1/a
369 369 --- a/dir1/a
370 370 +++ b/dir1/a
371 371 @@ -1,1 +1,2 @@
372 372 1
373 373 +foo
374 374
375 375 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
376 376
377 377 $ cd ..
378 378 $ hg init empty-repo
379 379 $ cat << EOF >> empty-repo/.hg/hgrc
380 380 > [experimental]
381 381 > changegroup3=yes
382 382 > EOF
383 383 $ grep treemanifest empty-repo/.hg/requires
384 384 [1]
385 385 $ hg push -R repo -r 0 empty-repo
386 386 pushing to empty-repo
387 387 searching for changes
388 388 adding changesets
389 389 adding manifests
390 390 adding file changes
391 391 added 1 changesets with 2 changes to 2 files
392 392 $ grep treemanifest empty-repo/.hg/requires
393 393 treemanifest
394 394
395 395 Pushing to an empty repo works
396 396
397 397 $ hg --config experimental.treemanifest=1 init clone
398 398 $ grep treemanifest clone/.hg/requires
399 399 treemanifest
400 400 $ hg push -R repo clone
401 401 pushing to clone
402 402 searching for changes
403 403 adding changesets
404 404 adding manifests
405 405 adding file changes
406 406 added 11 changesets with 15 changes to 10 files (+3 heads)
407 407 $ grep treemanifest clone/.hg/requires
408 408 treemanifest
409 409 $ hg -R clone verify
410 410 checking changesets
411 411 checking manifests
412 412 checking directory manifests
413 413 crosschecking files in changesets and manifests
414 414 checking files
415 415 10 files, 11 changesets, 15 total revisions
416 416
417 417 Create deeper repo with tree manifests.
418 418
419 419 $ hg --config experimental.treemanifest=True init deeprepo
420 420 $ cd deeprepo
421 421
422 422 $ mkdir .A
423 423 $ mkdir b
424 424 $ mkdir b/bar
425 425 $ mkdir b/bar/orange
426 426 $ mkdir b/bar/orange/fly
427 427 $ mkdir b/foo
428 428 $ mkdir b/foo/apple
429 429 $ mkdir b/foo/apple/bees
430 430
431 431 $ touch .A/one.txt
432 432 $ touch .A/two.txt
433 433 $ touch b/bar/fruits.txt
434 434 $ touch b/bar/orange/fly/gnat.py
435 435 $ touch b/bar/orange/fly/housefly.txt
436 436 $ touch b/foo/apple/bees/flower.py
437 437 $ touch c.txt
438 438 $ touch d.py
439 439
440 440 $ hg ci -Aqm 'initial'
441 441
442 442 $ echo >> .A/one.txt
443 443 $ echo >> .A/two.txt
444 444 $ echo >> b/bar/fruits.txt
445 445 $ echo >> b/bar/orange/fly/gnat.py
446 446 $ echo >> b/bar/orange/fly/housefly.txt
447 447 $ echo >> b/foo/apple/bees/flower.py
448 448 $ echo >> c.txt
449 449 $ echo >> d.py
450 450 $ hg ci -Aqm 'second'
451 451
452 452 We'll see that visitdir works by removing some treemanifest revlogs and running
453 453 the files command with various parameters.
454 454
455 455 Test files from the root.
456 456
457 457 $ hg files -r .
458 458 .A/one.txt
459 459 .A/two.txt
460 460 b/bar/fruits.txt
461 461 b/bar/orange/fly/gnat.py
462 462 b/bar/orange/fly/housefly.txt
463 463 b/foo/apple/bees/flower.py
464 464 c.txt
465 465 d.py
466 466
467 467 Excludes with a glob should not exclude everything from the glob's root
468 468
469 469 $ hg files -r . -X 'b/fo?' b
470 470 b/bar/fruits.txt
471 471 b/bar/orange/fly/gnat.py
472 472 b/bar/orange/fly/housefly.txt
473 473 $ cp -R .hg/store .hg/store-copy
474 474
475 475 Test files for a subdirectory.
476 476
477 477 $ rm -r .hg/store/meta/~2e_a
478 478 $ hg files -r . b
479 479 b/bar/fruits.txt
480 480 b/bar/orange/fly/gnat.py
481 481 b/bar/orange/fly/housefly.txt
482 482 b/foo/apple/bees/flower.py
483 483 $ hg diff -r '.^' -r . --stat b
484 484 b/bar/fruits.txt | 1 +
485 485 b/bar/orange/fly/gnat.py | 1 +
486 486 b/bar/orange/fly/housefly.txt | 1 +
487 487 b/foo/apple/bees/flower.py | 1 +
488 488 4 files changed, 4 insertions(+), 0 deletions(-)
489 489 $ cp -R .hg/store-copy/. .hg/store
490 490
491 491 Test files with just includes and excludes.
492 492
493 493 $ rm -r .hg/store/meta/~2e_a
494 494 $ rm -r .hg/store/meta/b/bar/orange/fly
495 495 $ rm -r .hg/store/meta/b/foo/apple/bees
496 496 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
497 497 b/bar/fruits.txt
498 498 $ hg diff -r '.^' -r . --stat -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
499 499 b/bar/fruits.txt | 1 +
500 500 1 files changed, 1 insertions(+), 0 deletions(-)
501 501 $ cp -R .hg/store-copy/. .hg/store
502 502
503 503 Test files for a subdirectory, excluding a directory within it.
504 504
505 505 $ rm -r .hg/store/meta/~2e_a
506 506 $ rm -r .hg/store/meta/b/foo
507 507 $ hg files -r . -X path:b/foo b
508 508 b/bar/fruits.txt
509 509 b/bar/orange/fly/gnat.py
510 510 b/bar/orange/fly/housefly.txt
511 511 $ hg diff -r '.^' -r . --stat -X path:b/foo b
512 512 b/bar/fruits.txt | 1 +
513 513 b/bar/orange/fly/gnat.py | 1 +
514 514 b/bar/orange/fly/housefly.txt | 1 +
515 515 3 files changed, 3 insertions(+), 0 deletions(-)
516 516 $ cp -R .hg/store-copy/. .hg/store
517 517
518 518 Test files for a sub directory, including only a directory within it, and
519 519 including an unrelated directory.
520 520
521 521 $ rm -r .hg/store/meta/~2e_a
522 522 $ rm -r .hg/store/meta/b/foo
523 523 $ hg files -r . -I path:b/bar/orange -I path:a b
524 524 b/bar/orange/fly/gnat.py
525 525 b/bar/orange/fly/housefly.txt
526 526 $ hg diff -r '.^' -r . --stat -I path:b/bar/orange -I path:a b
527 527 b/bar/orange/fly/gnat.py | 1 +
528 528 b/bar/orange/fly/housefly.txt | 1 +
529 529 2 files changed, 2 insertions(+), 0 deletions(-)
530 530 $ cp -R .hg/store-copy/. .hg/store
531 531
532 532 Test files for a pattern, including a directory, and excluding a directory
533 533 within that.
534 534
535 535 $ rm -r .hg/store/meta/~2e_a
536 536 $ rm -r .hg/store/meta/b/foo
537 537 $ rm -r .hg/store/meta/b/bar/orange
538 538 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
539 539 b/bar/fruits.txt
540 540 $ hg diff -r '.^' -r . --stat glob:**.txt -I path:b/bar -X path:b/bar/orange
541 541 b/bar/fruits.txt | 1 +
542 542 1 files changed, 1 insertions(+), 0 deletions(-)
543 543 $ cp -R .hg/store-copy/. .hg/store
544 544
545 545 Add some more changes to the deep repo
546 546 $ echo narf >> b/bar/fruits.txt
547 547 $ hg ci -m narf
548 548 $ echo troz >> b/bar/orange/fly/gnat.py
549 549 $ hg ci -m troz
550 550
551 551 Verify works
552 552 $ hg verify
553 553 checking changesets
554 554 checking manifests
555 555 checking directory manifests
556 556 crosschecking files in changesets and manifests
557 557 checking files
558 558 8 files, 4 changesets, 18 total revisions
559 559
560 560 Dirlogs are included in fncache
561 561 $ grep meta/.A/00manifest.i .hg/store/fncache
562 562 meta/.A/00manifest.i
563 563
564 564 Rebuilt fncache includes dirlogs
565 565 $ rm .hg/store/fncache
566 566 $ hg debugrebuildfncache
567 567 adding data/.A/one.txt.i
568 568 adding data/.A/two.txt.i
569 569 adding data/b/bar/fruits.txt.i
570 570 adding data/b/bar/orange/fly/gnat.py.i
571 571 adding data/b/bar/orange/fly/housefly.txt.i
572 572 adding data/b/foo/apple/bees/flower.py.i
573 573 adding data/c.txt.i
574 574 adding data/d.py.i
575 575 adding meta/.A/00manifest.i
576 576 adding meta/b/00manifest.i
577 577 adding meta/b/bar/00manifest.i
578 578 adding meta/b/bar/orange/00manifest.i
579 579 adding meta/b/bar/orange/fly/00manifest.i
580 580 adding meta/b/foo/00manifest.i
581 581 adding meta/b/foo/apple/00manifest.i
582 582 adding meta/b/foo/apple/bees/00manifest.i
583 583 16 items added, 0 removed from fncache
584 584
585 585 Finish first server
586 586 $ killdaemons.py
587 587
588 588 Back up the recently added revlogs
589 589 $ cp -R .hg/store .hg/store-newcopy
590 590
591 591 Verify reports missing dirlog
592 592 $ rm .hg/store/meta/b/00manifest.*
593 593 $ hg verify
594 594 checking changesets
595 595 checking manifests
596 596 checking directory manifests
597 597 0: empty or missing b/
598 598 b/@0: parent-directory manifest refers to unknown revision 67688a370455
599 599 b/@1: parent-directory manifest refers to unknown revision f065da70369e
600 600 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
601 601 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
602 602 warning: orphan revlog 'meta/b/bar/00manifest.i'
603 603 warning: orphan revlog 'meta/b/bar/orange/00manifest.i'
604 604 warning: orphan revlog 'meta/b/bar/orange/fly/00manifest.i'
605 605 warning: orphan revlog 'meta/b/foo/00manifest.i'
606 606 warning: orphan revlog 'meta/b/foo/apple/00manifest.i'
607 607 warning: orphan revlog 'meta/b/foo/apple/bees/00manifest.i'
608 608 crosschecking files in changesets and manifests
609 609 b/bar/fruits.txt@0: in changeset but not in manifest
610 610 b/bar/orange/fly/gnat.py@0: in changeset but not in manifest
611 611 b/bar/orange/fly/housefly.txt@0: in changeset but not in manifest
612 612 b/foo/apple/bees/flower.py@0: in changeset but not in manifest
613 613 checking files
614 614 8 files, 4 changesets, 18 total revisions
615 615 6 warnings encountered!
616 616 9 integrity errors encountered!
617 617 (first damaged changeset appears to be 0)
618 618 [1]
619 619 $ cp -R .hg/store-newcopy/. .hg/store
620 620
621 621 Verify reports missing dirlog entry
622 622 $ mv -f .hg/store-copy/meta/b/00manifest.* .hg/store/meta/b/
623 623 $ hg verify
624 624 checking changesets
625 625 checking manifests
626 626 checking directory manifests
627 627 b/@2: parent-directory manifest refers to unknown revision ac0d30948e0b
628 628 b/@3: parent-directory manifest refers to unknown revision 367152e6af28
629 629 b/bar/@?: rev 2 points to unexpected changeset 2
630 630 b/bar/@?: 44d7e1146e0d not in parent-directory manifest
631 631 b/bar/@?: rev 3 points to unexpected changeset 3
632 632 b/bar/@?: 70b10c6b17b7 not in parent-directory manifest
633 633 b/bar/orange/@?: rev 2 points to unexpected changeset 3
634 634 (expected None)
635 635 b/bar/orange/fly/@?: rev 2 points to unexpected changeset 3
636 636 (expected None)
637 637 crosschecking files in changesets and manifests
638 638 checking files
639 639 8 files, 4 changesets, 18 total revisions
640 640 2 warnings encountered!
641 641 8 integrity errors encountered!
642 642 (first damaged changeset appears to be 2)
643 643 [1]
644 644 $ cp -R .hg/store-newcopy/. .hg/store
645 645
646 646 Test cloning a treemanifest repo over http.
647 647 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
648 648 $ cat hg.pid >> $DAEMON_PIDS
649 649 $ cd ..
650 650 We can clone even with the knob turned off and we'll get a treemanifest repo.
651 651 $ hg clone --config experimental.treemanifest=False \
652 652 > --config experimental.changegroup3=True \
653 653 > http://localhost:$HGPORT deepclone
654 654 requesting all changes
655 655 adding changesets
656 656 adding manifests
657 657 adding file changes
658 658 added 4 changesets with 18 changes to 8 files
659 659 new changesets 775704be6f52:523e5c631710
660 660 updating to branch default
661 661 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
662 662 No server errors.
663 663 $ cat deeprepo/errors.log
664 664 requires got updated to include treemanifest
665 665 $ cat deepclone/.hg/requires | grep treemanifest
666 666 treemanifest
667 667 Tree manifest revlogs exist.
668 668 $ find deepclone/.hg/store/meta | sort
669 669 deepclone/.hg/store/meta
670 670 deepclone/.hg/store/meta/b
671 671 deepclone/.hg/store/meta/b/00manifest.i
672 672 deepclone/.hg/store/meta/b/bar
673 673 deepclone/.hg/store/meta/b/bar/00manifest.i
674 674 deepclone/.hg/store/meta/b/bar/orange
675 675 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
676 676 deepclone/.hg/store/meta/b/bar/orange/fly
677 677 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
678 678 deepclone/.hg/store/meta/b/foo
679 679 deepclone/.hg/store/meta/b/foo/00manifest.i
680 680 deepclone/.hg/store/meta/b/foo/apple
681 681 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
682 682 deepclone/.hg/store/meta/b/foo/apple/bees
683 683 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
684 684 deepclone/.hg/store/meta/~2e_a
685 685 deepclone/.hg/store/meta/~2e_a/00manifest.i
686 686 Verify passes.
687 687 $ cd deepclone
688 688 $ hg verify
689 689 checking changesets
690 690 checking manifests
691 691 checking directory manifests
692 692 crosschecking files in changesets and manifests
693 693 checking files
694 694 8 files, 4 changesets, 18 total revisions
695 695 $ cd ..
696 696
697 697 Create clones using old repo formats to use in later tests
698 698 $ hg clone --config format.usestore=False \
699 699 > --config experimental.changegroup3=True \
700 700 > http://localhost:$HGPORT deeprepo-basicstore
701 701 requesting all changes
702 702 adding changesets
703 703 adding manifests
704 704 adding file changes
705 705 added 4 changesets with 18 changes to 8 files
706 706 new changesets 775704be6f52:523e5c631710
707 707 updating to branch default
708 708 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
709 709 $ cd deeprepo-basicstore
710 710 $ grep store .hg/requires
711 711 [1]
712 712 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --errorlog=errors.log
713 713 $ cat hg.pid >> $DAEMON_PIDS
714 714 $ cd ..
715 715 $ hg clone --config format.usefncache=False \
716 716 > --config experimental.changegroup3=True \
717 717 > http://localhost:$HGPORT deeprepo-encodedstore
718 718 requesting all changes
719 719 adding changesets
720 720 adding manifests
721 721 adding file changes
722 722 added 4 changesets with 18 changes to 8 files
723 723 new changesets 775704be6f52:523e5c631710
724 724 updating to branch default
725 725 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
726 726 $ cd deeprepo-encodedstore
727 727 $ grep fncache .hg/requires
728 728 [1]
729 729 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
730 730 $ cat hg.pid >> $DAEMON_PIDS
731 731 $ cd ..
732 732
733 733 Local clone with basicstore
734 734 $ hg clone -U deeprepo-basicstore local-clone-basicstore
735 735 $ hg -R local-clone-basicstore verify
736 736 checking changesets
737 737 checking manifests
738 738 checking directory manifests
739 739 crosschecking files in changesets and manifests
740 740 checking files
741 741 8 files, 4 changesets, 18 total revisions
742 742
743 743 Local clone with encodedstore
744 744 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
745 745 $ hg -R local-clone-encodedstore verify
746 746 checking changesets
747 747 checking manifests
748 748 checking directory manifests
749 749 crosschecking files in changesets and manifests
750 750 checking files
751 751 8 files, 4 changesets, 18 total revisions
752 752
753 753 Local clone with fncachestore
754 754 $ hg clone -U deeprepo local-clone-fncachestore
755 755 $ hg -R local-clone-fncachestore verify
756 756 checking changesets
757 757 checking manifests
758 758 checking directory manifests
759 759 crosschecking files in changesets and manifests
760 760 checking files
761 761 8 files, 4 changesets, 18 total revisions
762 762
763 763 Stream clone with basicstore
764 764 $ hg clone --config experimental.changegroup3=True --stream -U \
765 765 > http://localhost:$HGPORT1 stream-clone-basicstore
766 766 streaming all changes
767 767 18 files to transfer, * of data (glob)
768 768 transferred * in * seconds (*) (glob)
769 769 searching for changes
770 770 no changes found
771 771 $ hg -R stream-clone-basicstore verify
772 772 checking changesets
773 773 checking manifests
774 774 checking directory manifests
775 775 crosschecking files in changesets and manifests
776 776 checking files
777 777 8 files, 4 changesets, 18 total revisions
778 778
779 779 Stream clone with encodedstore
780 780 $ hg clone --config experimental.changegroup3=True --stream -U \
781 781 > http://localhost:$HGPORT2 stream-clone-encodedstore
782 782 streaming all changes
783 783 18 files to transfer, * of data (glob)
784 784 transferred * in * seconds (*) (glob)
785 785 searching for changes
786 786 no changes found
787 787 $ hg -R stream-clone-encodedstore verify
788 788 checking changesets
789 789 checking manifests
790 790 checking directory manifests
791 791 crosschecking files in changesets and manifests
792 792 checking files
793 793 8 files, 4 changesets, 18 total revisions
794 794
795 795 Stream clone with fncachestore
796 796 $ hg clone --config experimental.changegroup3=True --stream -U \
797 797 > http://localhost:$HGPORT stream-clone-fncachestore
798 798 streaming all changes
799 799 18 files to transfer, * of data (glob)
800 800 transferred * in * seconds (*) (glob)
801 801 searching for changes
802 802 no changes found
803 803 $ hg -R stream-clone-fncachestore verify
804 804 checking changesets
805 805 checking manifests
806 806 checking directory manifests
807 807 crosschecking files in changesets and manifests
808 808 checking files
809 809 8 files, 4 changesets, 18 total revisions
810 810
811 811 Packed bundle
812 812 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
813 813 writing 5330 bytes for 18 files
814 814 bundle requirements: generaldelta, revlogv1, treemanifest
815 815 $ hg debugbundle --spec repo-packed.hg
816 816 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Ctreemanifest
817 817
818 818 Bundle with changegroup2 is not supported
819 819
820 820 $ hg -R deeprepo bundle --all -t v2 deeprepo.bundle
821 821 abort: repository does not support bundle version 02
822 822 [255]
823 823
824 824 Pull does not include changegroup for manifest the client already has from
825 825 other branch
826 826
827 827 $ mkdir grafted-dir-repo
828 828 $ cd grafted-dir-repo
829 829 $ hg --config experimental.treemanifest=1 init
830 830 $ mkdir dir
831 831 $ echo a > dir/file
832 832 $ echo a > file
833 833 $ hg ci -Am initial
834 834 adding dir/file
835 835 adding file
836 836 $ echo b > dir/file
837 837 $ hg ci -m updated
838 838 $ hg co '.^'
839 839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
840 840 $ hg revert -r tip dir/
841 841 reverting dir/file
842 842 $ echo b > file # to make sure root manifest is sent
843 843 $ hg ci -m grafted
844 844 created new head
845 845 $ cd ..
846 846
847 847 $ hg --config experimental.treemanifest=1 clone --pull -r 1 \
848 848 > grafted-dir-repo grafted-dir-repo-clone
849 849 adding changesets
850 850 adding manifests
851 851 adding file changes
852 852 added 2 changesets with 3 changes to 2 files
853 853 new changesets d84f4c419457:09ab742f3b0f
854 854 updating to branch default
855 855 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
856 856 $ cd grafted-dir-repo-clone
857 857 $ hg pull -r 2
858 858 pulling from $TESTTMP/grafted-dir-repo
859 859 searching for changes
860 860 adding changesets
861 861 adding manifests
862 862 adding file changes
863 863 added 1 changesets with 1 changes to 1 files (+1 heads)
864 864 new changesets 73699489fb7c
865 865 (run 'hg heads' to see heads, 'hg merge' to merge)
866 866
867 867 Committing a empty commit does not duplicate root treemanifest
868 868 $ echo z >> z
869 869 $ hg commit -Aqm 'pre-empty commit'
870 870 $ hg rm z
871 871 $ hg commit --amend -m 'empty commit'
872 872 saved backup bundle to $TESTTMP/grafted-dir-repo-clone/.hg/strip-backup/cb99d5717cea-9e3b6b02-amend.hg
873 873 $ hg log -r 'tip + tip^' -T '{manifest}\n'
874 874 1:678d3574b88c
875 875 1:678d3574b88c
876 876 $ hg --config extensions.strip= strip -r . -q
General Comments 0
You need to be logged in to leave comments. Login now