##// END OF EJS Templates
revset: evaluate filesets against each revision for 'file()' (issue5778)...
Matt Harbison -
r35835:f6ca1e11 stable
parent child Browse files
Show More
@@ -1,2226 +1,2236 b''
1 1 # revset.py - revision set queries for mercurial
2 2 #
3 3 # Copyright 2010 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 re
11 11
12 12 from .i18n import _
13 13 from . import (
14 14 dagop,
15 15 destutil,
16 16 encoding,
17 17 error,
18 18 hbisect,
19 19 match as matchmod,
20 20 node,
21 21 obsolete as obsmod,
22 22 obsutil,
23 23 pathutil,
24 24 phases,
25 25 pycompat,
26 26 registrar,
27 27 repoview,
28 28 revsetlang,
29 29 scmutil,
30 30 smartset,
31 31 util,
32 32 )
33 33
34 34 # helpers for processing parsed tree
35 35 getsymbol = revsetlang.getsymbol
36 36 getstring = revsetlang.getstring
37 37 getinteger = revsetlang.getinteger
38 38 getboolean = revsetlang.getboolean
39 39 getlist = revsetlang.getlist
40 40 getrange = revsetlang.getrange
41 41 getargs = revsetlang.getargs
42 42 getargsdict = revsetlang.getargsdict
43 43
44 44 baseset = smartset.baseset
45 45 generatorset = smartset.generatorset
46 46 spanset = smartset.spanset
47 47 fullreposet = smartset.fullreposet
48 48
49 49 # Constants for ordering requirement, used in getset():
50 50 #
51 51 # If 'define', any nested functions and operations MAY change the ordering of
52 52 # the entries in the set (but if changes the ordering, it MUST ALWAYS change
53 53 # it). If 'follow', any nested functions and operations MUST take the ordering
54 54 # specified by the first operand to the '&' operator.
55 55 #
56 56 # For instance,
57 57 #
58 58 # X & (Y | Z)
59 59 # ^ ^^^^^^^
60 60 # | follow
61 61 # define
62 62 #
63 63 # will be evaluated as 'or(y(x()), z(x()))', where 'x()' can change the order
64 64 # of the entries in the set, but 'y()', 'z()' and 'or()' shouldn't.
65 65 #
66 66 # 'any' means the order doesn't matter. For instance,
67 67 #
68 68 # (X & !Y) | ancestors(Z)
69 69 # ^ ^
70 70 # any any
71 71 #
72 72 # For 'X & !Y', 'X' decides the order and 'Y' is subtracted from 'X', so the
73 73 # order of 'Y' does not matter. For 'ancestors(Z)', Z's order does not matter
74 74 # since 'ancestors' does not care about the order of its argument.
75 75 #
76 76 # Currently, most revsets do not care about the order, so 'define' is
77 77 # equivalent to 'follow' for them, and the resulting order is based on the
78 78 # 'subset' parameter passed down to them:
79 79 #
80 80 # m = revset.match(...)
81 81 # m(repo, subset, order=defineorder)
82 82 # ^^^^^^
83 83 # For most revsets, 'define' means using the order this subset provides
84 84 #
85 85 # There are a few revsets that always redefine the order if 'define' is
86 86 # specified: 'sort(X)', 'reverse(X)', 'x:y'.
87 87 anyorder = 'any' # don't care the order, could be even random-shuffled
88 88 defineorder = 'define' # ALWAYS redefine, or ALWAYS follow the current order
89 89 followorder = 'follow' # MUST follow the current order
90 90
91 91 # helpers
92 92
93 93 def getset(repo, subset, x, order=defineorder):
94 94 if not x:
95 95 raise error.ParseError(_("missing argument"))
96 96 return methods[x[0]](repo, subset, *x[1:], order=order)
97 97
98 98 def _getrevsource(repo, r):
99 99 extra = repo[r].extra()
100 100 for label in ('source', 'transplant_source', 'rebase_source'):
101 101 if label in extra:
102 102 try:
103 103 return repo[extra[label]].rev()
104 104 except error.RepoLookupError:
105 105 pass
106 106 return None
107 107
108 108 # operator methods
109 109
110 110 def stringset(repo, subset, x, order):
111 111 x = scmutil.intrev(repo[x])
112 112 if (x in subset
113 113 or x == node.nullrev and isinstance(subset, fullreposet)):
114 114 return baseset([x])
115 115 return baseset()
116 116
117 117 def rangeset(repo, subset, x, y, order):
118 118 m = getset(repo, fullreposet(repo), x)
119 119 n = getset(repo, fullreposet(repo), y)
120 120
121 121 if not m or not n:
122 122 return baseset()
123 123 return _makerangeset(repo, subset, m.first(), n.last(), order)
124 124
125 125 def rangeall(repo, subset, x, order):
126 126 assert x is None
127 127 return _makerangeset(repo, subset, 0, repo.changelog.tiprev(), order)
128 128
129 129 def rangepre(repo, subset, y, order):
130 130 # ':y' can't be rewritten to '0:y' since '0' may be hidden
131 131 n = getset(repo, fullreposet(repo), y)
132 132 if not n:
133 133 return baseset()
134 134 return _makerangeset(repo, subset, 0, n.last(), order)
135 135
136 136 def rangepost(repo, subset, x, order):
137 137 m = getset(repo, fullreposet(repo), x)
138 138 if not m:
139 139 return baseset()
140 140 return _makerangeset(repo, subset, m.first(), repo.changelog.tiprev(),
141 141 order)
142 142
143 143 def _makerangeset(repo, subset, m, n, order):
144 144 if m == n:
145 145 r = baseset([m])
146 146 elif n == node.wdirrev:
147 147 r = spanset(repo, m, len(repo)) + baseset([n])
148 148 elif m == node.wdirrev:
149 149 r = baseset([m]) + spanset(repo, repo.changelog.tiprev(), n - 1)
150 150 elif m < n:
151 151 r = spanset(repo, m, n + 1)
152 152 else:
153 153 r = spanset(repo, m, n - 1)
154 154
155 155 if order == defineorder:
156 156 return r & subset
157 157 else:
158 158 # carrying the sorting over when possible would be more efficient
159 159 return subset & r
160 160
161 161 def dagrange(repo, subset, x, y, order):
162 162 r = fullreposet(repo)
163 163 xs = dagop.reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
164 164 includepath=True)
165 165 return subset & xs
166 166
167 167 def andset(repo, subset, x, y, order):
168 168 if order == anyorder:
169 169 yorder = anyorder
170 170 else:
171 171 yorder = followorder
172 172 return getset(repo, getset(repo, subset, x, order), y, yorder)
173 173
174 174 def andsmallyset(repo, subset, x, y, order):
175 175 # 'andsmally(x, y)' is equivalent to 'and(x, y)', but faster when y is small
176 176 if order == anyorder:
177 177 yorder = anyorder
178 178 else:
179 179 yorder = followorder
180 180 return getset(repo, getset(repo, subset, y, yorder), x, order)
181 181
182 182 def differenceset(repo, subset, x, y, order):
183 183 return getset(repo, subset, x, order) - getset(repo, subset, y, anyorder)
184 184
185 185 def _orsetlist(repo, subset, xs, order):
186 186 assert xs
187 187 if len(xs) == 1:
188 188 return getset(repo, subset, xs[0], order)
189 189 p = len(xs) // 2
190 190 a = _orsetlist(repo, subset, xs[:p], order)
191 191 b = _orsetlist(repo, subset, xs[p:], order)
192 192 return a + b
193 193
194 194 def orset(repo, subset, x, order):
195 195 xs = getlist(x)
196 196 if order == followorder:
197 197 # slow path to take the subset order
198 198 return subset & _orsetlist(repo, fullreposet(repo), xs, anyorder)
199 199 else:
200 200 return _orsetlist(repo, subset, xs, order)
201 201
202 202 def notset(repo, subset, x, order):
203 203 return subset - getset(repo, subset, x, anyorder)
204 204
205 205 def relationset(repo, subset, x, y, order):
206 206 raise error.ParseError(_("can't use a relation in this context"))
207 207
208 208 def relsubscriptset(repo, subset, x, y, z, order):
209 209 # this is pretty basic implementation of 'x#y[z]' operator, still
210 210 # experimental so undocumented. see the wiki for further ideas.
211 211 # https://www.mercurial-scm.org/wiki/RevsetOperatorPlan
212 212 rel = getsymbol(y)
213 213 n = getinteger(z, _("relation subscript must be an integer"))
214 214
215 215 # TODO: perhaps this should be a table of relation functions
216 216 if rel in ('g', 'generations'):
217 217 # TODO: support range, rewrite tests, and drop startdepth argument
218 218 # from ancestors() and descendants() predicates
219 219 if n <= 0:
220 220 n = -n
221 221 return _ancestors(repo, subset, x, startdepth=n, stopdepth=n + 1)
222 222 else:
223 223 return _descendants(repo, subset, x, startdepth=n, stopdepth=n + 1)
224 224
225 225 raise error.UnknownIdentifier(rel, ['generations'])
226 226
227 227 def subscriptset(repo, subset, x, y, order):
228 228 raise error.ParseError(_("can't use a subscript in this context"))
229 229
230 230 def listset(repo, subset, *xs, **opts):
231 231 raise error.ParseError(_("can't use a list in this context"),
232 232 hint=_('see hg help "revsets.x or y"'))
233 233
234 234 def keyvaluepair(repo, subset, k, v, order):
235 235 raise error.ParseError(_("can't use a key-value pair in this context"))
236 236
237 237 def func(repo, subset, a, b, order):
238 238 f = getsymbol(a)
239 239 if f in symbols:
240 240 func = symbols[f]
241 241 if getattr(func, '_takeorder', False):
242 242 return func(repo, subset, b, order)
243 243 return func(repo, subset, b)
244 244
245 245 keep = lambda fn: getattr(fn, '__doc__', None) is not None
246 246
247 247 syms = [s for (s, fn) in symbols.items() if keep(fn)]
248 248 raise error.UnknownIdentifier(f, syms)
249 249
250 250 # functions
251 251
252 252 # symbols are callables like:
253 253 # fn(repo, subset, x)
254 254 # with:
255 255 # repo - current repository instance
256 256 # subset - of revisions to be examined
257 257 # x - argument in tree form
258 258 symbols = revsetlang.symbols
259 259
260 260 # symbols which can't be used for a DoS attack for any given input
261 261 # (e.g. those which accept regexes as plain strings shouldn't be included)
262 262 # functions that just return a lot of changesets (like all) don't count here
263 263 safesymbols = set()
264 264
265 265 predicate = registrar.revsetpredicate()
266 266
267 267 @predicate('_destupdate')
268 268 def _destupdate(repo, subset, x):
269 269 # experimental revset for update destination
270 270 args = getargsdict(x, 'limit', 'clean')
271 271 return subset & baseset([destutil.destupdate(repo,
272 272 **pycompat.strkwargs(args))[0]])
273 273
274 274 @predicate('_destmerge')
275 275 def _destmerge(repo, subset, x):
276 276 # experimental revset for merge destination
277 277 sourceset = None
278 278 if x is not None:
279 279 sourceset = getset(repo, fullreposet(repo), x)
280 280 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
281 281
282 282 @predicate('adds(pattern)', safe=True, weight=30)
283 283 def adds(repo, subset, x):
284 284 """Changesets that add a file matching pattern.
285 285
286 286 The pattern without explicit kind like ``glob:`` is expected to be
287 287 relative to the current directory and match against a file or a
288 288 directory.
289 289 """
290 290 # i18n: "adds" is a keyword
291 291 pat = getstring(x, _("adds requires a pattern"))
292 292 return checkstatus(repo, subset, pat, 1)
293 293
294 294 @predicate('ancestor(*changeset)', safe=True, weight=0.5)
295 295 def ancestor(repo, subset, x):
296 296 """A greatest common ancestor of the changesets.
297 297
298 298 Accepts 0 or more changesets.
299 299 Will return empty list when passed no args.
300 300 Greatest common ancestor of a single changeset is that changeset.
301 301 """
302 302 # i18n: "ancestor" is a keyword
303 303 l = getlist(x)
304 304 rl = fullreposet(repo)
305 305 anc = None
306 306
307 307 # (getset(repo, rl, i) for i in l) generates a list of lists
308 308 for revs in (getset(repo, rl, i) for i in l):
309 309 for r in revs:
310 310 if anc is None:
311 311 anc = repo[r]
312 312 else:
313 313 anc = anc.ancestor(repo[r])
314 314
315 315 if anc is not None and anc.rev() in subset:
316 316 return baseset([anc.rev()])
317 317 return baseset()
318 318
319 319 def _ancestors(repo, subset, x, followfirst=False, startdepth=None,
320 320 stopdepth=None):
321 321 heads = getset(repo, fullreposet(repo), x)
322 322 if not heads:
323 323 return baseset()
324 324 s = dagop.revancestors(repo, heads, followfirst, startdepth, stopdepth)
325 325 return subset & s
326 326
327 327 @predicate('ancestors(set[, depth])', safe=True)
328 328 def ancestors(repo, subset, x):
329 329 """Changesets that are ancestors of changesets in set, including the
330 330 given changesets themselves.
331 331
332 332 If depth is specified, the result only includes changesets up to
333 333 the specified generation.
334 334 """
335 335 # startdepth is for internal use only until we can decide the UI
336 336 args = getargsdict(x, 'ancestors', 'set depth startdepth')
337 337 if 'set' not in args:
338 338 # i18n: "ancestors" is a keyword
339 339 raise error.ParseError(_('ancestors takes at least 1 argument'))
340 340 startdepth = stopdepth = None
341 341 if 'startdepth' in args:
342 342 n = getinteger(args['startdepth'],
343 343 "ancestors expects an integer startdepth")
344 344 if n < 0:
345 345 raise error.ParseError("negative startdepth")
346 346 startdepth = n
347 347 if 'depth' in args:
348 348 # i18n: "ancestors" is a keyword
349 349 n = getinteger(args['depth'], _("ancestors expects an integer depth"))
350 350 if n < 0:
351 351 raise error.ParseError(_("negative depth"))
352 352 stopdepth = n + 1
353 353 return _ancestors(repo, subset, args['set'],
354 354 startdepth=startdepth, stopdepth=stopdepth)
355 355
356 356 @predicate('_firstancestors', safe=True)
357 357 def _firstancestors(repo, subset, x):
358 358 # ``_firstancestors(set)``
359 359 # Like ``ancestors(set)`` but follows only the first parents.
360 360 return _ancestors(repo, subset, x, followfirst=True)
361 361
362 362 def _childrenspec(repo, subset, x, n, order):
363 363 """Changesets that are the Nth child of a changeset
364 364 in set.
365 365 """
366 366 cs = set()
367 367 for r in getset(repo, fullreposet(repo), x):
368 368 for i in range(n):
369 369 c = repo[r].children()
370 370 if len(c) == 0:
371 371 break
372 372 if len(c) > 1:
373 373 raise error.RepoLookupError(
374 374 _("revision in set has more than one child"))
375 375 r = c[0].rev()
376 376 else:
377 377 cs.add(r)
378 378 return subset & cs
379 379
380 380 def ancestorspec(repo, subset, x, n, order):
381 381 """``set~n``
382 382 Changesets that are the Nth ancestor (first parents only) of a changeset
383 383 in set.
384 384 """
385 385 n = getinteger(n, _("~ expects a number"))
386 386 if n < 0:
387 387 # children lookup
388 388 return _childrenspec(repo, subset, x, -n, order)
389 389 ps = set()
390 390 cl = repo.changelog
391 391 for r in getset(repo, fullreposet(repo), x):
392 392 for i in range(n):
393 393 try:
394 394 r = cl.parentrevs(r)[0]
395 395 except error.WdirUnsupported:
396 396 r = repo[r].parents()[0].rev()
397 397 ps.add(r)
398 398 return subset & ps
399 399
400 400 @predicate('author(string)', safe=True, weight=10)
401 401 def author(repo, subset, x):
402 402 """Alias for ``user(string)``.
403 403 """
404 404 # i18n: "author" is a keyword
405 405 n = getstring(x, _("author requires a string"))
406 406 kind, pattern, matcher = _substringmatcher(n, casesensitive=False)
407 407 return subset.filter(lambda x: matcher(repo[x].user()),
408 408 condrepr=('<user %r>', n))
409 409
410 410 @predicate('bisect(string)', safe=True)
411 411 def bisect(repo, subset, x):
412 412 """Changesets marked in the specified bisect status:
413 413
414 414 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
415 415 - ``goods``, ``bads`` : csets topologically good/bad
416 416 - ``range`` : csets taking part in the bisection
417 417 - ``pruned`` : csets that are goods, bads or skipped
418 418 - ``untested`` : csets whose fate is yet unknown
419 419 - ``ignored`` : csets ignored due to DAG topology
420 420 - ``current`` : the cset currently being bisected
421 421 """
422 422 # i18n: "bisect" is a keyword
423 423 status = getstring(x, _("bisect requires a string")).lower()
424 424 state = set(hbisect.get(repo, status))
425 425 return subset & state
426 426
427 427 # Backward-compatibility
428 428 # - no help entry so that we do not advertise it any more
429 429 @predicate('bisected', safe=True)
430 430 def bisected(repo, subset, x):
431 431 return bisect(repo, subset, x)
432 432
433 433 @predicate('bookmark([name])', safe=True)
434 434 def bookmark(repo, subset, x):
435 435 """The named bookmark or all bookmarks.
436 436
437 437 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
438 438 """
439 439 # i18n: "bookmark" is a keyword
440 440 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
441 441 if args:
442 442 bm = getstring(args[0],
443 443 # i18n: "bookmark" is a keyword
444 444 _('the argument to bookmark must be a string'))
445 445 kind, pattern, matcher = util.stringmatcher(bm)
446 446 bms = set()
447 447 if kind == 'literal':
448 448 bmrev = repo._bookmarks.get(pattern, None)
449 449 if not bmrev:
450 450 raise error.RepoLookupError(_("bookmark '%s' does not exist")
451 451 % pattern)
452 452 bms.add(repo[bmrev].rev())
453 453 else:
454 454 matchrevs = set()
455 455 for name, bmrev in repo._bookmarks.iteritems():
456 456 if matcher(name):
457 457 matchrevs.add(bmrev)
458 458 if not matchrevs:
459 459 raise error.RepoLookupError(_("no bookmarks exist"
460 460 " that match '%s'") % pattern)
461 461 for bmrev in matchrevs:
462 462 bms.add(repo[bmrev].rev())
463 463 else:
464 464 bms = {repo[r].rev() for r in repo._bookmarks.values()}
465 465 bms -= {node.nullrev}
466 466 return subset & bms
467 467
468 468 @predicate('branch(string or set)', safe=True, weight=10)
469 469 def branch(repo, subset, x):
470 470 """
471 471 All changesets belonging to the given branch or the branches of the given
472 472 changesets.
473 473
474 474 Pattern matching is supported for `string`. See
475 475 :hg:`help revisions.patterns`.
476 476 """
477 477 getbi = repo.revbranchcache().branchinfo
478 478 def getbranch(r):
479 479 try:
480 480 return getbi(r)[0]
481 481 except error.WdirUnsupported:
482 482 return repo[r].branch()
483 483
484 484 try:
485 485 b = getstring(x, '')
486 486 except error.ParseError:
487 487 # not a string, but another revspec, e.g. tip()
488 488 pass
489 489 else:
490 490 kind, pattern, matcher = util.stringmatcher(b)
491 491 if kind == 'literal':
492 492 # note: falls through to the revspec case if no branch with
493 493 # this name exists and pattern kind is not specified explicitly
494 494 if pattern in repo.branchmap():
495 495 return subset.filter(lambda r: matcher(getbranch(r)),
496 496 condrepr=('<branch %r>', b))
497 497 if b.startswith('literal:'):
498 498 raise error.RepoLookupError(_("branch '%s' does not exist")
499 499 % pattern)
500 500 else:
501 501 return subset.filter(lambda r: matcher(getbranch(r)),
502 502 condrepr=('<branch %r>', b))
503 503
504 504 s = getset(repo, fullreposet(repo), x)
505 505 b = set()
506 506 for r in s:
507 507 b.add(getbranch(r))
508 508 c = s.__contains__
509 509 return subset.filter(lambda r: c(r) or getbranch(r) in b,
510 510 condrepr=lambda: '<branch %r>' % sorted(b))
511 511
512 512 @predicate('bumped()', safe=True)
513 513 def bumped(repo, subset, x):
514 514 msg = ("'bumped()' is deprecated, "
515 515 "use 'phasedivergent()'")
516 516 repo.ui.deprecwarn(msg, '4.4')
517 517
518 518 return phasedivergent(repo, subset, x)
519 519
520 520 @predicate('phasedivergent()', safe=True)
521 521 def phasedivergent(repo, subset, x):
522 522 """Mutable changesets marked as successors of public changesets.
523 523
524 524 Only non-public and non-obsolete changesets can be `phasedivergent`.
525 525 (EXPERIMENTAL)
526 526 """
527 527 # i18n: "phasedivergent" is a keyword
528 528 getargs(x, 0, 0, _("phasedivergent takes no arguments"))
529 529 phasedivergent = obsmod.getrevs(repo, 'phasedivergent')
530 530 return subset & phasedivergent
531 531
532 532 @predicate('bundle()', safe=True)
533 533 def bundle(repo, subset, x):
534 534 """Changesets in the bundle.
535 535
536 536 Bundle must be specified by the -R option."""
537 537
538 538 try:
539 539 bundlerevs = repo.changelog.bundlerevs
540 540 except AttributeError:
541 541 raise error.Abort(_("no bundle provided - specify with -R"))
542 542 return subset & bundlerevs
543 543
544 544 def checkstatus(repo, subset, pat, field):
545 545 hasset = matchmod.patkind(pat) == 'set'
546 546
547 547 mcache = [None]
548 548 def matches(x):
549 549 c = repo[x]
550 550 if not mcache[0] or hasset:
551 551 mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
552 552 m = mcache[0]
553 553 fname = None
554 554 if not m.anypats() and len(m.files()) == 1:
555 555 fname = m.files()[0]
556 556 if fname is not None:
557 557 if fname not in c.files():
558 558 return False
559 559 else:
560 560 for f in c.files():
561 561 if m(f):
562 562 break
563 563 else:
564 564 return False
565 565 files = repo.status(c.p1().node(), c.node())[field]
566 566 if fname is not None:
567 567 if fname in files:
568 568 return True
569 569 else:
570 570 for f in files:
571 571 if m(f):
572 572 return True
573 573
574 574 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
575 575
576 576 def _children(repo, subset, parentset):
577 577 if not parentset:
578 578 return baseset()
579 579 cs = set()
580 580 pr = repo.changelog.parentrevs
581 581 minrev = parentset.min()
582 582 nullrev = node.nullrev
583 583 for r in subset:
584 584 if r <= minrev:
585 585 continue
586 586 p1, p2 = pr(r)
587 587 if p1 in parentset:
588 588 cs.add(r)
589 589 if p2 != nullrev and p2 in parentset:
590 590 cs.add(r)
591 591 return baseset(cs)
592 592
593 593 @predicate('children(set)', safe=True)
594 594 def children(repo, subset, x):
595 595 """Child changesets of changesets in set.
596 596 """
597 597 s = getset(repo, fullreposet(repo), x)
598 598 cs = _children(repo, subset, s)
599 599 return subset & cs
600 600
601 601 @predicate('closed()', safe=True, weight=10)
602 602 def closed(repo, subset, x):
603 603 """Changeset is closed.
604 604 """
605 605 # i18n: "closed" is a keyword
606 606 getargs(x, 0, 0, _("closed takes no arguments"))
607 607 return subset.filter(lambda r: repo[r].closesbranch(),
608 608 condrepr='<branch closed>')
609 609
610 610 @predicate('contains(pattern)', weight=100)
611 611 def contains(repo, subset, x):
612 612 """The revision's manifest contains a file matching pattern (but might not
613 613 modify it). See :hg:`help patterns` for information about file patterns.
614 614
615 615 The pattern without explicit kind like ``glob:`` is expected to be
616 616 relative to the current directory and match against a file exactly
617 617 for efficiency.
618 618 """
619 619 # i18n: "contains" is a keyword
620 620 pat = getstring(x, _("contains requires a pattern"))
621 621
622 622 def matches(x):
623 623 if not matchmod.patkind(pat):
624 624 pats = pathutil.canonpath(repo.root, repo.getcwd(), pat)
625 625 if pats in repo[x]:
626 626 return True
627 627 else:
628 628 c = repo[x]
629 629 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
630 630 for f in c.manifest():
631 631 if m(f):
632 632 return True
633 633 return False
634 634
635 635 return subset.filter(matches, condrepr=('<contains %r>', pat))
636 636
637 637 @predicate('converted([id])', safe=True)
638 638 def converted(repo, subset, x):
639 639 """Changesets converted from the given identifier in the old repository if
640 640 present, or all converted changesets if no identifier is specified.
641 641 """
642 642
643 643 # There is exactly no chance of resolving the revision, so do a simple
644 644 # string compare and hope for the best
645 645
646 646 rev = None
647 647 # i18n: "converted" is a keyword
648 648 l = getargs(x, 0, 1, _('converted takes one or no arguments'))
649 649 if l:
650 650 # i18n: "converted" is a keyword
651 651 rev = getstring(l[0], _('converted requires a revision'))
652 652
653 653 def _matchvalue(r):
654 654 source = repo[r].extra().get('convert_revision', None)
655 655 return source is not None and (rev is None or source.startswith(rev))
656 656
657 657 return subset.filter(lambda r: _matchvalue(r),
658 658 condrepr=('<converted %r>', rev))
659 659
660 660 @predicate('date(interval)', safe=True, weight=10)
661 661 def date(repo, subset, x):
662 662 """Changesets within the interval, see :hg:`help dates`.
663 663 """
664 664 # i18n: "date" is a keyword
665 665 ds = getstring(x, _("date requires a string"))
666 666 dm = util.matchdate(ds)
667 667 return subset.filter(lambda x: dm(repo[x].date()[0]),
668 668 condrepr=('<date %r>', ds))
669 669
670 670 @predicate('desc(string)', safe=True, weight=10)
671 671 def desc(repo, subset, x):
672 672 """Search commit message for string. The match is case-insensitive.
673 673
674 674 Pattern matching is supported for `string`. See
675 675 :hg:`help revisions.patterns`.
676 676 """
677 677 # i18n: "desc" is a keyword
678 678 ds = getstring(x, _("desc requires a string"))
679 679
680 680 kind, pattern, matcher = _substringmatcher(ds, casesensitive=False)
681 681
682 682 return subset.filter(lambda r: matcher(repo[r].description()),
683 683 condrepr=('<desc %r>', ds))
684 684
685 685 def _descendants(repo, subset, x, followfirst=False, startdepth=None,
686 686 stopdepth=None):
687 687 roots = getset(repo, fullreposet(repo), x)
688 688 if not roots:
689 689 return baseset()
690 690 s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth)
691 691 return subset & s
692 692
693 693 @predicate('descendants(set[, depth])', safe=True)
694 694 def descendants(repo, subset, x):
695 695 """Changesets which are descendants of changesets in set, including the
696 696 given changesets themselves.
697 697
698 698 If depth is specified, the result only includes changesets up to
699 699 the specified generation.
700 700 """
701 701 # startdepth is for internal use only until we can decide the UI
702 702 args = getargsdict(x, 'descendants', 'set depth startdepth')
703 703 if 'set' not in args:
704 704 # i18n: "descendants" is a keyword
705 705 raise error.ParseError(_('descendants takes at least 1 argument'))
706 706 startdepth = stopdepth = None
707 707 if 'startdepth' in args:
708 708 n = getinteger(args['startdepth'],
709 709 "descendants expects an integer startdepth")
710 710 if n < 0:
711 711 raise error.ParseError("negative startdepth")
712 712 startdepth = n
713 713 if 'depth' in args:
714 714 # i18n: "descendants" is a keyword
715 715 n = getinteger(args['depth'], _("descendants expects an integer depth"))
716 716 if n < 0:
717 717 raise error.ParseError(_("negative depth"))
718 718 stopdepth = n + 1
719 719 return _descendants(repo, subset, args['set'],
720 720 startdepth=startdepth, stopdepth=stopdepth)
721 721
722 722 @predicate('_firstdescendants', safe=True)
723 723 def _firstdescendants(repo, subset, x):
724 724 # ``_firstdescendants(set)``
725 725 # Like ``descendants(set)`` but follows only the first parents.
726 726 return _descendants(repo, subset, x, followfirst=True)
727 727
728 728 @predicate('destination([set])', safe=True, weight=10)
729 729 def destination(repo, subset, x):
730 730 """Changesets that were created by a graft, transplant or rebase operation,
731 731 with the given revisions specified as the source. Omitting the optional set
732 732 is the same as passing all().
733 733 """
734 734 if x is not None:
735 735 sources = getset(repo, fullreposet(repo), x)
736 736 else:
737 737 sources = fullreposet(repo)
738 738
739 739 dests = set()
740 740
741 741 # subset contains all of the possible destinations that can be returned, so
742 742 # iterate over them and see if their source(s) were provided in the arg set.
743 743 # Even if the immediate src of r is not in the arg set, src's source (or
744 744 # further back) may be. Scanning back further than the immediate src allows
745 745 # transitive transplants and rebases to yield the same results as transitive
746 746 # grafts.
747 747 for r in subset:
748 748 src = _getrevsource(repo, r)
749 749 lineage = None
750 750
751 751 while src is not None:
752 752 if lineage is None:
753 753 lineage = list()
754 754
755 755 lineage.append(r)
756 756
757 757 # The visited lineage is a match if the current source is in the arg
758 758 # set. Since every candidate dest is visited by way of iterating
759 759 # subset, any dests further back in the lineage will be tested by a
760 760 # different iteration over subset. Likewise, if the src was already
761 761 # selected, the current lineage can be selected without going back
762 762 # further.
763 763 if src in sources or src in dests:
764 764 dests.update(lineage)
765 765 break
766 766
767 767 r = src
768 768 src = _getrevsource(repo, r)
769 769
770 770 return subset.filter(dests.__contains__,
771 771 condrepr=lambda: '<destination %r>' % sorted(dests))
772 772
773 773 @predicate('divergent()', safe=True)
774 774 def divergent(repo, subset, x):
775 775 msg = ("'divergent()' is deprecated, "
776 776 "use 'contentdivergent()'")
777 777 repo.ui.deprecwarn(msg, '4.4')
778 778
779 779 return contentdivergent(repo, subset, x)
780 780
781 781 @predicate('contentdivergent()', safe=True)
782 782 def contentdivergent(repo, subset, x):
783 783 """
784 784 Final successors of changesets with an alternative set of final
785 785 successors. (EXPERIMENTAL)
786 786 """
787 787 # i18n: "contentdivergent" is a keyword
788 788 getargs(x, 0, 0, _("contentdivergent takes no arguments"))
789 789 contentdivergent = obsmod.getrevs(repo, 'contentdivergent')
790 790 return subset & contentdivergent
791 791
792 792 @predicate('extdata(source)', safe=False, weight=100)
793 793 def extdata(repo, subset, x):
794 794 """Changesets in the specified extdata source. (EXPERIMENTAL)"""
795 795 # i18n: "extdata" is a keyword
796 796 args = getargsdict(x, 'extdata', 'source')
797 797 source = getstring(args.get('source'),
798 798 # i18n: "extdata" is a keyword
799 799 _('extdata takes at least 1 string argument'))
800 800 data = scmutil.extdatasource(repo, source)
801 801 return subset & baseset(data)
802 802
803 803 @predicate('extinct()', safe=True)
804 804 def extinct(repo, subset, x):
805 805 """Obsolete changesets with obsolete descendants only.
806 806 """
807 807 # i18n: "extinct" is a keyword
808 808 getargs(x, 0, 0, _("extinct takes no arguments"))
809 809 extincts = obsmod.getrevs(repo, 'extinct')
810 810 return subset & extincts
811 811
812 812 @predicate('extra(label, [value])', safe=True)
813 813 def extra(repo, subset, x):
814 814 """Changesets with the given label in the extra metadata, with the given
815 815 optional value.
816 816
817 817 Pattern matching is supported for `value`. See
818 818 :hg:`help revisions.patterns`.
819 819 """
820 820 args = getargsdict(x, 'extra', 'label value')
821 821 if 'label' not in args:
822 822 # i18n: "extra" is a keyword
823 823 raise error.ParseError(_('extra takes at least 1 argument'))
824 824 # i18n: "extra" is a keyword
825 825 label = getstring(args['label'], _('first argument to extra must be '
826 826 'a string'))
827 827 value = None
828 828
829 829 if 'value' in args:
830 830 # i18n: "extra" is a keyword
831 831 value = getstring(args['value'], _('second argument to extra must be '
832 832 'a string'))
833 833 kind, value, matcher = util.stringmatcher(value)
834 834
835 835 def _matchvalue(r):
836 836 extra = repo[r].extra()
837 837 return label in extra and (value is None or matcher(extra[label]))
838 838
839 839 return subset.filter(lambda r: _matchvalue(r),
840 840 condrepr=('<extra[%r] %r>', label, value))
841 841
842 842 @predicate('filelog(pattern)', safe=True)
843 843 def filelog(repo, subset, x):
844 844 """Changesets connected to the specified filelog.
845 845
846 846 For performance reasons, visits only revisions mentioned in the file-level
847 847 filelog, rather than filtering through all changesets (much faster, but
848 848 doesn't include deletes or duplicate changes). For a slower, more accurate
849 849 result, use ``file()``.
850 850
851 851 The pattern without explicit kind like ``glob:`` is expected to be
852 852 relative to the current directory and match against a file exactly
853 853 for efficiency.
854 854
855 855 If some linkrev points to revisions filtered by the current repoview, we'll
856 856 work around it to return a non-filtered value.
857 857 """
858 858
859 859 # i18n: "filelog" is a keyword
860 860 pat = getstring(x, _("filelog requires a pattern"))
861 861 s = set()
862 862 cl = repo.changelog
863 863
864 864 if not matchmod.patkind(pat):
865 865 f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
866 866 files = [f]
867 867 else:
868 868 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
869 869 files = (f for f in repo[None] if m(f))
870 870
871 871 for f in files:
872 872 fl = repo.file(f)
873 873 known = {}
874 874 scanpos = 0
875 875 for fr in list(fl):
876 876 fn = fl.node(fr)
877 877 if fn in known:
878 878 s.add(known[fn])
879 879 continue
880 880
881 881 lr = fl.linkrev(fr)
882 882 if lr in cl:
883 883 s.add(lr)
884 884 elif scanpos is not None:
885 885 # lowest matching changeset is filtered, scan further
886 886 # ahead in changelog
887 887 start = max(lr, scanpos) + 1
888 888 scanpos = None
889 889 for r in cl.revs(start):
890 890 # minimize parsing of non-matching entries
891 891 if f in cl.revision(r) and f in cl.readfiles(r):
892 892 try:
893 893 # try to use manifest delta fastpath
894 894 n = repo[r].filenode(f)
895 895 if n not in known:
896 896 if n == fn:
897 897 s.add(r)
898 898 scanpos = r
899 899 break
900 900 else:
901 901 known[n] = r
902 902 except error.ManifestLookupError:
903 903 # deletion in changelog
904 904 continue
905 905
906 906 return subset & s
907 907
908 908 @predicate('first(set, [n])', safe=True, takeorder=True, weight=0)
909 909 def first(repo, subset, x, order):
910 910 """An alias for limit().
911 911 """
912 912 return limit(repo, subset, x, order)
913 913
914 914 def _follow(repo, subset, x, name, followfirst=False):
915 915 args = getargsdict(x, name, 'file startrev')
916 916 revs = None
917 917 if 'startrev' in args:
918 918 revs = getset(repo, fullreposet(repo), args['startrev'])
919 919 if 'file' in args:
920 920 x = getstring(args['file'], _("%s expected a pattern") % name)
921 921 if revs is None:
922 922 revs = [None]
923 923 fctxs = []
924 924 for r in revs:
925 925 ctx = mctx = repo[r]
926 926 if r is None:
927 927 ctx = repo['.']
928 928 m = matchmod.match(repo.root, repo.getcwd(), [x],
929 929 ctx=mctx, default='path')
930 930 fctxs.extend(ctx[f].introfilectx() for f in ctx.manifest().walk(m))
931 931 s = dagop.filerevancestors(fctxs, followfirst)
932 932 else:
933 933 if revs is None:
934 934 revs = baseset([repo['.'].rev()])
935 935 s = dagop.revancestors(repo, revs, followfirst)
936 936
937 937 return subset & s
938 938
939 939 @predicate('follow([file[, startrev]])', safe=True)
940 940 def follow(repo, subset, x):
941 941 """
942 942 An alias for ``::.`` (ancestors of the working directory's first parent).
943 943 If file pattern is specified, the histories of files matching given
944 944 pattern in the revision given by startrev are followed, including copies.
945 945 """
946 946 return _follow(repo, subset, x, 'follow')
947 947
948 948 @predicate('_followfirst', safe=True)
949 949 def _followfirst(repo, subset, x):
950 950 # ``followfirst([file[, startrev]])``
951 951 # Like ``follow([file[, startrev]])`` but follows only the first parent
952 952 # of every revisions or files revisions.
953 953 return _follow(repo, subset, x, '_followfirst', followfirst=True)
954 954
955 955 @predicate('followlines(file, fromline:toline[, startrev=., descend=False])',
956 956 safe=True)
957 957 def followlines(repo, subset, x):
958 958 """Changesets modifying `file` in line range ('fromline', 'toline').
959 959
960 960 Line range corresponds to 'file' content at 'startrev' and should hence be
961 961 consistent with file size. If startrev is not specified, working directory's
962 962 parent is used.
963 963
964 964 By default, ancestors of 'startrev' are returned. If 'descend' is True,
965 965 descendants of 'startrev' are returned though renames are (currently) not
966 966 followed in this direction.
967 967 """
968 968 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
969 969 if len(args['lines']) != 1:
970 970 raise error.ParseError(_("followlines requires a line range"))
971 971
972 972 rev = '.'
973 973 if 'startrev' in args:
974 974 revs = getset(repo, fullreposet(repo), args['startrev'])
975 975 if len(revs) != 1:
976 976 raise error.ParseError(
977 977 # i18n: "followlines" is a keyword
978 978 _("followlines expects exactly one revision"))
979 979 rev = revs.last()
980 980
981 981 pat = getstring(args['file'], _("followlines requires a pattern"))
982 982 # i18n: "followlines" is a keyword
983 983 msg = _("followlines expects exactly one file")
984 984 fname = scmutil.parsefollowlinespattern(repo, rev, pat, msg)
985 985 # i18n: "followlines" is a keyword
986 986 lr = getrange(args['lines'][0], _("followlines expects a line range"))
987 987 fromline, toline = [getinteger(a, _("line range bounds must be integers"))
988 988 for a in lr]
989 989 fromline, toline = util.processlinerange(fromline, toline)
990 990
991 991 fctx = repo[rev].filectx(fname)
992 992 descend = False
993 993 if 'descend' in args:
994 994 descend = getboolean(args['descend'],
995 995 # i18n: "descend" is a keyword
996 996 _("descend argument must be a boolean"))
997 997 if descend:
998 998 rs = generatorset(
999 999 (c.rev() for c, _linerange
1000 1000 in dagop.blockdescendants(fctx, fromline, toline)),
1001 1001 iterasc=True)
1002 1002 else:
1003 1003 rs = generatorset(
1004 1004 (c.rev() for c, _linerange
1005 1005 in dagop.blockancestors(fctx, fromline, toline)),
1006 1006 iterasc=False)
1007 1007 return subset & rs
1008 1008
1009 1009 @predicate('all()', safe=True)
1010 1010 def getall(repo, subset, x):
1011 1011 """All changesets, the same as ``0:tip``.
1012 1012 """
1013 1013 # i18n: "all" is a keyword
1014 1014 getargs(x, 0, 0, _("all takes no arguments"))
1015 1015 return subset & spanset(repo) # drop "null" if any
1016 1016
1017 1017 @predicate('grep(regex)', weight=10)
1018 1018 def grep(repo, subset, x):
1019 1019 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1020 1020 to ensure special escape characters are handled correctly. Unlike
1021 1021 ``keyword(string)``, the match is case-sensitive.
1022 1022 """
1023 1023 try:
1024 1024 # i18n: "grep" is a keyword
1025 1025 gr = re.compile(getstring(x, _("grep requires a string")))
1026 1026 except re.error as e:
1027 1027 raise error.ParseError(_('invalid match pattern: %s') % e)
1028 1028
1029 1029 def matches(x):
1030 1030 c = repo[x]
1031 1031 for e in c.files() + [c.user(), c.description()]:
1032 1032 if gr.search(e):
1033 1033 return True
1034 1034 return False
1035 1035
1036 1036 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
1037 1037
1038 1038 @predicate('_matchfiles', safe=True)
1039 1039 def _matchfiles(repo, subset, x):
1040 1040 # _matchfiles takes a revset list of prefixed arguments:
1041 1041 #
1042 1042 # [p:foo, i:bar, x:baz]
1043 1043 #
1044 1044 # builds a match object from them and filters subset. Allowed
1045 1045 # prefixes are 'p:' for regular patterns, 'i:' for include
1046 1046 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
1047 1047 # a revision identifier, or the empty string to reference the
1048 1048 # working directory, from which the match object is
1049 1049 # initialized. Use 'd:' to set the default matching mode, default
1050 1050 # to 'glob'. At most one 'r:' and 'd:' argument can be passed.
1051 1051
1052 1052 l = getargs(x, 1, -1, "_matchfiles requires at least one argument")
1053 1053 pats, inc, exc = [], [], []
1054 1054 rev, default = None, None
1055 1055 for arg in l:
1056 1056 s = getstring(arg, "_matchfiles requires string arguments")
1057 1057 prefix, value = s[:2], s[2:]
1058 1058 if prefix == 'p:':
1059 1059 pats.append(value)
1060 1060 elif prefix == 'i:':
1061 1061 inc.append(value)
1062 1062 elif prefix == 'x:':
1063 1063 exc.append(value)
1064 1064 elif prefix == 'r:':
1065 1065 if rev is not None:
1066 1066 raise error.ParseError('_matchfiles expected at most one '
1067 1067 'revision')
1068 if value != '': # empty means working directory; leave rev as None
1068 if value == '': # empty means working directory
1069 rev = node.wdirrev
1070 else:
1069 1071 rev = value
1070 1072 elif prefix == 'd:':
1071 1073 if default is not None:
1072 1074 raise error.ParseError('_matchfiles expected at most one '
1073 1075 'default mode')
1074 1076 default = value
1075 1077 else:
1076 1078 raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
1077 1079 if not default:
1078 1080 default = 'glob'
1081 hasset = any(matchmod.patkind(p) == 'set' for p in pats + inc + exc)
1079 1082
1080 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
1081 exclude=exc, ctx=repo[rev], default=default)
1083 mcache = [None]
1082 1084
1083 1085 # This directly read the changelog data as creating changectx for all
1084 1086 # revisions is quite expensive.
1085 1087 getfiles = repo.changelog.readfiles
1086 1088 wdirrev = node.wdirrev
1087 1089 def matches(x):
1088 1090 if x == wdirrev:
1089 1091 files = repo[x].files()
1090 1092 else:
1091 1093 files = getfiles(x)
1094
1095 if not mcache[0] or (hasset and rev is None):
1096 r = x if rev is None else rev
1097 mcache[0] = matchmod.match(repo.root, repo.getcwd(), pats,
1098 include=inc, exclude=exc, ctx=repo[r],
1099 default=default)
1100 m = mcache[0]
1101
1092 1102 for f in files:
1093 1103 if m(f):
1094 1104 return True
1095 1105 return False
1096 1106
1097 1107 return subset.filter(matches,
1098 1108 condrepr=('<matchfiles patterns=%r, include=%r '
1099 1109 'exclude=%r, default=%r, rev=%r>',
1100 1110 pats, inc, exc, default, rev))
1101 1111
1102 1112 @predicate('file(pattern)', safe=True, weight=10)
1103 1113 def hasfile(repo, subset, x):
1104 1114 """Changesets affecting files matched by pattern.
1105 1115
1106 1116 For a faster but less accurate result, consider using ``filelog()``
1107 1117 instead.
1108 1118
1109 1119 This predicate uses ``glob:`` as the default kind of pattern.
1110 1120 """
1111 1121 # i18n: "file" is a keyword
1112 1122 pat = getstring(x, _("file requires a pattern"))
1113 1123 return _matchfiles(repo, subset, ('string', 'p:' + pat))
1114 1124
1115 1125 @predicate('head()', safe=True)
1116 1126 def head(repo, subset, x):
1117 1127 """Changeset is a named branch head.
1118 1128 """
1119 1129 # i18n: "head" is a keyword
1120 1130 getargs(x, 0, 0, _("head takes no arguments"))
1121 1131 hs = set()
1122 1132 cl = repo.changelog
1123 1133 for ls in repo.branchmap().itervalues():
1124 1134 hs.update(cl.rev(h) for h in ls)
1125 1135 return subset & baseset(hs)
1126 1136
1127 1137 @predicate('heads(set)', safe=True)
1128 1138 def heads(repo, subset, x):
1129 1139 """Members of set with no children in set.
1130 1140 """
1131 1141 s = getset(repo, subset, x)
1132 1142 ps = parents(repo, subset, x)
1133 1143 return s - ps
1134 1144
1135 1145 @predicate('hidden()', safe=True)
1136 1146 def hidden(repo, subset, x):
1137 1147 """Hidden changesets.
1138 1148 """
1139 1149 # i18n: "hidden" is a keyword
1140 1150 getargs(x, 0, 0, _("hidden takes no arguments"))
1141 1151 hiddenrevs = repoview.filterrevs(repo, 'visible')
1142 1152 return subset & hiddenrevs
1143 1153
1144 1154 @predicate('keyword(string)', safe=True, weight=10)
1145 1155 def keyword(repo, subset, x):
1146 1156 """Search commit message, user name, and names of changed files for
1147 1157 string. The match is case-insensitive.
1148 1158
1149 1159 For a regular expression or case sensitive search of these fields, use
1150 1160 ``grep(regex)``.
1151 1161 """
1152 1162 # i18n: "keyword" is a keyword
1153 1163 kw = encoding.lower(getstring(x, _("keyword requires a string")))
1154 1164
1155 1165 def matches(r):
1156 1166 c = repo[r]
1157 1167 return any(kw in encoding.lower(t)
1158 1168 for t in c.files() + [c.user(), c.description()])
1159 1169
1160 1170 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1161 1171
1162 1172 @predicate('limit(set[, n[, offset]])', safe=True, takeorder=True, weight=0)
1163 1173 def limit(repo, subset, x, order):
1164 1174 """First n members of set, defaulting to 1, starting from offset.
1165 1175 """
1166 1176 args = getargsdict(x, 'limit', 'set n offset')
1167 1177 if 'set' not in args:
1168 1178 # i18n: "limit" is a keyword
1169 1179 raise error.ParseError(_("limit requires one to three arguments"))
1170 1180 # i18n: "limit" is a keyword
1171 1181 lim = getinteger(args.get('n'), _("limit expects a number"), default=1)
1172 1182 if lim < 0:
1173 1183 raise error.ParseError(_("negative number to select"))
1174 1184 # i18n: "limit" is a keyword
1175 1185 ofs = getinteger(args.get('offset'), _("limit expects a number"), default=0)
1176 1186 if ofs < 0:
1177 1187 raise error.ParseError(_("negative offset"))
1178 1188 os = getset(repo, fullreposet(repo), args['set'])
1179 1189 ls = os.slice(ofs, ofs + lim)
1180 1190 if order == followorder and lim > 1:
1181 1191 return subset & ls
1182 1192 return ls & subset
1183 1193
1184 1194 @predicate('last(set, [n])', safe=True, takeorder=True)
1185 1195 def last(repo, subset, x, order):
1186 1196 """Last n members of set, defaulting to 1.
1187 1197 """
1188 1198 # i18n: "last" is a keyword
1189 1199 l = getargs(x, 1, 2, _("last requires one or two arguments"))
1190 1200 lim = 1
1191 1201 if len(l) == 2:
1192 1202 # i18n: "last" is a keyword
1193 1203 lim = getinteger(l[1], _("last expects a number"))
1194 1204 if lim < 0:
1195 1205 raise error.ParseError(_("negative number to select"))
1196 1206 os = getset(repo, fullreposet(repo), l[0])
1197 1207 os.reverse()
1198 1208 ls = os.slice(0, lim)
1199 1209 if order == followorder and lim > 1:
1200 1210 return subset & ls
1201 1211 ls.reverse()
1202 1212 return ls & subset
1203 1213
1204 1214 @predicate('max(set)', safe=True)
1205 1215 def maxrev(repo, subset, x):
1206 1216 """Changeset with highest revision number in set.
1207 1217 """
1208 1218 os = getset(repo, fullreposet(repo), x)
1209 1219 try:
1210 1220 m = os.max()
1211 1221 if m in subset:
1212 1222 return baseset([m], datarepr=('<max %r, %r>', subset, os))
1213 1223 except ValueError:
1214 1224 # os.max() throws a ValueError when the collection is empty.
1215 1225 # Same as python's max().
1216 1226 pass
1217 1227 return baseset(datarepr=('<max %r, %r>', subset, os))
1218 1228
1219 1229 @predicate('merge()', safe=True)
1220 1230 def merge(repo, subset, x):
1221 1231 """Changeset is a merge changeset.
1222 1232 """
1223 1233 # i18n: "merge" is a keyword
1224 1234 getargs(x, 0, 0, _("merge takes no arguments"))
1225 1235 cl = repo.changelog
1226 1236 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1227 1237 condrepr='<merge>')
1228 1238
1229 1239 @predicate('branchpoint()', safe=True)
1230 1240 def branchpoint(repo, subset, x):
1231 1241 """Changesets with more than one child.
1232 1242 """
1233 1243 # i18n: "branchpoint" is a keyword
1234 1244 getargs(x, 0, 0, _("branchpoint takes no arguments"))
1235 1245 cl = repo.changelog
1236 1246 if not subset:
1237 1247 return baseset()
1238 1248 # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
1239 1249 # (and if it is not, it should.)
1240 1250 baserev = min(subset)
1241 1251 parentscount = [0]*(len(repo) - baserev)
1242 1252 for r in cl.revs(start=baserev + 1):
1243 1253 for p in cl.parentrevs(r):
1244 1254 if p >= baserev:
1245 1255 parentscount[p - baserev] += 1
1246 1256 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1247 1257 condrepr='<branchpoint>')
1248 1258
1249 1259 @predicate('min(set)', safe=True)
1250 1260 def minrev(repo, subset, x):
1251 1261 """Changeset with lowest revision number in set.
1252 1262 """
1253 1263 os = getset(repo, fullreposet(repo), x)
1254 1264 try:
1255 1265 m = os.min()
1256 1266 if m in subset:
1257 1267 return baseset([m], datarepr=('<min %r, %r>', subset, os))
1258 1268 except ValueError:
1259 1269 # os.min() throws a ValueError when the collection is empty.
1260 1270 # Same as python's min().
1261 1271 pass
1262 1272 return baseset(datarepr=('<min %r, %r>', subset, os))
1263 1273
1264 1274 @predicate('modifies(pattern)', safe=True, weight=30)
1265 1275 def modifies(repo, subset, x):
1266 1276 """Changesets modifying files matched by pattern.
1267 1277
1268 1278 The pattern without explicit kind like ``glob:`` is expected to be
1269 1279 relative to the current directory and match against a file or a
1270 1280 directory.
1271 1281 """
1272 1282 # i18n: "modifies" is a keyword
1273 1283 pat = getstring(x, _("modifies requires a pattern"))
1274 1284 return checkstatus(repo, subset, pat, 0)
1275 1285
1276 1286 @predicate('named(namespace)')
1277 1287 def named(repo, subset, x):
1278 1288 """The changesets in a given namespace.
1279 1289
1280 1290 Pattern matching is supported for `namespace`. See
1281 1291 :hg:`help revisions.patterns`.
1282 1292 """
1283 1293 # i18n: "named" is a keyword
1284 1294 args = getargs(x, 1, 1, _('named requires a namespace argument'))
1285 1295
1286 1296 ns = getstring(args[0],
1287 1297 # i18n: "named" is a keyword
1288 1298 _('the argument to named must be a string'))
1289 1299 kind, pattern, matcher = util.stringmatcher(ns)
1290 1300 namespaces = set()
1291 1301 if kind == 'literal':
1292 1302 if pattern not in repo.names:
1293 1303 raise error.RepoLookupError(_("namespace '%s' does not exist")
1294 1304 % ns)
1295 1305 namespaces.add(repo.names[pattern])
1296 1306 else:
1297 1307 for name, ns in repo.names.iteritems():
1298 1308 if matcher(name):
1299 1309 namespaces.add(ns)
1300 1310 if not namespaces:
1301 1311 raise error.RepoLookupError(_("no namespace exists"
1302 1312 " that match '%s'") % pattern)
1303 1313
1304 1314 names = set()
1305 1315 for ns in namespaces:
1306 1316 for name in ns.listnames(repo):
1307 1317 if name not in ns.deprecated:
1308 1318 names.update(repo[n].rev() for n in ns.nodes(repo, name))
1309 1319
1310 1320 names -= {node.nullrev}
1311 1321 return subset & names
1312 1322
1313 1323 @predicate('id(string)', safe=True)
1314 1324 def node_(repo, subset, x):
1315 1325 """Revision non-ambiguously specified by the given hex string prefix.
1316 1326 """
1317 1327 # i18n: "id" is a keyword
1318 1328 l = getargs(x, 1, 1, _("id requires one argument"))
1319 1329 # i18n: "id" is a keyword
1320 1330 n = getstring(l[0], _("id requires a string"))
1321 1331 if len(n) == 40:
1322 1332 try:
1323 1333 rn = repo.changelog.rev(node.bin(n))
1324 1334 except error.WdirUnsupported:
1325 1335 rn = node.wdirrev
1326 1336 except (LookupError, TypeError):
1327 1337 rn = None
1328 1338 else:
1329 1339 rn = None
1330 1340 try:
1331 1341 pm = repo.changelog._partialmatch(n)
1332 1342 if pm is not None:
1333 1343 rn = repo.changelog.rev(pm)
1334 1344 except error.WdirUnsupported:
1335 1345 rn = node.wdirrev
1336 1346
1337 1347 if rn is None:
1338 1348 return baseset()
1339 1349 result = baseset([rn])
1340 1350 return result & subset
1341 1351
1342 1352 @predicate('obsolete()', safe=True)
1343 1353 def obsolete(repo, subset, x):
1344 1354 """Mutable changeset with a newer version."""
1345 1355 # i18n: "obsolete" is a keyword
1346 1356 getargs(x, 0, 0, _("obsolete takes no arguments"))
1347 1357 obsoletes = obsmod.getrevs(repo, 'obsolete')
1348 1358 return subset & obsoletes
1349 1359
1350 1360 @predicate('only(set, [set])', safe=True)
1351 1361 def only(repo, subset, x):
1352 1362 """Changesets that are ancestors of the first set that are not ancestors
1353 1363 of any other head in the repo. If a second set is specified, the result
1354 1364 is ancestors of the first set that are not ancestors of the second set
1355 1365 (i.e. ::<set1> - ::<set2>).
1356 1366 """
1357 1367 cl = repo.changelog
1358 1368 # i18n: "only" is a keyword
1359 1369 args = getargs(x, 1, 2, _('only takes one or two arguments'))
1360 1370 include = getset(repo, fullreposet(repo), args[0])
1361 1371 if len(args) == 1:
1362 1372 if not include:
1363 1373 return baseset()
1364 1374
1365 1375 descendants = set(dagop.revdescendants(repo, include, False))
1366 1376 exclude = [rev for rev in cl.headrevs()
1367 1377 if not rev in descendants and not rev in include]
1368 1378 else:
1369 1379 exclude = getset(repo, fullreposet(repo), args[1])
1370 1380
1371 1381 results = set(cl.findmissingrevs(common=exclude, heads=include))
1372 1382 # XXX we should turn this into a baseset instead of a set, smartset may do
1373 1383 # some optimizations from the fact this is a baseset.
1374 1384 return subset & results
1375 1385
1376 1386 @predicate('origin([set])', safe=True)
1377 1387 def origin(repo, subset, x):
1378 1388 """
1379 1389 Changesets that were specified as a source for the grafts, transplants or
1380 1390 rebases that created the given revisions. Omitting the optional set is the
1381 1391 same as passing all(). If a changeset created by these operations is itself
1382 1392 specified as a source for one of these operations, only the source changeset
1383 1393 for the first operation is selected.
1384 1394 """
1385 1395 if x is not None:
1386 1396 dests = getset(repo, fullreposet(repo), x)
1387 1397 else:
1388 1398 dests = fullreposet(repo)
1389 1399
1390 1400 def _firstsrc(rev):
1391 1401 src = _getrevsource(repo, rev)
1392 1402 if src is None:
1393 1403 return None
1394 1404
1395 1405 while True:
1396 1406 prev = _getrevsource(repo, src)
1397 1407
1398 1408 if prev is None:
1399 1409 return src
1400 1410 src = prev
1401 1411
1402 1412 o = {_firstsrc(r) for r in dests}
1403 1413 o -= {None}
1404 1414 # XXX we should turn this into a baseset instead of a set, smartset may do
1405 1415 # some optimizations from the fact this is a baseset.
1406 1416 return subset & o
1407 1417
1408 1418 @predicate('outgoing([path])', safe=False, weight=10)
1409 1419 def outgoing(repo, subset, x):
1410 1420 """Changesets not found in the specified destination repository, or the
1411 1421 default push location.
1412 1422 """
1413 1423 # Avoid cycles.
1414 1424 from . import (
1415 1425 discovery,
1416 1426 hg,
1417 1427 )
1418 1428 # i18n: "outgoing" is a keyword
1419 1429 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
1420 1430 # i18n: "outgoing" is a keyword
1421 1431 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
1422 1432 if not dest:
1423 1433 # ui.paths.getpath() explicitly tests for None, not just a boolean
1424 1434 dest = None
1425 1435 path = repo.ui.paths.getpath(dest, default=('default-push', 'default'))
1426 1436 if not path:
1427 1437 raise error.Abort(_('default repository not configured!'),
1428 1438 hint=_("see 'hg help config.paths'"))
1429 1439 dest = path.pushloc or path.loc
1430 1440 branches = path.branch, []
1431 1441
1432 1442 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1433 1443 if revs:
1434 1444 revs = [repo.lookup(rev) for rev in revs]
1435 1445 other = hg.peer(repo, {}, dest)
1436 1446 repo.ui.pushbuffer()
1437 1447 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
1438 1448 repo.ui.popbuffer()
1439 1449 cl = repo.changelog
1440 1450 o = {cl.rev(r) for r in outgoing.missing}
1441 1451 return subset & o
1442 1452
1443 1453 @predicate('p1([set])', safe=True)
1444 1454 def p1(repo, subset, x):
1445 1455 """First parent of changesets in set, or the working directory.
1446 1456 """
1447 1457 if x is None:
1448 1458 p = repo[x].p1().rev()
1449 1459 if p >= 0:
1450 1460 return subset & baseset([p])
1451 1461 return baseset()
1452 1462
1453 1463 ps = set()
1454 1464 cl = repo.changelog
1455 1465 for r in getset(repo, fullreposet(repo), x):
1456 1466 try:
1457 1467 ps.add(cl.parentrevs(r)[0])
1458 1468 except error.WdirUnsupported:
1459 1469 ps.add(repo[r].parents()[0].rev())
1460 1470 ps -= {node.nullrev}
1461 1471 # XXX we should turn this into a baseset instead of a set, smartset may do
1462 1472 # some optimizations from the fact this is a baseset.
1463 1473 return subset & ps
1464 1474
1465 1475 @predicate('p2([set])', safe=True)
1466 1476 def p2(repo, subset, x):
1467 1477 """Second parent of changesets in set, or the working directory.
1468 1478 """
1469 1479 if x is None:
1470 1480 ps = repo[x].parents()
1471 1481 try:
1472 1482 p = ps[1].rev()
1473 1483 if p >= 0:
1474 1484 return subset & baseset([p])
1475 1485 return baseset()
1476 1486 except IndexError:
1477 1487 return baseset()
1478 1488
1479 1489 ps = set()
1480 1490 cl = repo.changelog
1481 1491 for r in getset(repo, fullreposet(repo), x):
1482 1492 try:
1483 1493 ps.add(cl.parentrevs(r)[1])
1484 1494 except error.WdirUnsupported:
1485 1495 parents = repo[r].parents()
1486 1496 if len(parents) == 2:
1487 1497 ps.add(parents[1])
1488 1498 ps -= {node.nullrev}
1489 1499 # XXX we should turn this into a baseset instead of a set, smartset may do
1490 1500 # some optimizations from the fact this is a baseset.
1491 1501 return subset & ps
1492 1502
1493 1503 def parentpost(repo, subset, x, order):
1494 1504 return p1(repo, subset, x)
1495 1505
1496 1506 @predicate('parents([set])', safe=True)
1497 1507 def parents(repo, subset, x):
1498 1508 """
1499 1509 The set of all parents for all changesets in set, or the working directory.
1500 1510 """
1501 1511 if x is None:
1502 1512 ps = set(p.rev() for p in repo[x].parents())
1503 1513 else:
1504 1514 ps = set()
1505 1515 cl = repo.changelog
1506 1516 up = ps.update
1507 1517 parentrevs = cl.parentrevs
1508 1518 for r in getset(repo, fullreposet(repo), x):
1509 1519 try:
1510 1520 up(parentrevs(r))
1511 1521 except error.WdirUnsupported:
1512 1522 up(p.rev() for p in repo[r].parents())
1513 1523 ps -= {node.nullrev}
1514 1524 return subset & ps
1515 1525
1516 1526 def _phase(repo, subset, *targets):
1517 1527 """helper to select all rev in <targets> phases"""
1518 1528 return repo._phasecache.getrevset(repo, targets, subset)
1519 1529
1520 1530 @predicate('draft()', safe=True)
1521 1531 def draft(repo, subset, x):
1522 1532 """Changeset in draft phase."""
1523 1533 # i18n: "draft" is a keyword
1524 1534 getargs(x, 0, 0, _("draft takes no arguments"))
1525 1535 target = phases.draft
1526 1536 return _phase(repo, subset, target)
1527 1537
1528 1538 @predicate('secret()', safe=True)
1529 1539 def secret(repo, subset, x):
1530 1540 """Changeset in secret phase."""
1531 1541 # i18n: "secret" is a keyword
1532 1542 getargs(x, 0, 0, _("secret takes no arguments"))
1533 1543 target = phases.secret
1534 1544 return _phase(repo, subset, target)
1535 1545
1536 1546 def parentspec(repo, subset, x, n, order):
1537 1547 """``set^0``
1538 1548 The set.
1539 1549 ``set^1`` (or ``set^``), ``set^2``
1540 1550 First or second parent, respectively, of all changesets in set.
1541 1551 """
1542 1552 try:
1543 1553 n = int(n[1])
1544 1554 if n not in (0, 1, 2):
1545 1555 raise ValueError
1546 1556 except (TypeError, ValueError):
1547 1557 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1548 1558 ps = set()
1549 1559 cl = repo.changelog
1550 1560 for r in getset(repo, fullreposet(repo), x):
1551 1561 if n == 0:
1552 1562 ps.add(r)
1553 1563 elif n == 1:
1554 1564 try:
1555 1565 ps.add(cl.parentrevs(r)[0])
1556 1566 except error.WdirUnsupported:
1557 1567 ps.add(repo[r].parents()[0].rev())
1558 1568 else:
1559 1569 try:
1560 1570 parents = cl.parentrevs(r)
1561 1571 if parents[1] != node.nullrev:
1562 1572 ps.add(parents[1])
1563 1573 except error.WdirUnsupported:
1564 1574 parents = repo[r].parents()
1565 1575 if len(parents) == 2:
1566 1576 ps.add(parents[1].rev())
1567 1577 return subset & ps
1568 1578
1569 1579 @predicate('present(set)', safe=True, takeorder=True)
1570 1580 def present(repo, subset, x, order):
1571 1581 """An empty set, if any revision in set isn't found; otherwise,
1572 1582 all revisions in set.
1573 1583
1574 1584 If any of specified revisions is not present in the local repository,
1575 1585 the query is normally aborted. But this predicate allows the query
1576 1586 to continue even in such cases.
1577 1587 """
1578 1588 try:
1579 1589 return getset(repo, subset, x, order)
1580 1590 except error.RepoLookupError:
1581 1591 return baseset()
1582 1592
1583 1593 # for internal use
1584 1594 @predicate('_notpublic', safe=True)
1585 1595 def _notpublic(repo, subset, x):
1586 1596 getargs(x, 0, 0, "_notpublic takes no arguments")
1587 1597 return _phase(repo, subset, phases.draft, phases.secret)
1588 1598
1589 1599 # for internal use
1590 1600 @predicate('_phaseandancestors(phasename, set)', safe=True)
1591 1601 def _phaseandancestors(repo, subset, x):
1592 1602 # equivalent to (phasename() & ancestors(set)) but more efficient
1593 1603 # phasename could be one of 'draft', 'secret', or '_notpublic'
1594 1604 args = getargs(x, 2, 2, "_phaseandancestors requires two arguments")
1595 1605 phasename = getsymbol(args[0])
1596 1606 s = getset(repo, fullreposet(repo), args[1])
1597 1607
1598 1608 draft = phases.draft
1599 1609 secret = phases.secret
1600 1610 phasenamemap = {
1601 1611 '_notpublic': draft,
1602 1612 'draft': draft, # follow secret's ancestors
1603 1613 'secret': secret,
1604 1614 }
1605 1615 if phasename not in phasenamemap:
1606 1616 raise error.ParseError('%r is not a valid phasename' % phasename)
1607 1617
1608 1618 minimalphase = phasenamemap[phasename]
1609 1619 getphase = repo._phasecache.phase
1610 1620
1611 1621 def cutfunc(rev):
1612 1622 return getphase(repo, rev) < minimalphase
1613 1623
1614 1624 revs = dagop.revancestors(repo, s, cutfunc=cutfunc)
1615 1625
1616 1626 if phasename == 'draft': # need to remove secret changesets
1617 1627 revs = revs.filter(lambda r: getphase(repo, r) == draft)
1618 1628 return subset & revs
1619 1629
1620 1630 @predicate('public()', safe=True)
1621 1631 def public(repo, subset, x):
1622 1632 """Changeset in public phase."""
1623 1633 # i18n: "public" is a keyword
1624 1634 getargs(x, 0, 0, _("public takes no arguments"))
1625 1635 return _phase(repo, subset, phases.public)
1626 1636
1627 1637 @predicate('remote([id [,path]])', safe=False)
1628 1638 def remote(repo, subset, x):
1629 1639 """Local revision that corresponds to the given identifier in a
1630 1640 remote repository, if present. Here, the '.' identifier is a
1631 1641 synonym for the current local branch.
1632 1642 """
1633 1643
1634 1644 from . import hg # avoid start-up nasties
1635 1645 # i18n: "remote" is a keyword
1636 1646 l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
1637 1647
1638 1648 q = '.'
1639 1649 if len(l) > 0:
1640 1650 # i18n: "remote" is a keyword
1641 1651 q = getstring(l[0], _("remote requires a string id"))
1642 1652 if q == '.':
1643 1653 q = repo['.'].branch()
1644 1654
1645 1655 dest = ''
1646 1656 if len(l) > 1:
1647 1657 # i18n: "remote" is a keyword
1648 1658 dest = getstring(l[1], _("remote requires a repository path"))
1649 1659 dest = repo.ui.expandpath(dest or 'default')
1650 1660 dest, branches = hg.parseurl(dest)
1651 1661 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
1652 1662 if revs:
1653 1663 revs = [repo.lookup(rev) for rev in revs]
1654 1664 other = hg.peer(repo, {}, dest)
1655 1665 n = other.lookup(q)
1656 1666 if n in repo:
1657 1667 r = repo[n].rev()
1658 1668 if r in subset:
1659 1669 return baseset([r])
1660 1670 return baseset()
1661 1671
1662 1672 @predicate('removes(pattern)', safe=True, weight=30)
1663 1673 def removes(repo, subset, x):
1664 1674 """Changesets which remove files matching pattern.
1665 1675
1666 1676 The pattern without explicit kind like ``glob:`` is expected to be
1667 1677 relative to the current directory and match against a file or a
1668 1678 directory.
1669 1679 """
1670 1680 # i18n: "removes" is a keyword
1671 1681 pat = getstring(x, _("removes requires a pattern"))
1672 1682 return checkstatus(repo, subset, pat, 2)
1673 1683
1674 1684 @predicate('rev(number)', safe=True)
1675 1685 def rev(repo, subset, x):
1676 1686 """Revision with the given numeric identifier.
1677 1687 """
1678 1688 # i18n: "rev" is a keyword
1679 1689 l = getargs(x, 1, 1, _("rev requires one argument"))
1680 1690 try:
1681 1691 # i18n: "rev" is a keyword
1682 1692 l = int(getstring(l[0], _("rev requires a number")))
1683 1693 except (TypeError, ValueError):
1684 1694 # i18n: "rev" is a keyword
1685 1695 raise error.ParseError(_("rev expects a number"))
1686 1696 if l not in repo.changelog and l not in (node.nullrev, node.wdirrev):
1687 1697 return baseset()
1688 1698 return subset & baseset([l])
1689 1699
1690 1700 @predicate('matching(revision [, field])', safe=True)
1691 1701 def matching(repo, subset, x):
1692 1702 """Changesets in which a given set of fields match the set of fields in the
1693 1703 selected revision or set.
1694 1704
1695 1705 To match more than one field pass the list of fields to match separated
1696 1706 by spaces (e.g. ``author description``).
1697 1707
1698 1708 Valid fields are most regular revision fields and some special fields.
1699 1709
1700 1710 Regular revision fields are ``description``, ``author``, ``branch``,
1701 1711 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
1702 1712 and ``diff``.
1703 1713 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
1704 1714 contents of the revision. Two revisions matching their ``diff`` will
1705 1715 also match their ``files``.
1706 1716
1707 1717 Special fields are ``summary`` and ``metadata``:
1708 1718 ``summary`` matches the first line of the description.
1709 1719 ``metadata`` is equivalent to matching ``description user date``
1710 1720 (i.e. it matches the main metadata fields).
1711 1721
1712 1722 ``metadata`` is the default field which is used when no fields are
1713 1723 specified. You can match more than one field at a time.
1714 1724 """
1715 1725 # i18n: "matching" is a keyword
1716 1726 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
1717 1727
1718 1728 revs = getset(repo, fullreposet(repo), l[0])
1719 1729
1720 1730 fieldlist = ['metadata']
1721 1731 if len(l) > 1:
1722 1732 fieldlist = getstring(l[1],
1723 1733 # i18n: "matching" is a keyword
1724 1734 _("matching requires a string "
1725 1735 "as its second argument")).split()
1726 1736
1727 1737 # Make sure that there are no repeated fields,
1728 1738 # expand the 'special' 'metadata' field type
1729 1739 # and check the 'files' whenever we check the 'diff'
1730 1740 fields = []
1731 1741 for field in fieldlist:
1732 1742 if field == 'metadata':
1733 1743 fields += ['user', 'description', 'date']
1734 1744 elif field == 'diff':
1735 1745 # a revision matching the diff must also match the files
1736 1746 # since matching the diff is very costly, make sure to
1737 1747 # also match the files first
1738 1748 fields += ['files', 'diff']
1739 1749 else:
1740 1750 if field == 'author':
1741 1751 field = 'user'
1742 1752 fields.append(field)
1743 1753 fields = set(fields)
1744 1754 if 'summary' in fields and 'description' in fields:
1745 1755 # If a revision matches its description it also matches its summary
1746 1756 fields.discard('summary')
1747 1757
1748 1758 # We may want to match more than one field
1749 1759 # Not all fields take the same amount of time to be matched
1750 1760 # Sort the selected fields in order of increasing matching cost
1751 1761 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
1752 1762 'files', 'description', 'substate', 'diff']
1753 1763 def fieldkeyfunc(f):
1754 1764 try:
1755 1765 return fieldorder.index(f)
1756 1766 except ValueError:
1757 1767 # assume an unknown field is very costly
1758 1768 return len(fieldorder)
1759 1769 fields = list(fields)
1760 1770 fields.sort(key=fieldkeyfunc)
1761 1771
1762 1772 # Each field will be matched with its own "getfield" function
1763 1773 # which will be added to the getfieldfuncs array of functions
1764 1774 getfieldfuncs = []
1765 1775 _funcs = {
1766 1776 'user': lambda r: repo[r].user(),
1767 1777 'branch': lambda r: repo[r].branch(),
1768 1778 'date': lambda r: repo[r].date(),
1769 1779 'description': lambda r: repo[r].description(),
1770 1780 'files': lambda r: repo[r].files(),
1771 1781 'parents': lambda r: repo[r].parents(),
1772 1782 'phase': lambda r: repo[r].phase(),
1773 1783 'substate': lambda r: repo[r].substate,
1774 1784 'summary': lambda r: repo[r].description().splitlines()[0],
1775 1785 'diff': lambda r: list(repo[r].diff(git=True),)
1776 1786 }
1777 1787 for info in fields:
1778 1788 getfield = _funcs.get(info, None)
1779 1789 if getfield is None:
1780 1790 raise error.ParseError(
1781 1791 # i18n: "matching" is a keyword
1782 1792 _("unexpected field name passed to matching: %s") % info)
1783 1793 getfieldfuncs.append(getfield)
1784 1794 # convert the getfield array of functions into a "getinfo" function
1785 1795 # which returns an array of field values (or a single value if there
1786 1796 # is only one field to match)
1787 1797 getinfo = lambda r: [f(r) for f in getfieldfuncs]
1788 1798
1789 1799 def matches(x):
1790 1800 for rev in revs:
1791 1801 target = getinfo(rev)
1792 1802 match = True
1793 1803 for n, f in enumerate(getfieldfuncs):
1794 1804 if target[n] != f(x):
1795 1805 match = False
1796 1806 if match:
1797 1807 return True
1798 1808 return False
1799 1809
1800 1810 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1801 1811
1802 1812 @predicate('reverse(set)', safe=True, takeorder=True, weight=0)
1803 1813 def reverse(repo, subset, x, order):
1804 1814 """Reverse order of set.
1805 1815 """
1806 1816 l = getset(repo, subset, x, order)
1807 1817 if order == defineorder:
1808 1818 l.reverse()
1809 1819 return l
1810 1820
1811 1821 @predicate('roots(set)', safe=True)
1812 1822 def roots(repo, subset, x):
1813 1823 """Changesets in set with no parent changeset in set.
1814 1824 """
1815 1825 s = getset(repo, fullreposet(repo), x)
1816 1826 parents = repo.changelog.parentrevs
1817 1827 def filter(r):
1818 1828 for p in parents(r):
1819 1829 if 0 <= p and p in s:
1820 1830 return False
1821 1831 return True
1822 1832 return subset & s.filter(filter, condrepr='<roots>')
1823 1833
1824 1834 _sortkeyfuncs = {
1825 1835 'rev': lambda c: c.rev(),
1826 1836 'branch': lambda c: c.branch(),
1827 1837 'desc': lambda c: c.description(),
1828 1838 'user': lambda c: c.user(),
1829 1839 'author': lambda c: c.user(),
1830 1840 'date': lambda c: c.date()[0],
1831 1841 }
1832 1842
1833 1843 def _getsortargs(x):
1834 1844 """Parse sort options into (set, [(key, reverse)], opts)"""
1835 1845 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1836 1846 if 'set' not in args:
1837 1847 # i18n: "sort" is a keyword
1838 1848 raise error.ParseError(_('sort requires one or two arguments'))
1839 1849 keys = "rev"
1840 1850 if 'keys' in args:
1841 1851 # i18n: "sort" is a keyword
1842 1852 keys = getstring(args['keys'], _("sort spec must be a string"))
1843 1853
1844 1854 keyflags = []
1845 1855 for k in keys.split():
1846 1856 fk = k
1847 1857 reverse = (k[0] == '-')
1848 1858 if reverse:
1849 1859 k = k[1:]
1850 1860 if k not in _sortkeyfuncs and k != 'topo':
1851 1861 raise error.ParseError(_("unknown sort key %r") % fk)
1852 1862 keyflags.append((k, reverse))
1853 1863
1854 1864 if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
1855 1865 # i18n: "topo" is a keyword
1856 1866 raise error.ParseError(_('topo sort order cannot be combined '
1857 1867 'with other sort keys'))
1858 1868
1859 1869 opts = {}
1860 1870 if 'topo.firstbranch' in args:
1861 1871 if any(k == 'topo' for k, reverse in keyflags):
1862 1872 opts['topo.firstbranch'] = args['topo.firstbranch']
1863 1873 else:
1864 1874 # i18n: "topo" and "topo.firstbranch" are keywords
1865 1875 raise error.ParseError(_('topo.firstbranch can only be used '
1866 1876 'when using the topo sort key'))
1867 1877
1868 1878 return args['set'], keyflags, opts
1869 1879
1870 1880 @predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True,
1871 1881 weight=10)
1872 1882 def sort(repo, subset, x, order):
1873 1883 """Sort set by keys. The default sort order is ascending, specify a key
1874 1884 as ``-key`` to sort in descending order.
1875 1885
1876 1886 The keys can be:
1877 1887
1878 1888 - ``rev`` for the revision number,
1879 1889 - ``branch`` for the branch name,
1880 1890 - ``desc`` for the commit message (description),
1881 1891 - ``user`` for user name (``author`` can be used as an alias),
1882 1892 - ``date`` for the commit date
1883 1893 - ``topo`` for a reverse topographical sort
1884 1894
1885 1895 The ``topo`` sort order cannot be combined with other sort keys. This sort
1886 1896 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1887 1897 specifies what topographical branches to prioritize in the sort.
1888 1898
1889 1899 """
1890 1900 s, keyflags, opts = _getsortargs(x)
1891 1901 revs = getset(repo, subset, s, order)
1892 1902
1893 1903 if not keyflags or order != defineorder:
1894 1904 return revs
1895 1905 if len(keyflags) == 1 and keyflags[0][0] == "rev":
1896 1906 revs.sort(reverse=keyflags[0][1])
1897 1907 return revs
1898 1908 elif keyflags[0][0] == "topo":
1899 1909 firstbranch = ()
1900 1910 if 'topo.firstbranch' in opts:
1901 1911 firstbranch = getset(repo, subset, opts['topo.firstbranch'])
1902 1912 revs = baseset(dagop.toposort(revs, repo.changelog.parentrevs,
1903 1913 firstbranch),
1904 1914 istopo=True)
1905 1915 if keyflags[0][1]:
1906 1916 revs.reverse()
1907 1917 return revs
1908 1918
1909 1919 # sort() is guaranteed to be stable
1910 1920 ctxs = [repo[r] for r in revs]
1911 1921 for k, reverse in reversed(keyflags):
1912 1922 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1913 1923 return baseset([c.rev() for c in ctxs])
1914 1924
1915 1925 @predicate('subrepo([pattern])')
1916 1926 def subrepo(repo, subset, x):
1917 1927 """Changesets that add, modify or remove the given subrepo. If no subrepo
1918 1928 pattern is named, any subrepo changes are returned.
1919 1929 """
1920 1930 # i18n: "subrepo" is a keyword
1921 1931 args = getargs(x, 0, 1, _('subrepo takes at most one argument'))
1922 1932 pat = None
1923 1933 if len(args) != 0:
1924 1934 pat = getstring(args[0], _("subrepo requires a pattern"))
1925 1935
1926 1936 m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
1927 1937
1928 1938 def submatches(names):
1929 1939 k, p, m = util.stringmatcher(pat)
1930 1940 for name in names:
1931 1941 if m(name):
1932 1942 yield name
1933 1943
1934 1944 def matches(x):
1935 1945 c = repo[x]
1936 1946 s = repo.status(c.p1().node(), c.node(), match=m)
1937 1947
1938 1948 if pat is None:
1939 1949 return s.added or s.modified or s.removed
1940 1950
1941 1951 if s.added:
1942 1952 return any(submatches(c.substate.keys()))
1943 1953
1944 1954 if s.modified:
1945 1955 subs = set(c.p1().substate.keys())
1946 1956 subs.update(c.substate.keys())
1947 1957
1948 1958 for path in submatches(subs):
1949 1959 if c.p1().substate.get(path) != c.substate.get(path):
1950 1960 return True
1951 1961
1952 1962 if s.removed:
1953 1963 return any(submatches(c.p1().substate.keys()))
1954 1964
1955 1965 return False
1956 1966
1957 1967 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
1958 1968
1959 1969 def _mapbynodefunc(repo, s, f):
1960 1970 """(repo, smartset, [node] -> [node]) -> smartset
1961 1971
1962 1972 Helper method to map a smartset to another smartset given a function only
1963 1973 talking about nodes. Handles converting between rev numbers and nodes, and
1964 1974 filtering.
1965 1975 """
1966 1976 cl = repo.unfiltered().changelog
1967 1977 torev = cl.rev
1968 1978 tonode = cl.node
1969 1979 nodemap = cl.nodemap
1970 1980 result = set(torev(n) for n in f(tonode(r) for r in s) if n in nodemap)
1971 1981 return smartset.baseset(result - repo.changelog.filteredrevs)
1972 1982
1973 1983 @predicate('successors(set)', safe=True)
1974 1984 def successors(repo, subset, x):
1975 1985 """All successors for set, including the given set themselves"""
1976 1986 s = getset(repo, fullreposet(repo), x)
1977 1987 f = lambda nodes: obsutil.allsuccessors(repo.obsstore, nodes)
1978 1988 d = _mapbynodefunc(repo, s, f)
1979 1989 return subset & d
1980 1990
1981 1991 def _substringmatcher(pattern, casesensitive=True):
1982 1992 kind, pattern, matcher = util.stringmatcher(pattern,
1983 1993 casesensitive=casesensitive)
1984 1994 if kind == 'literal':
1985 1995 if not casesensitive:
1986 1996 pattern = encoding.lower(pattern)
1987 1997 matcher = lambda s: pattern in encoding.lower(s)
1988 1998 else:
1989 1999 matcher = lambda s: pattern in s
1990 2000 return kind, pattern, matcher
1991 2001
1992 2002 @predicate('tag([name])', safe=True)
1993 2003 def tag(repo, subset, x):
1994 2004 """The specified tag by name, or all tagged revisions if no name is given.
1995 2005
1996 2006 Pattern matching is supported for `name`. See
1997 2007 :hg:`help revisions.patterns`.
1998 2008 """
1999 2009 # i18n: "tag" is a keyword
2000 2010 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
2001 2011 cl = repo.changelog
2002 2012 if args:
2003 2013 pattern = getstring(args[0],
2004 2014 # i18n: "tag" is a keyword
2005 2015 _('the argument to tag must be a string'))
2006 2016 kind, pattern, matcher = util.stringmatcher(pattern)
2007 2017 if kind == 'literal':
2008 2018 # avoid resolving all tags
2009 2019 tn = repo._tagscache.tags.get(pattern, None)
2010 2020 if tn is None:
2011 2021 raise error.RepoLookupError(_("tag '%s' does not exist")
2012 2022 % pattern)
2013 2023 s = {repo[tn].rev()}
2014 2024 else:
2015 2025 s = {cl.rev(n) for t, n in repo.tagslist() if matcher(t)}
2016 2026 else:
2017 2027 s = {cl.rev(n) for t, n in repo.tagslist() if t != 'tip'}
2018 2028 return subset & s
2019 2029
2020 2030 @predicate('tagged', safe=True)
2021 2031 def tagged(repo, subset, x):
2022 2032 return tag(repo, subset, x)
2023 2033
2024 2034 @predicate('unstable()', safe=True)
2025 2035 def unstable(repo, subset, x):
2026 2036 msg = ("'unstable()' is deprecated, "
2027 2037 "use 'orphan()'")
2028 2038 repo.ui.deprecwarn(msg, '4.4')
2029 2039
2030 2040 return orphan(repo, subset, x)
2031 2041
2032 2042 @predicate('orphan()', safe=True)
2033 2043 def orphan(repo, subset, x):
2034 2044 """Non-obsolete changesets with obsolete ancestors. (EXPERIMENTAL)
2035 2045 """
2036 2046 # i18n: "orphan" is a keyword
2037 2047 getargs(x, 0, 0, _("orphan takes no arguments"))
2038 2048 orphan = obsmod.getrevs(repo, 'orphan')
2039 2049 return subset & orphan
2040 2050
2041 2051
2042 2052 @predicate('user(string)', safe=True, weight=10)
2043 2053 def user(repo, subset, x):
2044 2054 """User name contains string. The match is case-insensitive.
2045 2055
2046 2056 Pattern matching is supported for `string`. See
2047 2057 :hg:`help revisions.patterns`.
2048 2058 """
2049 2059 return author(repo, subset, x)
2050 2060
2051 2061 @predicate('wdir()', safe=True, weight=0)
2052 2062 def wdir(repo, subset, x):
2053 2063 """Working directory. (EXPERIMENTAL)"""
2054 2064 # i18n: "wdir" is a keyword
2055 2065 getargs(x, 0, 0, _("wdir takes no arguments"))
2056 2066 if node.wdirrev in subset or isinstance(subset, fullreposet):
2057 2067 return baseset([node.wdirrev])
2058 2068 return baseset()
2059 2069
2060 2070 def _orderedlist(repo, subset, x):
2061 2071 s = getstring(x, "internal error")
2062 2072 if not s:
2063 2073 return baseset()
2064 2074 # remove duplicates here. it's difficult for caller to deduplicate sets
2065 2075 # because different symbols can point to the same rev.
2066 2076 cl = repo.changelog
2067 2077 ls = []
2068 2078 seen = set()
2069 2079 for t in s.split('\0'):
2070 2080 try:
2071 2081 # fast path for integer revision
2072 2082 r = int(t)
2073 2083 if str(r) != t or r not in cl:
2074 2084 raise ValueError
2075 2085 revs = [r]
2076 2086 except ValueError:
2077 2087 revs = stringset(repo, subset, t, defineorder)
2078 2088
2079 2089 for r in revs:
2080 2090 if r in seen:
2081 2091 continue
2082 2092 if (r in subset
2083 2093 or r == node.nullrev and isinstance(subset, fullreposet)):
2084 2094 ls.append(r)
2085 2095 seen.add(r)
2086 2096 return baseset(ls)
2087 2097
2088 2098 # for internal use
2089 2099 @predicate('_list', safe=True, takeorder=True)
2090 2100 def _list(repo, subset, x, order):
2091 2101 if order == followorder:
2092 2102 # slow path to take the subset order
2093 2103 return subset & _orderedlist(repo, fullreposet(repo), x)
2094 2104 else:
2095 2105 return _orderedlist(repo, subset, x)
2096 2106
2097 2107 def _orderedintlist(repo, subset, x):
2098 2108 s = getstring(x, "internal error")
2099 2109 if not s:
2100 2110 return baseset()
2101 2111 ls = [int(r) for r in s.split('\0')]
2102 2112 s = subset
2103 2113 return baseset([r for r in ls if r in s])
2104 2114
2105 2115 # for internal use
2106 2116 @predicate('_intlist', safe=True, takeorder=True, weight=0)
2107 2117 def _intlist(repo, subset, x, order):
2108 2118 if order == followorder:
2109 2119 # slow path to take the subset order
2110 2120 return subset & _orderedintlist(repo, fullreposet(repo), x)
2111 2121 else:
2112 2122 return _orderedintlist(repo, subset, x)
2113 2123
2114 2124 def _orderedhexlist(repo, subset, x):
2115 2125 s = getstring(x, "internal error")
2116 2126 if not s:
2117 2127 return baseset()
2118 2128 cl = repo.changelog
2119 2129 ls = [cl.rev(node.bin(r)) for r in s.split('\0')]
2120 2130 s = subset
2121 2131 return baseset([r for r in ls if r in s])
2122 2132
2123 2133 # for internal use
2124 2134 @predicate('_hexlist', safe=True, takeorder=True)
2125 2135 def _hexlist(repo, subset, x, order):
2126 2136 if order == followorder:
2127 2137 # slow path to take the subset order
2128 2138 return subset & _orderedhexlist(repo, fullreposet(repo), x)
2129 2139 else:
2130 2140 return _orderedhexlist(repo, subset, x)
2131 2141
2132 2142 methods = {
2133 2143 "range": rangeset,
2134 2144 "rangeall": rangeall,
2135 2145 "rangepre": rangepre,
2136 2146 "rangepost": rangepost,
2137 2147 "dagrange": dagrange,
2138 2148 "string": stringset,
2139 2149 "symbol": stringset,
2140 2150 "and": andset,
2141 2151 "andsmally": andsmallyset,
2142 2152 "or": orset,
2143 2153 "not": notset,
2144 2154 "difference": differenceset,
2145 2155 "relation": relationset,
2146 2156 "relsubscript": relsubscriptset,
2147 2157 "subscript": subscriptset,
2148 2158 "list": listset,
2149 2159 "keyvalue": keyvaluepair,
2150 2160 "func": func,
2151 2161 "ancestor": ancestorspec,
2152 2162 "parent": parentspec,
2153 2163 "parentpost": parentpost,
2154 2164 }
2155 2165
2156 2166 def posttreebuilthook(tree, repo):
2157 2167 # hook for extensions to execute code on the optimized tree
2158 2168 pass
2159 2169
2160 2170 def match(ui, spec, repo=None):
2161 2171 """Create a matcher for a single revision spec"""
2162 2172 return matchany(ui, [spec], repo=repo)
2163 2173
2164 2174 def matchany(ui, specs, repo=None, localalias=None):
2165 2175 """Create a matcher that will include any revisions matching one of the
2166 2176 given specs
2167 2177
2168 2178 If localalias is not None, it is a dict {name: definitionstring}. It takes
2169 2179 precedence over [revsetalias] config section.
2170 2180 """
2171 2181 if not specs:
2172 2182 def mfunc(repo, subset=None):
2173 2183 return baseset()
2174 2184 return mfunc
2175 2185 if not all(specs):
2176 2186 raise error.ParseError(_("empty query"))
2177 2187 lookup = None
2178 2188 if repo:
2179 2189 lookup = repo.__contains__
2180 2190 if len(specs) == 1:
2181 2191 tree = revsetlang.parse(specs[0], lookup)
2182 2192 else:
2183 2193 tree = ('or',
2184 2194 ('list',) + tuple(revsetlang.parse(s, lookup) for s in specs))
2185 2195
2186 2196 aliases = []
2187 2197 warn = None
2188 2198 if ui:
2189 2199 aliases.extend(ui.configitems('revsetalias'))
2190 2200 warn = ui.warn
2191 2201 if localalias:
2192 2202 aliases.extend(localalias.items())
2193 2203 if aliases:
2194 2204 tree = revsetlang.expandaliases(tree, aliases, warn=warn)
2195 2205 tree = revsetlang.foldconcat(tree)
2196 2206 tree = revsetlang.analyze(tree)
2197 2207 tree = revsetlang.optimize(tree)
2198 2208 posttreebuilthook(tree, repo)
2199 2209 return makematcher(tree)
2200 2210
2201 2211 def makematcher(tree):
2202 2212 """Create a matcher from an evaluatable tree"""
2203 2213 def mfunc(repo, subset=None, order=None):
2204 2214 if order is None:
2205 2215 if subset is None:
2206 2216 order = defineorder # 'x'
2207 2217 else:
2208 2218 order = followorder # 'subset & x'
2209 2219 if subset is None:
2210 2220 subset = fullreposet(repo)
2211 2221 return getset(repo, subset, tree, order)
2212 2222 return mfunc
2213 2223
2214 2224 def loadpredicate(ui, extname, registrarobj):
2215 2225 """Load revset predicates from specified registrarobj
2216 2226 """
2217 2227 for name, func in registrarobj._table.iteritems():
2218 2228 symbols[name] = func
2219 2229 if func._safe:
2220 2230 safesymbols.add(name)
2221 2231
2222 2232 # load built-in predicates explicitly to setup safesymbols
2223 2233 loadpredicate(None, None, predicate)
2224 2234
2225 2235 # tell hggettext to extract docstrings from these functions:
2226 2236 i18nfunctions = symbols.values()
@@ -1,3484 +1,3486 b''
1 1 @ (34) head
2 2 |
3 3 | o (33) head
4 4 | |
5 5 o | (32) expand
6 6 |\ \
7 7 | o \ (31) expand
8 8 | |\ \
9 9 | | o \ (30) expand
10 10 | | |\ \
11 11 | | | o | (29) regular commit
12 12 | | | | |
13 13 | | o | | (28) merge zero known
14 14 | | |\ \ \
15 15 o | | | | | (27) collapse
16 16 |/ / / / /
17 17 | | o---+ (26) merge one known; far right
18 18 | | | | |
19 19 +---o | | (25) merge one known; far left
20 20 | | | | |
21 21 | | o | | (24) merge one known; immediate right
22 22 | | |\| |
23 23 | | o | | (23) merge one known; immediate left
24 24 | |/| | |
25 25 +---o---+ (22) merge two known; one far left, one far right
26 26 | | / /
27 27 o | | | (21) expand
28 28 |\ \ \ \
29 29 | o---+-+ (20) merge two known; two far right
30 30 | / / /
31 31 o | | | (19) expand
32 32 |\ \ \ \
33 33 +---+---o (18) merge two known; two far left
34 34 | | | |
35 35 | o | | (17) expand
36 36 | |\ \ \
37 37 | | o---+ (16) merge two known; one immediate right, one near right
38 38 | | |/ /
39 39 o | | | (15) expand
40 40 |\ \ \ \
41 41 | o-----+ (14) merge two known; one immediate right, one far right
42 42 | |/ / /
43 43 o | | | (13) expand
44 44 |\ \ \ \
45 45 +---o | | (12) merge two known; one immediate right, one far left
46 46 | | |/ /
47 47 | o | | (11) expand
48 48 | |\ \ \
49 49 | | o---+ (10) merge two known; one immediate left, one near right
50 50 | |/ / /
51 51 o | | | (9) expand
52 52 |\ \ \ \
53 53 | o-----+ (8) merge two known; one immediate left, one far right
54 54 |/ / / /
55 55 o | | | (7) expand
56 56 |\ \ \ \
57 57 +---o | | (6) merge two known; one immediate left, one far left
58 58 | |/ / /
59 59 | o | | (5) expand
60 60 | |\ \ \
61 61 | | o | | (4) merge two known; one immediate left, one immediate right
62 62 | |/|/ /
63 63 | o / / (3) collapse
64 64 |/ / /
65 65 o / / (2) collapse
66 66 |/ /
67 67 o / (1) collapse
68 68 |/
69 69 o (0) root
70 70
71 71
72 72 $ commit()
73 73 > {
74 74 > rev=$1
75 75 > msg=$2
76 76 > shift 2
77 77 > if [ "$#" -gt 0 ]; then
78 78 > hg debugsetparents "$@"
79 79 > fi
80 80 > echo $rev > a
81 81 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
82 82 > }
83 83
84 84 $ cat > printrevset.py <<EOF
85 85 > from __future__ import absolute_import
86 86 > from mercurial import (
87 87 > cmdutil,
88 88 > commands,
89 89 > extensions,
90 90 > revsetlang,
91 91 > smartset,
92 92 > )
93 93 >
94 94 > def logrevset(repo, pats, opts):
95 95 > revs = cmdutil._logrevs(repo, opts)
96 96 > if not revs:
97 97 > return None
98 98 > match, pats, slowpath = cmdutil._makelogmatcher(repo, revs, pats, opts)
99 99 > return cmdutil._makelogrevset(repo, match, pats, slowpath, opts)
100 100 >
101 101 > def uisetup(ui):
102 102 > def printrevset(orig, repo, pats, opts):
103 103 > revs, filematcher = orig(repo, pats, opts)
104 104 > if opts.get('print_revset'):
105 105 > expr = logrevset(repo, pats, opts)
106 106 > if expr:
107 107 > tree = revsetlang.parse(expr)
108 108 > tree = revsetlang.analyze(tree)
109 109 > else:
110 110 > tree = []
111 111 > ui = repo.ui
112 112 > ui.write('%r\n' % (opts.get('rev', []),))
113 113 > ui.write(revsetlang.prettyformat(tree) + '\n')
114 114 > ui.write(smartset.prettyformat(revs) + '\n')
115 115 > revs = smartset.baseset() # display no revisions
116 116 > return revs, filematcher
117 117 > extensions.wrapfunction(cmdutil, 'getlogrevs', printrevset)
118 118 > aliases, entry = cmdutil.findcmd('log', commands.table)
119 119 > entry[1].append(('', 'print-revset', False,
120 120 > 'print generated revset and exit (DEPRECATED)'))
121 121 > EOF
122 122
123 123 $ echo "[extensions]" >> $HGRCPATH
124 124 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
125 125
126 126 $ hg init repo
127 127 $ cd repo
128 128
129 129 Empty repo:
130 130
131 131 $ hg log -G
132 132
133 133
134 134 Building DAG:
135 135
136 136 $ commit 0 "root"
137 137 $ commit 1 "collapse" 0
138 138 $ commit 2 "collapse" 1
139 139 $ commit 3 "collapse" 2
140 140 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
141 141 $ commit 5 "expand" 3 4
142 142 $ commit 6 "merge two known; one immediate left, one far left" 2 5
143 143 $ commit 7 "expand" 2 5
144 144 $ commit 8 "merge two known; one immediate left, one far right" 0 7
145 145 $ commit 9 "expand" 7 8
146 146 $ commit 10 "merge two known; one immediate left, one near right" 0 6
147 147 $ commit 11 "expand" 6 10
148 148 $ commit 12 "merge two known; one immediate right, one far left" 1 9
149 149 $ commit 13 "expand" 9 11
150 150 $ commit 14 "merge two known; one immediate right, one far right" 0 12
151 151 $ commit 15 "expand" 13 14
152 152 $ commit 16 "merge two known; one immediate right, one near right" 0 1
153 153 $ commit 17 "expand" 12 16
154 154 $ commit 18 "merge two known; two far left" 1 15
155 155 $ commit 19 "expand" 15 17
156 156 $ commit 20 "merge two known; two far right" 0 18
157 157 $ commit 21 "expand" 19 20
158 158 $ commit 22 "merge two known; one far left, one far right" 18 21
159 159 $ commit 23 "merge one known; immediate left" 1 22
160 160 $ commit 24 "merge one known; immediate right" 0 23
161 161 $ commit 25 "merge one known; far left" 21 24
162 162 $ commit 26 "merge one known; far right" 18 25
163 163 $ commit 27 "collapse" 21
164 164 $ commit 28 "merge zero known" 1 26
165 165 $ commit 29 "regular commit" 0
166 166 $ commit 30 "expand" 28 29
167 167 $ commit 31 "expand" 21 30
168 168 $ commit 32 "expand" 27 31
169 169 $ commit 33 "head" 18
170 170 $ commit 34 "head" 32
171 171
172 172
173 173 $ hg log -G -q
174 174 @ 34:fea3ac5810e0
175 175 |
176 176 | o 33:68608f5145f9
177 177 | |
178 178 o | 32:d06dffa21a31
179 179 |\ \
180 180 | o \ 31:621d83e11f67
181 181 | |\ \
182 182 | | o \ 30:6e11cd4b648f
183 183 | | |\ \
184 184 | | | o | 29:cd9bb2be7593
185 185 | | | | |
186 186 | | o | | 28:44ecd0b9ae99
187 187 | | |\ \ \
188 188 o | | | | | 27:886ed638191b
189 189 |/ / / / /
190 190 | | o---+ 26:7f25b6c2f0b9
191 191 | | | | |
192 192 +---o | | 25:91da8ed57247
193 193 | | | | |
194 194 | | o | | 24:a9c19a3d96b7
195 195 | | |\| |
196 196 | | o | | 23:a01cddf0766d
197 197 | |/| | |
198 198 +---o---+ 22:e0d9cccacb5d
199 199 | | / /
200 200 o | | | 21:d42a756af44d
201 201 |\ \ \ \
202 202 | o---+-+ 20:d30ed6450e32
203 203 | / / /
204 204 o | | | 19:31ddc2c1573b
205 205 |\ \ \ \
206 206 +---+---o 18:1aa84d96232a
207 207 | | | |
208 208 | o | | 17:44765d7c06e0
209 209 | |\ \ \
210 210 | | o---+ 16:3677d192927d
211 211 | | |/ /
212 212 o | | | 15:1dda3f72782d
213 213 |\ \ \ \
214 214 | o-----+ 14:8eac370358ef
215 215 | |/ / /
216 216 o | | | 13:22d8966a97e3
217 217 |\ \ \ \
218 218 +---o | | 12:86b91144a6e9
219 219 | | |/ /
220 220 | o | | 11:832d76e6bdf2
221 221 | |\ \ \
222 222 | | o---+ 10:74c64d036d72
223 223 | |/ / /
224 224 o | | | 9:7010c0af0a35
225 225 |\ \ \ \
226 226 | o-----+ 8:7a0b11f71937
227 227 |/ / / /
228 228 o | | | 7:b632bb1b1224
229 229 |\ \ \ \
230 230 +---o | | 6:b105a072e251
231 231 | |/ / /
232 232 | o | | 5:4409d547b708
233 233 | |\ \ \
234 234 | | o | | 4:26a8bac39d9f
235 235 | |/|/ /
236 236 | o / / 3:27eef8ed80b4
237 237 |/ / /
238 238 o / / 2:3d9a33b8d1e1
239 239 |/ /
240 240 o / 1:6db2ef61d156
241 241 |/
242 242 o 0:e6eb3150255d
243 243
244 244
245 245 $ hg log -G
246 246 @ changeset: 34:fea3ac5810e0
247 247 | tag: tip
248 248 | parent: 32:d06dffa21a31
249 249 | user: test
250 250 | date: Thu Jan 01 00:00:34 1970 +0000
251 251 | summary: (34) head
252 252 |
253 253 | o changeset: 33:68608f5145f9
254 254 | | parent: 18:1aa84d96232a
255 255 | | user: test
256 256 | | date: Thu Jan 01 00:00:33 1970 +0000
257 257 | | summary: (33) head
258 258 | |
259 259 o | changeset: 32:d06dffa21a31
260 260 |\ \ parent: 27:886ed638191b
261 261 | | | parent: 31:621d83e11f67
262 262 | | | user: test
263 263 | | | date: Thu Jan 01 00:00:32 1970 +0000
264 264 | | | summary: (32) expand
265 265 | | |
266 266 | o | changeset: 31:621d83e11f67
267 267 | |\ \ parent: 21:d42a756af44d
268 268 | | | | parent: 30:6e11cd4b648f
269 269 | | | | user: test
270 270 | | | | date: Thu Jan 01 00:00:31 1970 +0000
271 271 | | | | summary: (31) expand
272 272 | | | |
273 273 | | o | changeset: 30:6e11cd4b648f
274 274 | | |\ \ parent: 28:44ecd0b9ae99
275 275 | | | | | parent: 29:cd9bb2be7593
276 276 | | | | | user: test
277 277 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
278 278 | | | | | summary: (30) expand
279 279 | | | | |
280 280 | | | o | changeset: 29:cd9bb2be7593
281 281 | | | | | parent: 0:e6eb3150255d
282 282 | | | | | user: test
283 283 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
284 284 | | | | | summary: (29) regular commit
285 285 | | | | |
286 286 | | o | | changeset: 28:44ecd0b9ae99
287 287 | | |\ \ \ parent: 1:6db2ef61d156
288 288 | | | | | | parent: 26:7f25b6c2f0b9
289 289 | | | | | | user: test
290 290 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
291 291 | | | | | | summary: (28) merge zero known
292 292 | | | | | |
293 293 o | | | | | changeset: 27:886ed638191b
294 294 |/ / / / / parent: 21:d42a756af44d
295 295 | | | | | user: test
296 296 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
297 297 | | | | | summary: (27) collapse
298 298 | | | | |
299 299 | | o---+ changeset: 26:7f25b6c2f0b9
300 300 | | | | | parent: 18:1aa84d96232a
301 301 | | | | | parent: 25:91da8ed57247
302 302 | | | | | user: test
303 303 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
304 304 | | | | | summary: (26) merge one known; far right
305 305 | | | | |
306 306 +---o | | changeset: 25:91da8ed57247
307 307 | | | | | parent: 21:d42a756af44d
308 308 | | | | | parent: 24:a9c19a3d96b7
309 309 | | | | | user: test
310 310 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
311 311 | | | | | summary: (25) merge one known; far left
312 312 | | | | |
313 313 | | o | | changeset: 24:a9c19a3d96b7
314 314 | | |\| | parent: 0:e6eb3150255d
315 315 | | | | | parent: 23:a01cddf0766d
316 316 | | | | | user: test
317 317 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
318 318 | | | | | summary: (24) merge one known; immediate right
319 319 | | | | |
320 320 | | o | | changeset: 23:a01cddf0766d
321 321 | |/| | | parent: 1:6db2ef61d156
322 322 | | | | | parent: 22:e0d9cccacb5d
323 323 | | | | | user: test
324 324 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
325 325 | | | | | summary: (23) merge one known; immediate left
326 326 | | | | |
327 327 +---o---+ changeset: 22:e0d9cccacb5d
328 328 | | | | parent: 18:1aa84d96232a
329 329 | | / / parent: 21:d42a756af44d
330 330 | | | | user: test
331 331 | | | | date: Thu Jan 01 00:00:22 1970 +0000
332 332 | | | | summary: (22) merge two known; one far left, one far right
333 333 | | | |
334 334 o | | | changeset: 21:d42a756af44d
335 335 |\ \ \ \ parent: 19:31ddc2c1573b
336 336 | | | | | parent: 20:d30ed6450e32
337 337 | | | | | user: test
338 338 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
339 339 | | | | | summary: (21) expand
340 340 | | | | |
341 341 | o---+-+ changeset: 20:d30ed6450e32
342 342 | | | | parent: 0:e6eb3150255d
343 343 | / / / parent: 18:1aa84d96232a
344 344 | | | | user: test
345 345 | | | | date: Thu Jan 01 00:00:20 1970 +0000
346 346 | | | | summary: (20) merge two known; two far right
347 347 | | | |
348 348 o | | | changeset: 19:31ddc2c1573b
349 349 |\ \ \ \ parent: 15:1dda3f72782d
350 350 | | | | | parent: 17:44765d7c06e0
351 351 | | | | | user: test
352 352 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
353 353 | | | | | summary: (19) expand
354 354 | | | | |
355 355 +---+---o changeset: 18:1aa84d96232a
356 356 | | | | parent: 1:6db2ef61d156
357 357 | | | | parent: 15:1dda3f72782d
358 358 | | | | user: test
359 359 | | | | date: Thu Jan 01 00:00:18 1970 +0000
360 360 | | | | summary: (18) merge two known; two far left
361 361 | | | |
362 362 | o | | changeset: 17:44765d7c06e0
363 363 | |\ \ \ parent: 12:86b91144a6e9
364 364 | | | | | parent: 16:3677d192927d
365 365 | | | | | user: test
366 366 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
367 367 | | | | | summary: (17) expand
368 368 | | | | |
369 369 | | o---+ changeset: 16:3677d192927d
370 370 | | | | | parent: 0:e6eb3150255d
371 371 | | |/ / parent: 1:6db2ef61d156
372 372 | | | | user: test
373 373 | | | | date: Thu Jan 01 00:00:16 1970 +0000
374 374 | | | | summary: (16) merge two known; one immediate right, one near right
375 375 | | | |
376 376 o | | | changeset: 15:1dda3f72782d
377 377 |\ \ \ \ parent: 13:22d8966a97e3
378 378 | | | | | parent: 14:8eac370358ef
379 379 | | | | | user: test
380 380 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
381 381 | | | | | summary: (15) expand
382 382 | | | | |
383 383 | o-----+ changeset: 14:8eac370358ef
384 384 | | | | | parent: 0:e6eb3150255d
385 385 | |/ / / parent: 12:86b91144a6e9
386 386 | | | | user: test
387 387 | | | | date: Thu Jan 01 00:00:14 1970 +0000
388 388 | | | | summary: (14) merge two known; one immediate right, one far right
389 389 | | | |
390 390 o | | | changeset: 13:22d8966a97e3
391 391 |\ \ \ \ parent: 9:7010c0af0a35
392 392 | | | | | parent: 11:832d76e6bdf2
393 393 | | | | | user: test
394 394 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
395 395 | | | | | summary: (13) expand
396 396 | | | | |
397 397 +---o | | changeset: 12:86b91144a6e9
398 398 | | |/ / parent: 1:6db2ef61d156
399 399 | | | | parent: 9:7010c0af0a35
400 400 | | | | user: test
401 401 | | | | date: Thu Jan 01 00:00:12 1970 +0000
402 402 | | | | summary: (12) merge two known; one immediate right, one far left
403 403 | | | |
404 404 | o | | changeset: 11:832d76e6bdf2
405 405 | |\ \ \ parent: 6:b105a072e251
406 406 | | | | | parent: 10:74c64d036d72
407 407 | | | | | user: test
408 408 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
409 409 | | | | | summary: (11) expand
410 410 | | | | |
411 411 | | o---+ changeset: 10:74c64d036d72
412 412 | | | | | parent: 0:e6eb3150255d
413 413 | |/ / / parent: 6:b105a072e251
414 414 | | | | user: test
415 415 | | | | date: Thu Jan 01 00:00:10 1970 +0000
416 416 | | | | summary: (10) merge two known; one immediate left, one near right
417 417 | | | |
418 418 o | | | changeset: 9:7010c0af0a35
419 419 |\ \ \ \ parent: 7:b632bb1b1224
420 420 | | | | | parent: 8:7a0b11f71937
421 421 | | | | | user: test
422 422 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
423 423 | | | | | summary: (9) expand
424 424 | | | | |
425 425 | o-----+ changeset: 8:7a0b11f71937
426 426 | | | | | parent: 0:e6eb3150255d
427 427 |/ / / / parent: 7:b632bb1b1224
428 428 | | | | user: test
429 429 | | | | date: Thu Jan 01 00:00:08 1970 +0000
430 430 | | | | summary: (8) merge two known; one immediate left, one far right
431 431 | | | |
432 432 o | | | changeset: 7:b632bb1b1224
433 433 |\ \ \ \ parent: 2:3d9a33b8d1e1
434 434 | | | | | parent: 5:4409d547b708
435 435 | | | | | user: test
436 436 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
437 437 | | | | | summary: (7) expand
438 438 | | | | |
439 439 +---o | | changeset: 6:b105a072e251
440 440 | |/ / / parent: 2:3d9a33b8d1e1
441 441 | | | | parent: 5:4409d547b708
442 442 | | | | user: test
443 443 | | | | date: Thu Jan 01 00:00:06 1970 +0000
444 444 | | | | summary: (6) merge two known; one immediate left, one far left
445 445 | | | |
446 446 | o | | changeset: 5:4409d547b708
447 447 | |\ \ \ parent: 3:27eef8ed80b4
448 448 | | | | | parent: 4:26a8bac39d9f
449 449 | | | | | user: test
450 450 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
451 451 | | | | | summary: (5) expand
452 452 | | | | |
453 453 | | o | | changeset: 4:26a8bac39d9f
454 454 | |/|/ / parent: 1:6db2ef61d156
455 455 | | | | parent: 3:27eef8ed80b4
456 456 | | | | user: test
457 457 | | | | date: Thu Jan 01 00:00:04 1970 +0000
458 458 | | | | summary: (4) merge two known; one immediate left, one immediate right
459 459 | | | |
460 460 | o | | changeset: 3:27eef8ed80b4
461 461 |/ / / user: test
462 462 | | | date: Thu Jan 01 00:00:03 1970 +0000
463 463 | | | summary: (3) collapse
464 464 | | |
465 465 o | | changeset: 2:3d9a33b8d1e1
466 466 |/ / user: test
467 467 | | date: Thu Jan 01 00:00:02 1970 +0000
468 468 | | summary: (2) collapse
469 469 | |
470 470 o | changeset: 1:6db2ef61d156
471 471 |/ user: test
472 472 | date: Thu Jan 01 00:00:01 1970 +0000
473 473 | summary: (1) collapse
474 474 |
475 475 o changeset: 0:e6eb3150255d
476 476 user: test
477 477 date: Thu Jan 01 00:00:00 1970 +0000
478 478 summary: (0) root
479 479
480 480
481 481 File glog:
482 482 $ hg log -G a
483 483 @ changeset: 34:fea3ac5810e0
484 484 | tag: tip
485 485 | parent: 32:d06dffa21a31
486 486 | user: test
487 487 | date: Thu Jan 01 00:00:34 1970 +0000
488 488 | summary: (34) head
489 489 |
490 490 | o changeset: 33:68608f5145f9
491 491 | | parent: 18:1aa84d96232a
492 492 | | user: test
493 493 | | date: Thu Jan 01 00:00:33 1970 +0000
494 494 | | summary: (33) head
495 495 | |
496 496 o | changeset: 32:d06dffa21a31
497 497 |\ \ parent: 27:886ed638191b
498 498 | | | parent: 31:621d83e11f67
499 499 | | | user: test
500 500 | | | date: Thu Jan 01 00:00:32 1970 +0000
501 501 | | | summary: (32) expand
502 502 | | |
503 503 | o | changeset: 31:621d83e11f67
504 504 | |\ \ parent: 21:d42a756af44d
505 505 | | | | parent: 30:6e11cd4b648f
506 506 | | | | user: test
507 507 | | | | date: Thu Jan 01 00:00:31 1970 +0000
508 508 | | | | summary: (31) expand
509 509 | | | |
510 510 | | o | changeset: 30:6e11cd4b648f
511 511 | | |\ \ parent: 28:44ecd0b9ae99
512 512 | | | | | parent: 29:cd9bb2be7593
513 513 | | | | | user: test
514 514 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
515 515 | | | | | summary: (30) expand
516 516 | | | | |
517 517 | | | o | changeset: 29:cd9bb2be7593
518 518 | | | | | parent: 0:e6eb3150255d
519 519 | | | | | user: test
520 520 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
521 521 | | | | | summary: (29) regular commit
522 522 | | | | |
523 523 | | o | | changeset: 28:44ecd0b9ae99
524 524 | | |\ \ \ parent: 1:6db2ef61d156
525 525 | | | | | | parent: 26:7f25b6c2f0b9
526 526 | | | | | | user: test
527 527 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
528 528 | | | | | | summary: (28) merge zero known
529 529 | | | | | |
530 530 o | | | | | changeset: 27:886ed638191b
531 531 |/ / / / / parent: 21:d42a756af44d
532 532 | | | | | user: test
533 533 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
534 534 | | | | | summary: (27) collapse
535 535 | | | | |
536 536 | | o---+ changeset: 26:7f25b6c2f0b9
537 537 | | | | | parent: 18:1aa84d96232a
538 538 | | | | | parent: 25:91da8ed57247
539 539 | | | | | user: test
540 540 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
541 541 | | | | | summary: (26) merge one known; far right
542 542 | | | | |
543 543 +---o | | changeset: 25:91da8ed57247
544 544 | | | | | parent: 21:d42a756af44d
545 545 | | | | | parent: 24:a9c19a3d96b7
546 546 | | | | | user: test
547 547 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
548 548 | | | | | summary: (25) merge one known; far left
549 549 | | | | |
550 550 | | o | | changeset: 24:a9c19a3d96b7
551 551 | | |\| | parent: 0:e6eb3150255d
552 552 | | | | | parent: 23:a01cddf0766d
553 553 | | | | | user: test
554 554 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
555 555 | | | | | summary: (24) merge one known; immediate right
556 556 | | | | |
557 557 | | o | | changeset: 23:a01cddf0766d
558 558 | |/| | | parent: 1:6db2ef61d156
559 559 | | | | | parent: 22:e0d9cccacb5d
560 560 | | | | | user: test
561 561 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
562 562 | | | | | summary: (23) merge one known; immediate left
563 563 | | | | |
564 564 +---o---+ changeset: 22:e0d9cccacb5d
565 565 | | | | parent: 18:1aa84d96232a
566 566 | | / / parent: 21:d42a756af44d
567 567 | | | | user: test
568 568 | | | | date: Thu Jan 01 00:00:22 1970 +0000
569 569 | | | | summary: (22) merge two known; one far left, one far right
570 570 | | | |
571 571 o | | | changeset: 21:d42a756af44d
572 572 |\ \ \ \ parent: 19:31ddc2c1573b
573 573 | | | | | parent: 20:d30ed6450e32
574 574 | | | | | user: test
575 575 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
576 576 | | | | | summary: (21) expand
577 577 | | | | |
578 578 | o---+-+ changeset: 20:d30ed6450e32
579 579 | | | | parent: 0:e6eb3150255d
580 580 | / / / parent: 18:1aa84d96232a
581 581 | | | | user: test
582 582 | | | | date: Thu Jan 01 00:00:20 1970 +0000
583 583 | | | | summary: (20) merge two known; two far right
584 584 | | | |
585 585 o | | | changeset: 19:31ddc2c1573b
586 586 |\ \ \ \ parent: 15:1dda3f72782d
587 587 | | | | | parent: 17:44765d7c06e0
588 588 | | | | | user: test
589 589 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
590 590 | | | | | summary: (19) expand
591 591 | | | | |
592 592 +---+---o changeset: 18:1aa84d96232a
593 593 | | | | parent: 1:6db2ef61d156
594 594 | | | | parent: 15:1dda3f72782d
595 595 | | | | user: test
596 596 | | | | date: Thu Jan 01 00:00:18 1970 +0000
597 597 | | | | summary: (18) merge two known; two far left
598 598 | | | |
599 599 | o | | changeset: 17:44765d7c06e0
600 600 | |\ \ \ parent: 12:86b91144a6e9
601 601 | | | | | parent: 16:3677d192927d
602 602 | | | | | user: test
603 603 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
604 604 | | | | | summary: (17) expand
605 605 | | | | |
606 606 | | o---+ changeset: 16:3677d192927d
607 607 | | | | | parent: 0:e6eb3150255d
608 608 | | |/ / parent: 1:6db2ef61d156
609 609 | | | | user: test
610 610 | | | | date: Thu Jan 01 00:00:16 1970 +0000
611 611 | | | | summary: (16) merge two known; one immediate right, one near right
612 612 | | | |
613 613 o | | | changeset: 15:1dda3f72782d
614 614 |\ \ \ \ parent: 13:22d8966a97e3
615 615 | | | | | parent: 14:8eac370358ef
616 616 | | | | | user: test
617 617 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
618 618 | | | | | summary: (15) expand
619 619 | | | | |
620 620 | o-----+ changeset: 14:8eac370358ef
621 621 | | | | | parent: 0:e6eb3150255d
622 622 | |/ / / parent: 12:86b91144a6e9
623 623 | | | | user: test
624 624 | | | | date: Thu Jan 01 00:00:14 1970 +0000
625 625 | | | | summary: (14) merge two known; one immediate right, one far right
626 626 | | | |
627 627 o | | | changeset: 13:22d8966a97e3
628 628 |\ \ \ \ parent: 9:7010c0af0a35
629 629 | | | | | parent: 11:832d76e6bdf2
630 630 | | | | | user: test
631 631 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
632 632 | | | | | summary: (13) expand
633 633 | | | | |
634 634 +---o | | changeset: 12:86b91144a6e9
635 635 | | |/ / parent: 1:6db2ef61d156
636 636 | | | | parent: 9:7010c0af0a35
637 637 | | | | user: test
638 638 | | | | date: Thu Jan 01 00:00:12 1970 +0000
639 639 | | | | summary: (12) merge two known; one immediate right, one far left
640 640 | | | |
641 641 | o | | changeset: 11:832d76e6bdf2
642 642 | |\ \ \ parent: 6:b105a072e251
643 643 | | | | | parent: 10:74c64d036d72
644 644 | | | | | user: test
645 645 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
646 646 | | | | | summary: (11) expand
647 647 | | | | |
648 648 | | o---+ changeset: 10:74c64d036d72
649 649 | | | | | parent: 0:e6eb3150255d
650 650 | |/ / / parent: 6:b105a072e251
651 651 | | | | user: test
652 652 | | | | date: Thu Jan 01 00:00:10 1970 +0000
653 653 | | | | summary: (10) merge two known; one immediate left, one near right
654 654 | | | |
655 655 o | | | changeset: 9:7010c0af0a35
656 656 |\ \ \ \ parent: 7:b632bb1b1224
657 657 | | | | | parent: 8:7a0b11f71937
658 658 | | | | | user: test
659 659 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
660 660 | | | | | summary: (9) expand
661 661 | | | | |
662 662 | o-----+ changeset: 8:7a0b11f71937
663 663 | | | | | parent: 0:e6eb3150255d
664 664 |/ / / / parent: 7:b632bb1b1224
665 665 | | | | user: test
666 666 | | | | date: Thu Jan 01 00:00:08 1970 +0000
667 667 | | | | summary: (8) merge two known; one immediate left, one far right
668 668 | | | |
669 669 o | | | changeset: 7:b632bb1b1224
670 670 |\ \ \ \ parent: 2:3d9a33b8d1e1
671 671 | | | | | parent: 5:4409d547b708
672 672 | | | | | user: test
673 673 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
674 674 | | | | | summary: (7) expand
675 675 | | | | |
676 676 +---o | | changeset: 6:b105a072e251
677 677 | |/ / / parent: 2:3d9a33b8d1e1
678 678 | | | | parent: 5:4409d547b708
679 679 | | | | user: test
680 680 | | | | date: Thu Jan 01 00:00:06 1970 +0000
681 681 | | | | summary: (6) merge two known; one immediate left, one far left
682 682 | | | |
683 683 | o | | changeset: 5:4409d547b708
684 684 | |\ \ \ parent: 3:27eef8ed80b4
685 685 | | | | | parent: 4:26a8bac39d9f
686 686 | | | | | user: test
687 687 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
688 688 | | | | | summary: (5) expand
689 689 | | | | |
690 690 | | o | | changeset: 4:26a8bac39d9f
691 691 | |/|/ / parent: 1:6db2ef61d156
692 692 | | | | parent: 3:27eef8ed80b4
693 693 | | | | user: test
694 694 | | | | date: Thu Jan 01 00:00:04 1970 +0000
695 695 | | | | summary: (4) merge two known; one immediate left, one immediate right
696 696 | | | |
697 697 | o | | changeset: 3:27eef8ed80b4
698 698 |/ / / user: test
699 699 | | | date: Thu Jan 01 00:00:03 1970 +0000
700 700 | | | summary: (3) collapse
701 701 | | |
702 702 o | | changeset: 2:3d9a33b8d1e1
703 703 |/ / user: test
704 704 | | date: Thu Jan 01 00:00:02 1970 +0000
705 705 | | summary: (2) collapse
706 706 | |
707 707 o | changeset: 1:6db2ef61d156
708 708 |/ user: test
709 709 | date: Thu Jan 01 00:00:01 1970 +0000
710 710 | summary: (1) collapse
711 711 |
712 712 o changeset: 0:e6eb3150255d
713 713 user: test
714 714 date: Thu Jan 01 00:00:00 1970 +0000
715 715 summary: (0) root
716 716
717 717
718 718 File glog per revset:
719 719
720 720 $ hg log -G -r 'file("a")'
721 721 @ changeset: 34:fea3ac5810e0
722 722 | tag: tip
723 723 | parent: 32:d06dffa21a31
724 724 | user: test
725 725 | date: Thu Jan 01 00:00:34 1970 +0000
726 726 | summary: (34) head
727 727 |
728 728 | o changeset: 33:68608f5145f9
729 729 | | parent: 18:1aa84d96232a
730 730 | | user: test
731 731 | | date: Thu Jan 01 00:00:33 1970 +0000
732 732 | | summary: (33) head
733 733 | |
734 734 o | changeset: 32:d06dffa21a31
735 735 |\ \ parent: 27:886ed638191b
736 736 | | | parent: 31:621d83e11f67
737 737 | | | user: test
738 738 | | | date: Thu Jan 01 00:00:32 1970 +0000
739 739 | | | summary: (32) expand
740 740 | | |
741 741 | o | changeset: 31:621d83e11f67
742 742 | |\ \ parent: 21:d42a756af44d
743 743 | | | | parent: 30:6e11cd4b648f
744 744 | | | | user: test
745 745 | | | | date: Thu Jan 01 00:00:31 1970 +0000
746 746 | | | | summary: (31) expand
747 747 | | | |
748 748 | | o | changeset: 30:6e11cd4b648f
749 749 | | |\ \ parent: 28:44ecd0b9ae99
750 750 | | | | | parent: 29:cd9bb2be7593
751 751 | | | | | user: test
752 752 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
753 753 | | | | | summary: (30) expand
754 754 | | | | |
755 755 | | | o | changeset: 29:cd9bb2be7593
756 756 | | | | | parent: 0:e6eb3150255d
757 757 | | | | | user: test
758 758 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
759 759 | | | | | summary: (29) regular commit
760 760 | | | | |
761 761 | | o | | changeset: 28:44ecd0b9ae99
762 762 | | |\ \ \ parent: 1:6db2ef61d156
763 763 | | | | | | parent: 26:7f25b6c2f0b9
764 764 | | | | | | user: test
765 765 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
766 766 | | | | | | summary: (28) merge zero known
767 767 | | | | | |
768 768 o | | | | | changeset: 27:886ed638191b
769 769 |/ / / / / parent: 21:d42a756af44d
770 770 | | | | | user: test
771 771 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
772 772 | | | | | summary: (27) collapse
773 773 | | | | |
774 774 | | o---+ changeset: 26:7f25b6c2f0b9
775 775 | | | | | parent: 18:1aa84d96232a
776 776 | | | | | parent: 25:91da8ed57247
777 777 | | | | | user: test
778 778 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
779 779 | | | | | summary: (26) merge one known; far right
780 780 | | | | |
781 781 +---o | | changeset: 25:91da8ed57247
782 782 | | | | | parent: 21:d42a756af44d
783 783 | | | | | parent: 24:a9c19a3d96b7
784 784 | | | | | user: test
785 785 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
786 786 | | | | | summary: (25) merge one known; far left
787 787 | | | | |
788 788 | | o | | changeset: 24:a9c19a3d96b7
789 789 | | |\| | parent: 0:e6eb3150255d
790 790 | | | | | parent: 23:a01cddf0766d
791 791 | | | | | user: test
792 792 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
793 793 | | | | | summary: (24) merge one known; immediate right
794 794 | | | | |
795 795 | | o | | changeset: 23:a01cddf0766d
796 796 | |/| | | parent: 1:6db2ef61d156
797 797 | | | | | parent: 22:e0d9cccacb5d
798 798 | | | | | user: test
799 799 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
800 800 | | | | | summary: (23) merge one known; immediate left
801 801 | | | | |
802 802 +---o---+ changeset: 22:e0d9cccacb5d
803 803 | | | | parent: 18:1aa84d96232a
804 804 | | / / parent: 21:d42a756af44d
805 805 | | | | user: test
806 806 | | | | date: Thu Jan 01 00:00:22 1970 +0000
807 807 | | | | summary: (22) merge two known; one far left, one far right
808 808 | | | |
809 809 o | | | changeset: 21:d42a756af44d
810 810 |\ \ \ \ parent: 19:31ddc2c1573b
811 811 | | | | | parent: 20:d30ed6450e32
812 812 | | | | | user: test
813 813 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
814 814 | | | | | summary: (21) expand
815 815 | | | | |
816 816 | o---+-+ changeset: 20:d30ed6450e32
817 817 | | | | parent: 0:e6eb3150255d
818 818 | / / / parent: 18:1aa84d96232a
819 819 | | | | user: test
820 820 | | | | date: Thu Jan 01 00:00:20 1970 +0000
821 821 | | | | summary: (20) merge two known; two far right
822 822 | | | |
823 823 o | | | changeset: 19:31ddc2c1573b
824 824 |\ \ \ \ parent: 15:1dda3f72782d
825 825 | | | | | parent: 17:44765d7c06e0
826 826 | | | | | user: test
827 827 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
828 828 | | | | | summary: (19) expand
829 829 | | | | |
830 830 +---+---o changeset: 18:1aa84d96232a
831 831 | | | | parent: 1:6db2ef61d156
832 832 | | | | parent: 15:1dda3f72782d
833 833 | | | | user: test
834 834 | | | | date: Thu Jan 01 00:00:18 1970 +0000
835 835 | | | | summary: (18) merge two known; two far left
836 836 | | | |
837 837 | o | | changeset: 17:44765d7c06e0
838 838 | |\ \ \ parent: 12:86b91144a6e9
839 839 | | | | | parent: 16:3677d192927d
840 840 | | | | | user: test
841 841 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
842 842 | | | | | summary: (17) expand
843 843 | | | | |
844 844 | | o---+ changeset: 16:3677d192927d
845 845 | | | | | parent: 0:e6eb3150255d
846 846 | | |/ / parent: 1:6db2ef61d156
847 847 | | | | user: test
848 848 | | | | date: Thu Jan 01 00:00:16 1970 +0000
849 849 | | | | summary: (16) merge two known; one immediate right, one near right
850 850 | | | |
851 851 o | | | changeset: 15:1dda3f72782d
852 852 |\ \ \ \ parent: 13:22d8966a97e3
853 853 | | | | | parent: 14:8eac370358ef
854 854 | | | | | user: test
855 855 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
856 856 | | | | | summary: (15) expand
857 857 | | | | |
858 858 | o-----+ changeset: 14:8eac370358ef
859 859 | | | | | parent: 0:e6eb3150255d
860 860 | |/ / / parent: 12:86b91144a6e9
861 861 | | | | user: test
862 862 | | | | date: Thu Jan 01 00:00:14 1970 +0000
863 863 | | | | summary: (14) merge two known; one immediate right, one far right
864 864 | | | |
865 865 o | | | changeset: 13:22d8966a97e3
866 866 |\ \ \ \ parent: 9:7010c0af0a35
867 867 | | | | | parent: 11:832d76e6bdf2
868 868 | | | | | user: test
869 869 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
870 870 | | | | | summary: (13) expand
871 871 | | | | |
872 872 +---o | | changeset: 12:86b91144a6e9
873 873 | | |/ / parent: 1:6db2ef61d156
874 874 | | | | parent: 9:7010c0af0a35
875 875 | | | | user: test
876 876 | | | | date: Thu Jan 01 00:00:12 1970 +0000
877 877 | | | | summary: (12) merge two known; one immediate right, one far left
878 878 | | | |
879 879 | o | | changeset: 11:832d76e6bdf2
880 880 | |\ \ \ parent: 6:b105a072e251
881 881 | | | | | parent: 10:74c64d036d72
882 882 | | | | | user: test
883 883 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
884 884 | | | | | summary: (11) expand
885 885 | | | | |
886 886 | | o---+ changeset: 10:74c64d036d72
887 887 | | | | | parent: 0:e6eb3150255d
888 888 | |/ / / parent: 6:b105a072e251
889 889 | | | | user: test
890 890 | | | | date: Thu Jan 01 00:00:10 1970 +0000
891 891 | | | | summary: (10) merge two known; one immediate left, one near right
892 892 | | | |
893 893 o | | | changeset: 9:7010c0af0a35
894 894 |\ \ \ \ parent: 7:b632bb1b1224
895 895 | | | | | parent: 8:7a0b11f71937
896 896 | | | | | user: test
897 897 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
898 898 | | | | | summary: (9) expand
899 899 | | | | |
900 900 | o-----+ changeset: 8:7a0b11f71937
901 901 | | | | | parent: 0:e6eb3150255d
902 902 |/ / / / parent: 7:b632bb1b1224
903 903 | | | | user: test
904 904 | | | | date: Thu Jan 01 00:00:08 1970 +0000
905 905 | | | | summary: (8) merge two known; one immediate left, one far right
906 906 | | | |
907 907 o | | | changeset: 7:b632bb1b1224
908 908 |\ \ \ \ parent: 2:3d9a33b8d1e1
909 909 | | | | | parent: 5:4409d547b708
910 910 | | | | | user: test
911 911 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
912 912 | | | | | summary: (7) expand
913 913 | | | | |
914 914 +---o | | changeset: 6:b105a072e251
915 915 | |/ / / parent: 2:3d9a33b8d1e1
916 916 | | | | parent: 5:4409d547b708
917 917 | | | | user: test
918 918 | | | | date: Thu Jan 01 00:00:06 1970 +0000
919 919 | | | | summary: (6) merge two known; one immediate left, one far left
920 920 | | | |
921 921 | o | | changeset: 5:4409d547b708
922 922 | |\ \ \ parent: 3:27eef8ed80b4
923 923 | | | | | parent: 4:26a8bac39d9f
924 924 | | | | | user: test
925 925 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
926 926 | | | | | summary: (5) expand
927 927 | | | | |
928 928 | | o | | changeset: 4:26a8bac39d9f
929 929 | |/|/ / parent: 1:6db2ef61d156
930 930 | | | | parent: 3:27eef8ed80b4
931 931 | | | | user: test
932 932 | | | | date: Thu Jan 01 00:00:04 1970 +0000
933 933 | | | | summary: (4) merge two known; one immediate left, one immediate right
934 934 | | | |
935 935 | o | | changeset: 3:27eef8ed80b4
936 936 |/ / / user: test
937 937 | | | date: Thu Jan 01 00:00:03 1970 +0000
938 938 | | | summary: (3) collapse
939 939 | | |
940 940 o | | changeset: 2:3d9a33b8d1e1
941 941 |/ / user: test
942 942 | | date: Thu Jan 01 00:00:02 1970 +0000
943 943 | | summary: (2) collapse
944 944 | |
945 945 o | changeset: 1:6db2ef61d156
946 946 |/ user: test
947 947 | date: Thu Jan 01 00:00:01 1970 +0000
948 948 | summary: (1) collapse
949 949 |
950 950 o changeset: 0:e6eb3150255d
951 951 user: test
952 952 date: Thu Jan 01 00:00:00 1970 +0000
953 953 summary: (0) root
954 954
955 955
956 956
957 957 File glog per revset (only merges):
958 958
959 959 $ hg log -G -r 'file("a")' -m
960 960 o changeset: 32:d06dffa21a31
961 961 |\ parent: 27:886ed638191b
962 962 | : parent: 31:621d83e11f67
963 963 | : user: test
964 964 | : date: Thu Jan 01 00:00:32 1970 +0000
965 965 | : summary: (32) expand
966 966 | :
967 967 o : changeset: 31:621d83e11f67
968 968 |\: parent: 21:d42a756af44d
969 969 | : parent: 30:6e11cd4b648f
970 970 | : user: test
971 971 | : date: Thu Jan 01 00:00:31 1970 +0000
972 972 | : summary: (31) expand
973 973 | :
974 974 o : changeset: 30:6e11cd4b648f
975 975 |\ \ parent: 28:44ecd0b9ae99
976 976 | ~ : parent: 29:cd9bb2be7593
977 977 | : user: test
978 978 | : date: Thu Jan 01 00:00:30 1970 +0000
979 979 | : summary: (30) expand
980 980 | /
981 981 o : changeset: 28:44ecd0b9ae99
982 982 |\ \ parent: 1:6db2ef61d156
983 983 | ~ : parent: 26:7f25b6c2f0b9
984 984 | : user: test
985 985 | : date: Thu Jan 01 00:00:28 1970 +0000
986 986 | : summary: (28) merge zero known
987 987 | /
988 988 o : changeset: 26:7f25b6c2f0b9
989 989 |\ \ parent: 18:1aa84d96232a
990 990 | | : parent: 25:91da8ed57247
991 991 | | : user: test
992 992 | | : date: Thu Jan 01 00:00:26 1970 +0000
993 993 | | : summary: (26) merge one known; far right
994 994 | | :
995 995 | o : changeset: 25:91da8ed57247
996 996 | |\: parent: 21:d42a756af44d
997 997 | | : parent: 24:a9c19a3d96b7
998 998 | | : user: test
999 999 | | : date: Thu Jan 01 00:00:25 1970 +0000
1000 1000 | | : summary: (25) merge one known; far left
1001 1001 | | :
1002 1002 | o : changeset: 24:a9c19a3d96b7
1003 1003 | |\ \ parent: 0:e6eb3150255d
1004 1004 | | ~ : parent: 23:a01cddf0766d
1005 1005 | | : user: test
1006 1006 | | : date: Thu Jan 01 00:00:24 1970 +0000
1007 1007 | | : summary: (24) merge one known; immediate right
1008 1008 | | /
1009 1009 | o : changeset: 23:a01cddf0766d
1010 1010 | |\ \ parent: 1:6db2ef61d156
1011 1011 | | ~ : parent: 22:e0d9cccacb5d
1012 1012 | | : user: test
1013 1013 | | : date: Thu Jan 01 00:00:23 1970 +0000
1014 1014 | | : summary: (23) merge one known; immediate left
1015 1015 | | /
1016 1016 | o : changeset: 22:e0d9cccacb5d
1017 1017 |/:/ parent: 18:1aa84d96232a
1018 1018 | : parent: 21:d42a756af44d
1019 1019 | : user: test
1020 1020 | : date: Thu Jan 01 00:00:22 1970 +0000
1021 1021 | : summary: (22) merge two known; one far left, one far right
1022 1022 | :
1023 1023 | o changeset: 21:d42a756af44d
1024 1024 | |\ parent: 19:31ddc2c1573b
1025 1025 | | | parent: 20:d30ed6450e32
1026 1026 | | | user: test
1027 1027 | | | date: Thu Jan 01 00:00:21 1970 +0000
1028 1028 | | | summary: (21) expand
1029 1029 | | |
1030 1030 +---o changeset: 20:d30ed6450e32
1031 1031 | | | parent: 0:e6eb3150255d
1032 1032 | | ~ parent: 18:1aa84d96232a
1033 1033 | | user: test
1034 1034 | | date: Thu Jan 01 00:00:20 1970 +0000
1035 1035 | | summary: (20) merge two known; two far right
1036 1036 | |
1037 1037 | o changeset: 19:31ddc2c1573b
1038 1038 | |\ parent: 15:1dda3f72782d
1039 1039 | | | parent: 17:44765d7c06e0
1040 1040 | | | user: test
1041 1041 | | | date: Thu Jan 01 00:00:19 1970 +0000
1042 1042 | | | summary: (19) expand
1043 1043 | | |
1044 1044 o | | changeset: 18:1aa84d96232a
1045 1045 |\| | parent: 1:6db2ef61d156
1046 1046 ~ | | parent: 15:1dda3f72782d
1047 1047 | | user: test
1048 1048 | | date: Thu Jan 01 00:00:18 1970 +0000
1049 1049 | | summary: (18) merge two known; two far left
1050 1050 / /
1051 1051 | o changeset: 17:44765d7c06e0
1052 1052 | |\ parent: 12:86b91144a6e9
1053 1053 | | | parent: 16:3677d192927d
1054 1054 | | | user: test
1055 1055 | | | date: Thu Jan 01 00:00:17 1970 +0000
1056 1056 | | | summary: (17) expand
1057 1057 | | |
1058 1058 | | o changeset: 16:3677d192927d
1059 1059 | | |\ parent: 0:e6eb3150255d
1060 1060 | | ~ ~ parent: 1:6db2ef61d156
1061 1061 | | user: test
1062 1062 | | date: Thu Jan 01 00:00:16 1970 +0000
1063 1063 | | summary: (16) merge two known; one immediate right, one near right
1064 1064 | |
1065 1065 o | changeset: 15:1dda3f72782d
1066 1066 |\ \ parent: 13:22d8966a97e3
1067 1067 | | | parent: 14:8eac370358ef
1068 1068 | | | user: test
1069 1069 | | | date: Thu Jan 01 00:00:15 1970 +0000
1070 1070 | | | summary: (15) expand
1071 1071 | | |
1072 1072 | o | changeset: 14:8eac370358ef
1073 1073 | |\| parent: 0:e6eb3150255d
1074 1074 | ~ | parent: 12:86b91144a6e9
1075 1075 | | user: test
1076 1076 | | date: Thu Jan 01 00:00:14 1970 +0000
1077 1077 | | summary: (14) merge two known; one immediate right, one far right
1078 1078 | /
1079 1079 o | changeset: 13:22d8966a97e3
1080 1080 |\ \ parent: 9:7010c0af0a35
1081 1081 | | | parent: 11:832d76e6bdf2
1082 1082 | | | user: test
1083 1083 | | | date: Thu Jan 01 00:00:13 1970 +0000
1084 1084 | | | summary: (13) expand
1085 1085 | | |
1086 1086 +---o changeset: 12:86b91144a6e9
1087 1087 | | | parent: 1:6db2ef61d156
1088 1088 | | ~ parent: 9:7010c0af0a35
1089 1089 | | user: test
1090 1090 | | date: Thu Jan 01 00:00:12 1970 +0000
1091 1091 | | summary: (12) merge two known; one immediate right, one far left
1092 1092 | |
1093 1093 | o changeset: 11:832d76e6bdf2
1094 1094 | |\ parent: 6:b105a072e251
1095 1095 | | | parent: 10:74c64d036d72
1096 1096 | | | user: test
1097 1097 | | | date: Thu Jan 01 00:00:11 1970 +0000
1098 1098 | | | summary: (11) expand
1099 1099 | | |
1100 1100 | | o changeset: 10:74c64d036d72
1101 1101 | |/| parent: 0:e6eb3150255d
1102 1102 | | ~ parent: 6:b105a072e251
1103 1103 | | user: test
1104 1104 | | date: Thu Jan 01 00:00:10 1970 +0000
1105 1105 | | summary: (10) merge two known; one immediate left, one near right
1106 1106 | |
1107 1107 o | changeset: 9:7010c0af0a35
1108 1108 |\ \ parent: 7:b632bb1b1224
1109 1109 | | | parent: 8:7a0b11f71937
1110 1110 | | | user: test
1111 1111 | | | date: Thu Jan 01 00:00:09 1970 +0000
1112 1112 | | | summary: (9) expand
1113 1113 | | |
1114 1114 | o | changeset: 8:7a0b11f71937
1115 1115 |/| | parent: 0:e6eb3150255d
1116 1116 | ~ | parent: 7:b632bb1b1224
1117 1117 | | user: test
1118 1118 | | date: Thu Jan 01 00:00:08 1970 +0000
1119 1119 | | summary: (8) merge two known; one immediate left, one far right
1120 1120 | /
1121 1121 o | changeset: 7:b632bb1b1224
1122 1122 |\ \ parent: 2:3d9a33b8d1e1
1123 1123 | ~ | parent: 5:4409d547b708
1124 1124 | | user: test
1125 1125 | | date: Thu Jan 01 00:00:07 1970 +0000
1126 1126 | | summary: (7) expand
1127 1127 | /
1128 1128 | o changeset: 6:b105a072e251
1129 1129 |/| parent: 2:3d9a33b8d1e1
1130 1130 | ~ parent: 5:4409d547b708
1131 1131 | user: test
1132 1132 | date: Thu Jan 01 00:00:06 1970 +0000
1133 1133 | summary: (6) merge two known; one immediate left, one far left
1134 1134 |
1135 1135 o changeset: 5:4409d547b708
1136 1136 |\ parent: 3:27eef8ed80b4
1137 1137 | ~ parent: 4:26a8bac39d9f
1138 1138 | user: test
1139 1139 | date: Thu Jan 01 00:00:05 1970 +0000
1140 1140 | summary: (5) expand
1141 1141 |
1142 1142 o changeset: 4:26a8bac39d9f
1143 1143 |\ parent: 1:6db2ef61d156
1144 1144 ~ ~ parent: 3:27eef8ed80b4
1145 1145 user: test
1146 1146 date: Thu Jan 01 00:00:04 1970 +0000
1147 1147 summary: (4) merge two known; one immediate left, one immediate right
1148 1148
1149 1149
1150 1150
1151 1151 Empty revision range - display nothing:
1152 1152 $ hg log -G -r 1..0
1153 1153
1154 1154 $ cd ..
1155 1155
1156 1156 #if no-outer-repo
1157 1157
1158 1158 From outer space:
1159 1159 $ hg log -G -l1 repo
1160 1160 @ changeset: 34:fea3ac5810e0
1161 1161 | tag: tip
1162 1162 ~ parent: 32:d06dffa21a31
1163 1163 user: test
1164 1164 date: Thu Jan 01 00:00:34 1970 +0000
1165 1165 summary: (34) head
1166 1166
1167 1167 $ hg log -G -l1 repo/a
1168 1168 @ changeset: 34:fea3ac5810e0
1169 1169 | tag: tip
1170 1170 ~ parent: 32:d06dffa21a31
1171 1171 user: test
1172 1172 date: Thu Jan 01 00:00:34 1970 +0000
1173 1173 summary: (34) head
1174 1174
1175 1175 $ hg log -G -l1 repo/missing
1176 1176
1177 1177 #endif
1178 1178
1179 1179 File log with revs != cset revs:
1180 1180 $ hg init flog
1181 1181 $ cd flog
1182 1182 $ echo one >one
1183 1183 $ hg add one
1184 1184 $ hg commit -mone
1185 1185 $ echo two >two
1186 1186 $ hg add two
1187 1187 $ hg commit -mtwo
1188 1188 $ echo more >two
1189 1189 $ hg commit -mmore
1190 1190 $ hg log -G two
1191 1191 @ changeset: 2:12c28321755b
1192 1192 | tag: tip
1193 1193 | user: test
1194 1194 | date: Thu Jan 01 00:00:00 1970 +0000
1195 1195 | summary: more
1196 1196 |
1197 1197 o changeset: 1:5ac72c0599bf
1198 1198 | user: test
1199 1199 ~ date: Thu Jan 01 00:00:00 1970 +0000
1200 1200 summary: two
1201 1201
1202 1202
1203 1203 Issue1896: File log with explicit style
1204 1204 $ hg log -G --style=default one
1205 1205 o changeset: 0:3d578b4a1f53
1206 1206 user: test
1207 1207 date: Thu Jan 01 00:00:00 1970 +0000
1208 1208 summary: one
1209 1209
1210 1210 Issue2395: glog --style header and footer
1211 1211 $ hg log -G --style=xml one
1212 1212 <?xml version="1.0"?>
1213 1213 <log>
1214 1214 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1215 1215 <author email="test">test</author>
1216 1216 <date>1970-01-01T00:00:00+00:00</date>
1217 1217 <msg xml:space="preserve">one</msg>
1218 1218 </logentry>
1219 1219 </log>
1220 1220
1221 1221 $ cd ..
1222 1222
1223 1223 Incoming and outgoing:
1224 1224
1225 1225 $ hg clone -U -r31 repo repo2
1226 1226 adding changesets
1227 1227 adding manifests
1228 1228 adding file changes
1229 1229 added 31 changesets with 31 changes to 1 files
1230 1230 new changesets e6eb3150255d:621d83e11f67
1231 1231 $ cd repo2
1232 1232
1233 1233 $ hg incoming --graph ../repo
1234 1234 comparing with ../repo
1235 1235 searching for changes
1236 1236 o changeset: 34:fea3ac5810e0
1237 1237 | tag: tip
1238 1238 | parent: 32:d06dffa21a31
1239 1239 | user: test
1240 1240 | date: Thu Jan 01 00:00:34 1970 +0000
1241 1241 | summary: (34) head
1242 1242 |
1243 1243 | o changeset: 33:68608f5145f9
1244 1244 | parent: 18:1aa84d96232a
1245 1245 | user: test
1246 1246 | date: Thu Jan 01 00:00:33 1970 +0000
1247 1247 | summary: (33) head
1248 1248 |
1249 1249 o changeset: 32:d06dffa21a31
1250 1250 | parent: 27:886ed638191b
1251 1251 | parent: 31:621d83e11f67
1252 1252 | user: test
1253 1253 | date: Thu Jan 01 00:00:32 1970 +0000
1254 1254 | summary: (32) expand
1255 1255 |
1256 1256 o changeset: 27:886ed638191b
1257 1257 parent: 21:d42a756af44d
1258 1258 user: test
1259 1259 date: Thu Jan 01 00:00:27 1970 +0000
1260 1260 summary: (27) collapse
1261 1261
1262 1262 $ cd ..
1263 1263
1264 1264 $ hg -R repo outgoing --graph repo2
1265 1265 comparing with repo2
1266 1266 searching for changes
1267 1267 @ changeset: 34:fea3ac5810e0
1268 1268 | tag: tip
1269 1269 | parent: 32:d06dffa21a31
1270 1270 | user: test
1271 1271 | date: Thu Jan 01 00:00:34 1970 +0000
1272 1272 | summary: (34) head
1273 1273 |
1274 1274 | o changeset: 33:68608f5145f9
1275 1275 | parent: 18:1aa84d96232a
1276 1276 | user: test
1277 1277 | date: Thu Jan 01 00:00:33 1970 +0000
1278 1278 | summary: (33) head
1279 1279 |
1280 1280 o changeset: 32:d06dffa21a31
1281 1281 | parent: 27:886ed638191b
1282 1282 | parent: 31:621d83e11f67
1283 1283 | user: test
1284 1284 | date: Thu Jan 01 00:00:32 1970 +0000
1285 1285 | summary: (32) expand
1286 1286 |
1287 1287 o changeset: 27:886ed638191b
1288 1288 parent: 21:d42a756af44d
1289 1289 user: test
1290 1290 date: Thu Jan 01 00:00:27 1970 +0000
1291 1291 summary: (27) collapse
1292 1292
1293 1293
1294 1294 File + limit with revs != cset revs:
1295 1295 $ cd repo
1296 1296 $ touch b
1297 1297 $ hg ci -Aqm0
1298 1298 $ hg log -G -l2 a
1299 1299 o changeset: 34:fea3ac5810e0
1300 1300 | parent: 32:d06dffa21a31
1301 1301 ~ user: test
1302 1302 date: Thu Jan 01 00:00:34 1970 +0000
1303 1303 summary: (34) head
1304 1304
1305 1305 o changeset: 33:68608f5145f9
1306 1306 | parent: 18:1aa84d96232a
1307 1307 ~ user: test
1308 1308 date: Thu Jan 01 00:00:33 1970 +0000
1309 1309 summary: (33) head
1310 1310
1311 1311
1312 1312 File + limit + -ra:b, (b - a) < limit:
1313 1313 $ hg log -G -l3000 -r32:tip a
1314 1314 o changeset: 34:fea3ac5810e0
1315 1315 | parent: 32:d06dffa21a31
1316 1316 | user: test
1317 1317 | date: Thu Jan 01 00:00:34 1970 +0000
1318 1318 | summary: (34) head
1319 1319 |
1320 1320 | o changeset: 33:68608f5145f9
1321 1321 | | parent: 18:1aa84d96232a
1322 1322 | ~ user: test
1323 1323 | date: Thu Jan 01 00:00:33 1970 +0000
1324 1324 | summary: (33) head
1325 1325 |
1326 1326 o changeset: 32:d06dffa21a31
1327 1327 |\ parent: 27:886ed638191b
1328 1328 ~ ~ parent: 31:621d83e11f67
1329 1329 user: test
1330 1330 date: Thu Jan 01 00:00:32 1970 +0000
1331 1331 summary: (32) expand
1332 1332
1333 1333
1334 1334 Point out a common and an uncommon unshown parent
1335 1335
1336 1336 $ hg log -G -r 'rev(8) or rev(9)'
1337 1337 o changeset: 9:7010c0af0a35
1338 1338 |\ parent: 7:b632bb1b1224
1339 1339 | ~ parent: 8:7a0b11f71937
1340 1340 | user: test
1341 1341 | date: Thu Jan 01 00:00:09 1970 +0000
1342 1342 | summary: (9) expand
1343 1343 |
1344 1344 o changeset: 8:7a0b11f71937
1345 1345 |\ parent: 0:e6eb3150255d
1346 1346 ~ ~ parent: 7:b632bb1b1224
1347 1347 user: test
1348 1348 date: Thu Jan 01 00:00:08 1970 +0000
1349 1349 summary: (8) merge two known; one immediate left, one far right
1350 1350
1351 1351
1352 1352 File + limit + -ra:b, b < tip:
1353 1353
1354 1354 $ hg log -G -l1 -r32:34 a
1355 1355 o changeset: 34:fea3ac5810e0
1356 1356 | parent: 32:d06dffa21a31
1357 1357 ~ user: test
1358 1358 date: Thu Jan 01 00:00:34 1970 +0000
1359 1359 summary: (34) head
1360 1360
1361 1361
1362 1362 file(File) + limit + -ra:b, b < tip:
1363 1363
1364 1364 $ hg log -G -l1 -r32:34 -r 'file("a")'
1365 1365 o changeset: 34:fea3ac5810e0
1366 1366 | parent: 32:d06dffa21a31
1367 1367 ~ user: test
1368 1368 date: Thu Jan 01 00:00:34 1970 +0000
1369 1369 summary: (34) head
1370 1370
1371 1371
1372 1372 limit(file(File) and a::b), b < tip:
1373 1373
1374 1374 $ hg log -G -r 'limit(file("a") and 32::34, 1)'
1375 1375 o changeset: 32:d06dffa21a31
1376 1376 |\ parent: 27:886ed638191b
1377 1377 ~ ~ parent: 31:621d83e11f67
1378 1378 user: test
1379 1379 date: Thu Jan 01 00:00:32 1970 +0000
1380 1380 summary: (32) expand
1381 1381
1382 1382
1383 1383 File + limit + -ra:b, b < tip:
1384 1384
1385 1385 $ hg log -G -r 'limit(file("a") and 34::32, 1)'
1386 1386
1387 1387 File + limit + -ra:b, b < tip, (b - a) < limit:
1388 1388
1389 1389 $ hg log -G -l10 -r33:34 a
1390 1390 o changeset: 34:fea3ac5810e0
1391 1391 | parent: 32:d06dffa21a31
1392 1392 ~ user: test
1393 1393 date: Thu Jan 01 00:00:34 1970 +0000
1394 1394 summary: (34) head
1395 1395
1396 1396 o changeset: 33:68608f5145f9
1397 1397 | parent: 18:1aa84d96232a
1398 1398 ~ user: test
1399 1399 date: Thu Jan 01 00:00:33 1970 +0000
1400 1400 summary: (33) head
1401 1401
1402 1402
1403 1403 Do not crash or produce strange graphs if history is buggy
1404 1404
1405 1405 $ hg branch branch
1406 1406 marked working directory as branch branch
1407 1407 (branches are permanent and global, did you want a bookmark?)
1408 1408 $ commit 36 "buggy merge: identical parents" 35 35
1409 1409 $ hg log -G -l5
1410 1410 @ changeset: 36:08a19a744424
1411 1411 | branch: branch
1412 1412 | tag: tip
1413 1413 | parent: 35:9159c3644c5e
1414 1414 | parent: 35:9159c3644c5e
1415 1415 | user: test
1416 1416 | date: Thu Jan 01 00:00:36 1970 +0000
1417 1417 | summary: (36) buggy merge: identical parents
1418 1418 |
1419 1419 o changeset: 35:9159c3644c5e
1420 1420 | user: test
1421 1421 | date: Thu Jan 01 00:00:00 1970 +0000
1422 1422 | summary: 0
1423 1423 |
1424 1424 o changeset: 34:fea3ac5810e0
1425 1425 | parent: 32:d06dffa21a31
1426 1426 | user: test
1427 1427 | date: Thu Jan 01 00:00:34 1970 +0000
1428 1428 | summary: (34) head
1429 1429 |
1430 1430 | o changeset: 33:68608f5145f9
1431 1431 | | parent: 18:1aa84d96232a
1432 1432 | ~ user: test
1433 1433 | date: Thu Jan 01 00:00:33 1970 +0000
1434 1434 | summary: (33) head
1435 1435 |
1436 1436 o changeset: 32:d06dffa21a31
1437 1437 |\ parent: 27:886ed638191b
1438 1438 ~ ~ parent: 31:621d83e11f67
1439 1439 user: test
1440 1440 date: Thu Jan 01 00:00:32 1970 +0000
1441 1441 summary: (32) expand
1442 1442
1443 1443
1444 1444 Test log -G options
1445 1445
1446 1446 $ testlog() {
1447 1447 > hg log -G --print-revset "$@"
1448 1448 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1449 1449 > | sed 's/.*nodetag/nodetag/' > log.nodes
1450 1450 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1451 1451 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1452 1452 > (cmp log.nodes glog.nodes || diff -u log.nodes glog.nodes) \
1453 1453 > | grep '^[-+@ ]' || :
1454 1454 > }
1455 1455
1456 1456 glog always reorders nodes which explains the difference with log
1457 1457
1458 1458 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1459 1459 ['27', '25', '21', '34', '32', '31']
1460 1460 []
1461 1461 <baseset- [21, 25, 27, 31, 32, 34]>
1462 1462 --- log.nodes * (glob)
1463 1463 +++ glog.nodes * (glob)
1464 1464 @@ -1,6 +1,6 @@
1465 1465 -nodetag 27
1466 1466 -nodetag 25
1467 1467 -nodetag 21
1468 1468 nodetag 34
1469 1469 nodetag 32
1470 1470 nodetag 31
1471 1471 +nodetag 27
1472 1472 +nodetag 25
1473 1473 +nodetag 21
1474 1474 $ testlog -u test -u not-a-user
1475 1475 []
1476 1476 (or
1477 1477 (list
1478 1478 (func
1479 1479 (symbol 'user')
1480 1480 (string 'test'))
1481 1481 (func
1482 1482 (symbol 'user')
1483 1483 (string 'not-a-user'))))
1484 1484 <filteredset
1485 1485 <spanset- 0:37>,
1486 1486 <addset
1487 1487 <filteredset
1488 1488 <fullreposet+ 0:37>,
1489 1489 <user 'test'>>,
1490 1490 <filteredset
1491 1491 <fullreposet+ 0:37>,
1492 1492 <user 'not-a-user'>>>>
1493 1493 $ testlog -b not-a-branch
1494 1494 abort: unknown revision 'not-a-branch'!
1495 1495 abort: unknown revision 'not-a-branch'!
1496 1496 abort: unknown revision 'not-a-branch'!
1497 1497 $ testlog -b 35 -b 36 --only-branch branch
1498 1498 []
1499 1499 (or
1500 1500 (list
1501 1501 (func
1502 1502 (symbol 'branch')
1503 1503 (string 'default'))
1504 1504 (or
1505 1505 (list
1506 1506 (func
1507 1507 (symbol 'branch')
1508 1508 (string 'branch'))
1509 1509 (func
1510 1510 (symbol 'branch')
1511 1511 (string 'branch'))))))
1512 1512 <filteredset
1513 1513 <spanset- 0:37>,
1514 1514 <addset
1515 1515 <filteredset
1516 1516 <fullreposet+ 0:37>,
1517 1517 <branch 'default'>>,
1518 1518 <addset
1519 1519 <filteredset
1520 1520 <fullreposet+ 0:37>,
1521 1521 <branch 'branch'>>,
1522 1522 <filteredset
1523 1523 <fullreposet+ 0:37>,
1524 1524 <branch 'branch'>>>>>
1525 1525 $ testlog -k expand -k merge
1526 1526 []
1527 1527 (or
1528 1528 (list
1529 1529 (func
1530 1530 (symbol 'keyword')
1531 1531 (string 'expand'))
1532 1532 (func
1533 1533 (symbol 'keyword')
1534 1534 (string 'merge'))))
1535 1535 <filteredset
1536 1536 <spanset- 0:37>,
1537 1537 <addset
1538 1538 <filteredset
1539 1539 <fullreposet+ 0:37>,
1540 1540 <keyword 'expand'>>,
1541 1541 <filteredset
1542 1542 <fullreposet+ 0:37>,
1543 1543 <keyword 'merge'>>>>
1544 1544 $ testlog --only-merges
1545 1545 []
1546 1546 (func
1547 1547 (symbol 'merge')
1548 1548 None)
1549 1549 <filteredset
1550 1550 <spanset- 0:37>,
1551 1551 <merge>>
1552 1552 $ testlog --no-merges
1553 1553 []
1554 1554 (not
1555 1555 (func
1556 1556 (symbol 'merge')
1557 1557 None))
1558 1558 <filteredset
1559 1559 <spanset- 0:37>,
1560 1560 <not
1561 1561 <filteredset
1562 1562 <spanset- 0:37>,
1563 1563 <merge>>>>
1564 1564 $ testlog --date '2 0 to 4 0'
1565 1565 []
1566 1566 (func
1567 1567 (symbol 'date')
1568 1568 (string '2 0 to 4 0'))
1569 1569 <filteredset
1570 1570 <spanset- 0:37>,
1571 1571 <date '2 0 to 4 0'>>
1572 1572 $ hg log -G -d 'brace ) in a date'
1573 1573 hg: parse error: invalid date: 'brace ) in a date'
1574 1574 [255]
1575 1575 $ testlog --prune 31 --prune 32
1576 1576 []
1577 1577 (not
1578 1578 (or
1579 1579 (list
1580 1580 (func
1581 1581 (symbol 'ancestors')
1582 1582 (string '31'))
1583 1583 (func
1584 1584 (symbol 'ancestors')
1585 1585 (string '32')))))
1586 1586 <filteredset
1587 1587 <spanset- 0:37>,
1588 1588 <not
1589 1589 <addset
1590 1590 <filteredset
1591 1591 <spanset- 0:37>,
1592 1592 <generatorsetdesc+>>,
1593 1593 <filteredset
1594 1594 <spanset- 0:37>,
1595 1595 <generatorsetdesc+>>>>>
1596 1596
1597 1597 Dedicated repo for --follow and paths filtering. The g is crafted to
1598 1598 have 2 filelog topological heads in a linear changeset graph.
1599 1599
1600 1600 $ cd ..
1601 1601 $ hg init follow
1602 1602 $ cd follow
1603 1603 $ testlog --follow
1604 1604 []
1605 1605 []
1606 1606 <baseset []>
1607 1607 $ testlog -rnull
1608 1608 ['null']
1609 1609 []
1610 1610 <baseset [-1]>
1611 1611 $ echo a > a
1612 1612 $ echo aa > aa
1613 1613 $ echo f > f
1614 1614 $ hg ci -Am "add a" a aa f
1615 1615 $ hg cp a b
1616 1616 $ hg cp f g
1617 1617 $ hg ci -m "copy a b"
1618 1618 $ mkdir dir
1619 1619 $ hg mv b dir
1620 1620 $ echo g >> g
1621 1621 $ echo f >> f
1622 1622 $ hg ci -m "mv b dir/b"
1623 1623 $ hg mv a b
1624 1624 $ hg cp -f f g
1625 1625 $ echo a > d
1626 1626 $ hg add d
1627 1627 $ hg ci -m "mv a b; add d"
1628 1628 $ hg mv dir/b e
1629 1629 $ hg ci -m "mv dir/b e"
1630 1630 $ hg log -G --template '({rev}) {desc|firstline}\n'
1631 1631 @ (4) mv dir/b e
1632 1632 |
1633 1633 o (3) mv a b; add d
1634 1634 |
1635 1635 o (2) mv b dir/b
1636 1636 |
1637 1637 o (1) copy a b
1638 1638 |
1639 1639 o (0) add a
1640 1640
1641 1641
1642 1642 $ testlog a
1643 1643 []
1644 1644 (func
1645 1645 (symbol 'filelog')
1646 1646 (string 'a'))
1647 1647 <filteredset
1648 1648 <spanset- 0:5>, set([0])>
1649 1649 $ testlog a b
1650 1650 []
1651 1651 (or
1652 1652 (list
1653 1653 (func
1654 1654 (symbol 'filelog')
1655 1655 (string 'a'))
1656 1656 (func
1657 1657 (symbol 'filelog')
1658 1658 (string 'b'))))
1659 1659 <filteredset
1660 1660 <spanset- 0:5>,
1661 1661 <addset
1662 1662 <baseset+ [0]>,
1663 1663 <baseset+ [1]>>>
1664 1664
1665 1665 Test falling back to slow path for non-existing files
1666 1666
1667 1667 $ testlog a c
1668 1668 []
1669 1669 (func
1670 1670 (symbol '_matchfiles')
1671 1671 (list
1672 1672 (string 'r:')
1673 1673 (string 'd:relpath')
1674 1674 (string 'p:a')
1675 1675 (string 'p:c')))
1676 1676 <filteredset
1677 1677 <spanset- 0:5>,
1678 <matchfiles patterns=['a', 'c'], include=[] exclude=[], default='relpath', rev=None>>
1678 <matchfiles patterns=['a', 'c'], include=[] exclude=[], default='relpath', rev=2147483647>>
1679 1679
1680 1680 Test multiple --include/--exclude/paths
1681 1681
1682 1682 $ testlog --include a --include e --exclude b --exclude e a e
1683 1683 []
1684 1684 (func
1685 1685 (symbol '_matchfiles')
1686 1686 (list
1687 1687 (string 'r:')
1688 1688 (string 'd:relpath')
1689 1689 (string 'p:a')
1690 1690 (string 'p:e')
1691 1691 (string 'i:a')
1692 1692 (string 'i:e')
1693 1693 (string 'x:b')
1694 1694 (string 'x:e')))
1695 1695 <filteredset
1696 1696 <spanset- 0:5>,
1697 <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=None>>
1697 <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=2147483647>>
1698 1698
1699 1699 Test glob expansion of pats
1700 1700
1701 1701 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1702 1702 > print(mercurial.util.expandglobs and 'true' or 'false')"`
1703 1703 $ if [ $expandglobs = "true" ]; then
1704 1704 > testlog 'a*';
1705 1705 > else
1706 1706 > testlog a*;
1707 1707 > fi;
1708 1708 []
1709 1709 (func
1710 1710 (symbol 'filelog')
1711 1711 (string 'aa'))
1712 1712 <filteredset
1713 1713 <spanset- 0:5>, set([0])>
1714 1714
1715 1715 Test --follow on a non-existent directory
1716 1716
1717 1717 $ testlog -f dir
1718 1718 abort: cannot follow file not in parent revision: "dir"
1719 1719 abort: cannot follow file not in parent revision: "dir"
1720 1720 abort: cannot follow file not in parent revision: "dir"
1721 1721
1722 1722 Test --follow on a directory
1723 1723
1724 1724 $ hg up -q '.^'
1725 1725 $ testlog -f dir
1726 1726 []
1727 1727 (func
1728 1728 (symbol '_matchfiles')
1729 1729 (list
1730 1730 (string 'r:')
1731 1731 (string 'd:relpath')
1732 1732 (string 'p:dir')))
1733 1733 <filteredset
1734 1734 <generatorsetdesc->,
1735 <matchfiles patterns=['dir'], include=[] exclude=[], default='relpath', rev=None>>
1735 <matchfiles patterns=['dir'], include=[] exclude=[], default='relpath', rev=2147483647>>
1736 1736 $ hg up -q tip
1737 1737
1738 1738 Test --follow on file not in parent revision
1739 1739
1740 1740 $ testlog -f a
1741 1741 abort: cannot follow file not in parent revision: "a"
1742 1742 abort: cannot follow file not in parent revision: "a"
1743 1743 abort: cannot follow file not in parent revision: "a"
1744 1744
1745 1745 Test --follow and patterns
1746 1746
1747 1747 $ testlog -f 'glob:*'
1748 1748 []
1749 1749 (func
1750 1750 (symbol '_matchfiles')
1751 1751 (list
1752 1752 (string 'r:')
1753 1753 (string 'd:relpath')
1754 1754 (string 'p:glob:*')))
1755 1755 <filteredset
1756 1756 <generatorsetdesc->,
1757 <matchfiles patterns=['glob:*'], include=[] exclude=[], default='relpath', rev=None>>
1757 <matchfiles patterns=['glob:*'], include=[] exclude=[], default='relpath', rev=2147483647>>
1758 1758
1759 1759 Test --follow on a single rename
1760 1760
1761 1761 $ hg up -q 2
1762 1762 $ testlog -f a
1763 1763 []
1764 1764 []
1765 1765 <generatorsetdesc->
1766 1766
1767 1767 Test --follow and multiple renames
1768 1768
1769 1769 $ hg up -q tip
1770 1770 $ testlog -f e
1771 1771 []
1772 1772 []
1773 1773 <generatorsetdesc->
1774 1774
1775 1775 Test --follow and multiple filelog heads
1776 1776
1777 1777 $ hg up -q 2
1778 1778 $ testlog -f g
1779 1779 []
1780 1780 []
1781 1781 <generatorsetdesc->
1782 1782 $ cat log.nodes
1783 1783 nodetag 2
1784 1784 nodetag 1
1785 1785 nodetag 0
1786 1786 $ hg up -q tip
1787 1787 $ testlog -f g
1788 1788 []
1789 1789 []
1790 1790 <generatorsetdesc->
1791 1791 $ cat log.nodes
1792 1792 nodetag 3
1793 1793 nodetag 2
1794 1794 nodetag 0
1795 1795
1796 1796 Test --follow and multiple files
1797 1797
1798 1798 $ testlog -f g e
1799 1799 []
1800 1800 []
1801 1801 <generatorsetdesc->
1802 1802 $ cat log.nodes
1803 1803 nodetag 4
1804 1804 nodetag 3
1805 1805 nodetag 2
1806 1806 nodetag 1
1807 1807 nodetag 0
1808 1808
1809 1809 Test --follow null parent
1810 1810
1811 1811 $ hg up -q null
1812 1812 $ testlog -f
1813 1813 []
1814 1814 []
1815 1815 <baseset []>
1816 1816
1817 1817 Test --follow-first
1818 1818
1819 1819 $ hg up -q 3
1820 1820 $ echo ee > e
1821 1821 $ hg ci -Am "add another e" e
1822 1822 created new head
1823 1823 $ hg merge --tool internal:other 4
1824 1824 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1825 1825 (branch merge, don't forget to commit)
1826 1826 $ echo merge > e
1827 1827 $ hg ci -m "merge 5 and 4"
1828 1828 $ testlog --follow-first
1829 1829 []
1830 1830 []
1831 1831 <generatorsetdesc->
1832 1832
1833 1833 Cannot compare with log --follow-first FILE as it never worked
1834 1834
1835 1835 $ hg log -G --print-revset --follow-first e
1836 1836 []
1837 1837 []
1838 1838 <generatorsetdesc->
1839 1839 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1840 1840 @ 6 merge 5 and 4
1841 1841 |\
1842 1842 | ~
1843 1843 o 5 add another e
1844 1844 |
1845 1845 ~
1846 1846
1847 1847 Test --copies
1848 1848
1849 1849 $ hg log -G --copies --template "{rev} {desc|firstline} \
1850 1850 > copies: {file_copies_switch}\n"
1851 1851 @ 6 merge 5 and 4 copies:
1852 1852 |\
1853 1853 | o 5 add another e copies:
1854 1854 | |
1855 1855 o | 4 mv dir/b e copies: e (dir/b)
1856 1856 |/
1857 1857 o 3 mv a b; add d copies: b (a)g (f)
1858 1858 |
1859 1859 o 2 mv b dir/b copies: dir/b (b)
1860 1860 |
1861 1861 o 1 copy a b copies: b (a)g (f)
1862 1862 |
1863 1863 o 0 add a copies:
1864 1864
1865 1865 Test "set:..." and parent revision
1866 1866
1867 1867 $ hg up -q 4
1868 1868 $ testlog "set:copied()"
1869 1869 []
1870 1870 (func
1871 1871 (symbol '_matchfiles')
1872 1872 (list
1873 1873 (string 'r:')
1874 1874 (string 'd:relpath')
1875 1875 (string 'p:set:copied()')))
1876 1876 <filteredset
1877 1877 <spanset- 0:7>,
1878 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=None>>
1878 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=2147483647>>
1879 1879 $ testlog --include "set:copied()"
1880 1880 []
1881 1881 (func
1882 1882 (symbol '_matchfiles')
1883 1883 (list
1884 1884 (string 'r:')
1885 1885 (string 'd:relpath')
1886 1886 (string 'i:set:copied()')))
1887 1887 <filteredset
1888 1888 <spanset- 0:7>,
1889 <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=None>>
1889 <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=2147483647>>
1890 1890 $ testlog -r "sort(file('set:copied()'), -rev)"
1891 1891 ["sort(file('set:copied()'), -rev)"]
1892 1892 []
1893 <baseset []>
1893 <filteredset
1894 <fullreposet- 0:7>,
1895 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='glob', rev=None>>
1894 1896
1895 1897 Test --removed
1896 1898
1897 1899 $ testlog --removed
1898 1900 []
1899 1901 []
1900 1902 <spanset- 0:7>
1901 1903 $ testlog --removed a
1902 1904 []
1903 1905 (func
1904 1906 (symbol '_matchfiles')
1905 1907 (list
1906 1908 (string 'r:')
1907 1909 (string 'd:relpath')
1908 1910 (string 'p:a')))
1909 1911 <filteredset
1910 1912 <spanset- 0:7>,
1911 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=None>>
1913 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1912 1914 $ testlog --removed --follow a
1913 1915 []
1914 1916 (func
1915 1917 (symbol '_matchfiles')
1916 1918 (list
1917 1919 (string 'r:')
1918 1920 (string 'd:relpath')
1919 1921 (string 'p:a')))
1920 1922 <filteredset
1921 1923 <generatorsetdesc->,
1922 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=None>>
1924 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1923 1925
1924 1926 Test --patch and --stat with --follow and --follow-first
1925 1927
1926 1928 $ hg up -q 3
1927 1929 $ hg log -G --git --patch b
1928 1930 o changeset: 1:216d4c92cf98
1929 1931 | user: test
1930 1932 ~ date: Thu Jan 01 00:00:00 1970 +0000
1931 1933 summary: copy a b
1932 1934
1933 1935 diff --git a/a b/b
1934 1936 copy from a
1935 1937 copy to b
1936 1938
1937 1939
1938 1940 $ hg log -G --git --stat b
1939 1941 o changeset: 1:216d4c92cf98
1940 1942 | user: test
1941 1943 ~ date: Thu Jan 01 00:00:00 1970 +0000
1942 1944 summary: copy a b
1943 1945
1944 1946 b | 0
1945 1947 1 files changed, 0 insertions(+), 0 deletions(-)
1946 1948
1947 1949
1948 1950 $ hg log -G --git --patch --follow b
1949 1951 o changeset: 1:216d4c92cf98
1950 1952 | user: test
1951 1953 | date: Thu Jan 01 00:00:00 1970 +0000
1952 1954 | summary: copy a b
1953 1955 |
1954 1956 | diff --git a/a b/b
1955 1957 | copy from a
1956 1958 | copy to b
1957 1959 |
1958 1960 o changeset: 0:f8035bb17114
1959 1961 user: test
1960 1962 date: Thu Jan 01 00:00:00 1970 +0000
1961 1963 summary: add a
1962 1964
1963 1965 diff --git a/a b/a
1964 1966 new file mode 100644
1965 1967 --- /dev/null
1966 1968 +++ b/a
1967 1969 @@ -0,0 +1,1 @@
1968 1970 +a
1969 1971
1970 1972
1971 1973 $ hg log -G --git --stat --follow b
1972 1974 o changeset: 1:216d4c92cf98
1973 1975 | user: test
1974 1976 | date: Thu Jan 01 00:00:00 1970 +0000
1975 1977 | summary: copy a b
1976 1978 |
1977 1979 | b | 0
1978 1980 | 1 files changed, 0 insertions(+), 0 deletions(-)
1979 1981 |
1980 1982 o changeset: 0:f8035bb17114
1981 1983 user: test
1982 1984 date: Thu Jan 01 00:00:00 1970 +0000
1983 1985 summary: add a
1984 1986
1985 1987 a | 1 +
1986 1988 1 files changed, 1 insertions(+), 0 deletions(-)
1987 1989
1988 1990
1989 1991 $ hg up -q 6
1990 1992 $ hg log -G --git --patch --follow-first e
1991 1993 @ changeset: 6:fc281d8ff18d
1992 1994 |\ tag: tip
1993 1995 | ~ parent: 5:99b31f1c2782
1994 1996 | parent: 4:17d952250a9d
1995 1997 | user: test
1996 1998 | date: Thu Jan 01 00:00:00 1970 +0000
1997 1999 | summary: merge 5 and 4
1998 2000 |
1999 2001 | diff --git a/e b/e
2000 2002 | --- a/e
2001 2003 | +++ b/e
2002 2004 | @@ -1,1 +1,1 @@
2003 2005 | -ee
2004 2006 | +merge
2005 2007 |
2006 2008 o changeset: 5:99b31f1c2782
2007 2009 | parent: 3:5918b8d165d1
2008 2010 ~ user: test
2009 2011 date: Thu Jan 01 00:00:00 1970 +0000
2010 2012 summary: add another e
2011 2013
2012 2014 diff --git a/e b/e
2013 2015 new file mode 100644
2014 2016 --- /dev/null
2015 2017 +++ b/e
2016 2018 @@ -0,0 +1,1 @@
2017 2019 +ee
2018 2020
2019 2021
2020 2022 Test old-style --rev
2021 2023
2022 2024 $ hg tag 'foo-bar'
2023 2025 $ testlog -r 'foo-bar'
2024 2026 ['foo-bar']
2025 2027 []
2026 2028 <baseset [6]>
2027 2029
2028 2030 Test --follow and forward --rev
2029 2031
2030 2032 $ hg up -q 6
2031 2033 $ echo g > g
2032 2034 $ hg ci -Am 'add g' g
2033 2035 created new head
2034 2036 $ hg up -q 2
2035 2037 $ hg log -G --template "{rev} {desc|firstline}\n"
2036 2038 o 8 add g
2037 2039 |
2038 2040 | o 7 Added tag foo-bar for changeset fc281d8ff18d
2039 2041 |/
2040 2042 o 6 merge 5 and 4
2041 2043 |\
2042 2044 | o 5 add another e
2043 2045 | |
2044 2046 o | 4 mv dir/b e
2045 2047 |/
2046 2048 o 3 mv a b; add d
2047 2049 |
2048 2050 @ 2 mv b dir/b
2049 2051 |
2050 2052 o 1 copy a b
2051 2053 |
2052 2054 o 0 add a
2053 2055
2054 2056 $ hg archive -r 7 archive
2055 2057 $ grep changessincelatesttag archive/.hg_archival.txt
2056 2058 changessincelatesttag: 1
2057 2059 $ rm -r archive
2058 2060
2059 2061 changessincelatesttag with no prior tag
2060 2062 $ hg archive -r 4 archive
2061 2063 $ grep changessincelatesttag archive/.hg_archival.txt
2062 2064 changessincelatesttag: 5
2063 2065
2064 2066 $ hg export 'all()'
2065 2067 # HG changeset patch
2066 2068 # User test
2067 2069 # Date 0 0
2068 2070 # Thu Jan 01 00:00:00 1970 +0000
2069 2071 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2070 2072 # Parent 0000000000000000000000000000000000000000
2071 2073 add a
2072 2074
2073 2075 diff -r 000000000000 -r f8035bb17114 a
2074 2076 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2075 2077 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2076 2078 @@ -0,0 +1,1 @@
2077 2079 +a
2078 2080 diff -r 000000000000 -r f8035bb17114 aa
2079 2081 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2080 2082 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2081 2083 @@ -0,0 +1,1 @@
2082 2084 +aa
2083 2085 diff -r 000000000000 -r f8035bb17114 f
2084 2086 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2085 2087 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2086 2088 @@ -0,0 +1,1 @@
2087 2089 +f
2088 2090 # HG changeset patch
2089 2091 # User test
2090 2092 # Date 0 0
2091 2093 # Thu Jan 01 00:00:00 1970 +0000
2092 2094 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2093 2095 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2094 2096 copy a b
2095 2097
2096 2098 diff -r f8035bb17114 -r 216d4c92cf98 b
2097 2099 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2098 2100 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2099 2101 @@ -0,0 +1,1 @@
2100 2102 +a
2101 2103 diff -r f8035bb17114 -r 216d4c92cf98 g
2102 2104 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2103 2105 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2104 2106 @@ -0,0 +1,1 @@
2105 2107 +f
2106 2108 # HG changeset patch
2107 2109 # User test
2108 2110 # Date 0 0
2109 2111 # Thu Jan 01 00:00:00 1970 +0000
2110 2112 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2111 2113 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2112 2114 mv b dir/b
2113 2115
2114 2116 diff -r 216d4c92cf98 -r bb573313a9e8 b
2115 2117 --- a/b Thu Jan 01 00:00:00 1970 +0000
2116 2118 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2117 2119 @@ -1,1 +0,0 @@
2118 2120 -a
2119 2121 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2120 2122 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2121 2123 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2122 2124 @@ -0,0 +1,1 @@
2123 2125 +a
2124 2126 diff -r 216d4c92cf98 -r bb573313a9e8 f
2125 2127 --- a/f Thu Jan 01 00:00:00 1970 +0000
2126 2128 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2127 2129 @@ -1,1 +1,2 @@
2128 2130 f
2129 2131 +f
2130 2132 diff -r 216d4c92cf98 -r bb573313a9e8 g
2131 2133 --- a/g Thu Jan 01 00:00:00 1970 +0000
2132 2134 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2133 2135 @@ -1,1 +1,2 @@
2134 2136 f
2135 2137 +g
2136 2138 # HG changeset patch
2137 2139 # User test
2138 2140 # Date 0 0
2139 2141 # Thu Jan 01 00:00:00 1970 +0000
2140 2142 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2141 2143 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2142 2144 mv a b; add d
2143 2145
2144 2146 diff -r bb573313a9e8 -r 5918b8d165d1 a
2145 2147 --- a/a Thu Jan 01 00:00:00 1970 +0000
2146 2148 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2147 2149 @@ -1,1 +0,0 @@
2148 2150 -a
2149 2151 diff -r bb573313a9e8 -r 5918b8d165d1 b
2150 2152 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2151 2153 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2152 2154 @@ -0,0 +1,1 @@
2153 2155 +a
2154 2156 diff -r bb573313a9e8 -r 5918b8d165d1 d
2155 2157 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2156 2158 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2157 2159 @@ -0,0 +1,1 @@
2158 2160 +a
2159 2161 diff -r bb573313a9e8 -r 5918b8d165d1 g
2160 2162 --- a/g Thu Jan 01 00:00:00 1970 +0000
2161 2163 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2162 2164 @@ -1,2 +1,2 @@
2163 2165 f
2164 2166 -g
2165 2167 +f
2166 2168 # HG changeset patch
2167 2169 # User test
2168 2170 # Date 0 0
2169 2171 # Thu Jan 01 00:00:00 1970 +0000
2170 2172 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2171 2173 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2172 2174 mv dir/b e
2173 2175
2174 2176 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2175 2177 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2176 2178 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2177 2179 @@ -1,1 +0,0 @@
2178 2180 -a
2179 2181 diff -r 5918b8d165d1 -r 17d952250a9d e
2180 2182 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2181 2183 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2182 2184 @@ -0,0 +1,1 @@
2183 2185 +a
2184 2186 # HG changeset patch
2185 2187 # User test
2186 2188 # Date 0 0
2187 2189 # Thu Jan 01 00:00:00 1970 +0000
2188 2190 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2189 2191 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2190 2192 add another e
2191 2193
2192 2194 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2193 2195 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2194 2196 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2195 2197 @@ -0,0 +1,1 @@
2196 2198 +ee
2197 2199 # HG changeset patch
2198 2200 # User test
2199 2201 # Date 0 0
2200 2202 # Thu Jan 01 00:00:00 1970 +0000
2201 2203 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2202 2204 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2203 2205 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2204 2206 merge 5 and 4
2205 2207
2206 2208 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2207 2209 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2208 2210 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2209 2211 @@ -1,1 +0,0 @@
2210 2212 -a
2211 2213 diff -r 99b31f1c2782 -r fc281d8ff18d e
2212 2214 --- a/e Thu Jan 01 00:00:00 1970 +0000
2213 2215 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2214 2216 @@ -1,1 +1,1 @@
2215 2217 -ee
2216 2218 +merge
2217 2219 # HG changeset patch
2218 2220 # User test
2219 2221 # Date 0 0
2220 2222 # Thu Jan 01 00:00:00 1970 +0000
2221 2223 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2222 2224 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2223 2225 Added tag foo-bar for changeset fc281d8ff18d
2224 2226
2225 2227 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2226 2228 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2227 2229 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2228 2230 @@ -0,0 +1,1 @@
2229 2231 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2230 2232 # HG changeset patch
2231 2233 # User test
2232 2234 # Date 0 0
2233 2235 # Thu Jan 01 00:00:00 1970 +0000
2234 2236 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2235 2237 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2236 2238 add g
2237 2239
2238 2240 diff -r fc281d8ff18d -r 24c2e826ddeb g
2239 2241 --- a/g Thu Jan 01 00:00:00 1970 +0000
2240 2242 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2241 2243 @@ -1,2 +1,1 @@
2242 2244 -f
2243 2245 -f
2244 2246 +g
2245 2247 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2246 2248 ['6', '8', '5', '7', '4']
2247 2249 []
2248 2250 <generatorsetdesc->
2249 2251
2250 2252 Test --follow-first and forward --rev
2251 2253
2252 2254 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2253 2255 ['6', '8', '5', '7', '4']
2254 2256 []
2255 2257 <generatorsetdesc->
2256 2258
2257 2259 Test --follow and backward --rev
2258 2260
2259 2261 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2260 2262 ['6', '5', '7', '8', '4']
2261 2263 []
2262 2264 <generatorsetdesc->
2263 2265
2264 2266 Test --follow-first and backward --rev
2265 2267
2266 2268 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2267 2269 ['6', '5', '7', '8', '4']
2268 2270 []
2269 2271 <generatorsetdesc->
2270 2272
2271 2273 Test --follow with --rev of graphlog extension
2272 2274
2273 2275 $ hg --config extensions.graphlog= glog -qfr1
2274 2276 o 1:216d4c92cf98
2275 2277 |
2276 2278 o 0:f8035bb17114
2277 2279
2278 2280
2279 2281 Test subdir
2280 2282
2281 2283 $ hg up -q 3
2282 2284 $ cd dir
2283 2285 $ testlog .
2284 2286 []
2285 2287 (func
2286 2288 (symbol '_matchfiles')
2287 2289 (list
2288 2290 (string 'r:')
2289 2291 (string 'd:relpath')
2290 2292 (string 'p:.')))
2291 2293 <filteredset
2292 2294 <spanset- 0:9>,
2293 <matchfiles patterns=['.'], include=[] exclude=[], default='relpath', rev=None>>
2295 <matchfiles patterns=['.'], include=[] exclude=[], default='relpath', rev=2147483647>>
2294 2296 $ testlog ../b
2295 2297 []
2296 2298 (func
2297 2299 (symbol 'filelog')
2298 2300 (string '../b'))
2299 2301 <filteredset
2300 2302 <spanset- 0:9>, set([1])>
2301 2303 $ testlog -f ../b
2302 2304 []
2303 2305 []
2304 2306 <generatorsetdesc->
2305 2307 $ cd ..
2306 2308
2307 2309 Test --hidden
2308 2310 (enable obsolete)
2309 2311
2310 2312 $ cat >> $HGRCPATH << EOF
2311 2313 > [experimental]
2312 2314 > evolution.createmarkers=True
2313 2315 > EOF
2314 2316
2315 2317 $ hg debugobsolete `hg id --debug -i -r 8`
2316 2318 obsoleted 1 changesets
2317 2319 $ testlog
2318 2320 []
2319 2321 []
2320 2322 <spanset- 0:9>
2321 2323 $ testlog --hidden
2322 2324 []
2323 2325 []
2324 2326 <spanset- 0:9>
2325 2327 $ hg log -G --template '{rev} {desc}\n'
2326 2328 o 7 Added tag foo-bar for changeset fc281d8ff18d
2327 2329 |
2328 2330 o 6 merge 5 and 4
2329 2331 |\
2330 2332 | o 5 add another e
2331 2333 | |
2332 2334 o | 4 mv dir/b e
2333 2335 |/
2334 2336 @ 3 mv a b; add d
2335 2337 |
2336 2338 o 2 mv b dir/b
2337 2339 |
2338 2340 o 1 copy a b
2339 2341 |
2340 2342 o 0 add a
2341 2343
2342 2344
2343 2345 A template without trailing newline should do something sane
2344 2346
2345 2347 $ hg log -G -r ::2 --template '{rev} {desc}'
2346 2348 o 2 mv b dir/b
2347 2349 |
2348 2350 o 1 copy a b
2349 2351 |
2350 2352 o 0 add a
2351 2353
2352 2354
2353 2355 Extra newlines must be preserved
2354 2356
2355 2357 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2356 2358 o
2357 2359 | 2 mv b dir/b
2358 2360 |
2359 2361 o
2360 2362 | 1 copy a b
2361 2363 |
2362 2364 o
2363 2365 0 add a
2364 2366
2365 2367
2366 2368 The almost-empty template should do something sane too ...
2367 2369
2368 2370 $ hg log -G -r ::2 --template '\n'
2369 2371 o
2370 2372 |
2371 2373 o
2372 2374 |
2373 2375 o
2374 2376
2375 2377
2376 2378 issue3772
2377 2379
2378 2380 $ hg log -G -r :null
2379 2381 o changeset: 0:f8035bb17114
2380 2382 | user: test
2381 2383 | date: Thu Jan 01 00:00:00 1970 +0000
2382 2384 | summary: add a
2383 2385 |
2384 2386 o changeset: -1:000000000000
2385 2387 user:
2386 2388 date: Thu Jan 01 00:00:00 1970 +0000
2387 2389
2388 2390 $ hg log -G -r null:null
2389 2391 o changeset: -1:000000000000
2390 2392 user:
2391 2393 date: Thu Jan 01 00:00:00 1970 +0000
2392 2394
2393 2395
2394 2396 should not draw line down to null due to the magic of fullreposet
2395 2397
2396 2398 $ hg log -G -r 'all()' | tail -6
2397 2399 |
2398 2400 o changeset: 0:f8035bb17114
2399 2401 user: test
2400 2402 date: Thu Jan 01 00:00:00 1970 +0000
2401 2403 summary: add a
2402 2404
2403 2405
2404 2406 $ hg log -G -r 'branch(default)' | tail -6
2405 2407 |
2406 2408 o changeset: 0:f8035bb17114
2407 2409 user: test
2408 2410 date: Thu Jan 01 00:00:00 1970 +0000
2409 2411 summary: add a
2410 2412
2411 2413
2412 2414 working-directory revision
2413 2415
2414 2416 $ hg log -G -qr '. + wdir()'
2415 2417 o 2147483647:ffffffffffff
2416 2418 |
2417 2419 @ 3:5918b8d165d1
2418 2420 |
2419 2421 ~
2420 2422
2421 2423 node template with changeset_printer:
2422 2424
2423 2425 $ hg log -Gqr 5:7 --config ui.graphnodetemplate='"{rev}"'
2424 2426 7 7:02dbb8e276b8
2425 2427 |
2426 2428 6 6:fc281d8ff18d
2427 2429 |\
2428 2430 | ~
2429 2431 5 5:99b31f1c2782
2430 2432 |
2431 2433 ~
2432 2434
2433 2435 node template with changeset_templater (shared cache variable):
2434 2436
2435 2437 $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \
2436 2438 > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}'
2437 2439 o 7 foo-bar+1
2438 2440 |
2439 2441 # 6 foo-bar+0
2440 2442 |\
2441 2443 | ~
2442 2444 o 5 null+5
2443 2445 |
2444 2446 ~
2445 2447
2446 2448 label() should just work in node template:
2447 2449
2448 2450 $ hg log -Gqr 7 --config extensions.color= --color=debug \
2449 2451 > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}'
2450 2452 [branch.default|7] [log.node|7:02dbb8e276b8]
2451 2453 |
2452 2454 ~
2453 2455
2454 2456 $ cd ..
2455 2457
2456 2458 change graph edge styling
2457 2459
2458 2460 $ cd repo
2459 2461 $ cat << EOF >> $HGRCPATH
2460 2462 > [experimental]
2461 2463 > graphstyle.parent = |
2462 2464 > graphstyle.grandparent = :
2463 2465 > graphstyle.missing =
2464 2466 > EOF
2465 2467 $ hg log -G -r 'file("a")' -m
2466 2468 @ changeset: 36:08a19a744424
2467 2469 : branch: branch
2468 2470 : tag: tip
2469 2471 : parent: 35:9159c3644c5e
2470 2472 : parent: 35:9159c3644c5e
2471 2473 : user: test
2472 2474 : date: Thu Jan 01 00:00:36 1970 +0000
2473 2475 : summary: (36) buggy merge: identical parents
2474 2476 :
2475 2477 o changeset: 32:d06dffa21a31
2476 2478 |\ parent: 27:886ed638191b
2477 2479 | : parent: 31:621d83e11f67
2478 2480 | : user: test
2479 2481 | : date: Thu Jan 01 00:00:32 1970 +0000
2480 2482 | : summary: (32) expand
2481 2483 | :
2482 2484 o : changeset: 31:621d83e11f67
2483 2485 |\: parent: 21:d42a756af44d
2484 2486 | : parent: 30:6e11cd4b648f
2485 2487 | : user: test
2486 2488 | : date: Thu Jan 01 00:00:31 1970 +0000
2487 2489 | : summary: (31) expand
2488 2490 | :
2489 2491 o : changeset: 30:6e11cd4b648f
2490 2492 |\ \ parent: 28:44ecd0b9ae99
2491 2493 | ~ : parent: 29:cd9bb2be7593
2492 2494 | : user: test
2493 2495 | : date: Thu Jan 01 00:00:30 1970 +0000
2494 2496 | : summary: (30) expand
2495 2497 | /
2496 2498 o : changeset: 28:44ecd0b9ae99
2497 2499 |\ \ parent: 1:6db2ef61d156
2498 2500 | ~ : parent: 26:7f25b6c2f0b9
2499 2501 | : user: test
2500 2502 | : date: Thu Jan 01 00:00:28 1970 +0000
2501 2503 | : summary: (28) merge zero known
2502 2504 | /
2503 2505 o : changeset: 26:7f25b6c2f0b9
2504 2506 |\ \ parent: 18:1aa84d96232a
2505 2507 | | : parent: 25:91da8ed57247
2506 2508 | | : user: test
2507 2509 | | : date: Thu Jan 01 00:00:26 1970 +0000
2508 2510 | | : summary: (26) merge one known; far right
2509 2511 | | :
2510 2512 | o : changeset: 25:91da8ed57247
2511 2513 | |\: parent: 21:d42a756af44d
2512 2514 | | : parent: 24:a9c19a3d96b7
2513 2515 | | : user: test
2514 2516 | | : date: Thu Jan 01 00:00:25 1970 +0000
2515 2517 | | : summary: (25) merge one known; far left
2516 2518 | | :
2517 2519 | o : changeset: 24:a9c19a3d96b7
2518 2520 | |\ \ parent: 0:e6eb3150255d
2519 2521 | | ~ : parent: 23:a01cddf0766d
2520 2522 | | : user: test
2521 2523 | | : date: Thu Jan 01 00:00:24 1970 +0000
2522 2524 | | : summary: (24) merge one known; immediate right
2523 2525 | | /
2524 2526 | o : changeset: 23:a01cddf0766d
2525 2527 | |\ \ parent: 1:6db2ef61d156
2526 2528 | | ~ : parent: 22:e0d9cccacb5d
2527 2529 | | : user: test
2528 2530 | | : date: Thu Jan 01 00:00:23 1970 +0000
2529 2531 | | : summary: (23) merge one known; immediate left
2530 2532 | | /
2531 2533 | o : changeset: 22:e0d9cccacb5d
2532 2534 |/:/ parent: 18:1aa84d96232a
2533 2535 | : parent: 21:d42a756af44d
2534 2536 | : user: test
2535 2537 | : date: Thu Jan 01 00:00:22 1970 +0000
2536 2538 | : summary: (22) merge two known; one far left, one far right
2537 2539 | :
2538 2540 | o changeset: 21:d42a756af44d
2539 2541 | |\ parent: 19:31ddc2c1573b
2540 2542 | | | parent: 20:d30ed6450e32
2541 2543 | | | user: test
2542 2544 | | | date: Thu Jan 01 00:00:21 1970 +0000
2543 2545 | | | summary: (21) expand
2544 2546 | | |
2545 2547 +---o changeset: 20:d30ed6450e32
2546 2548 | | | parent: 0:e6eb3150255d
2547 2549 | | ~ parent: 18:1aa84d96232a
2548 2550 | | user: test
2549 2551 | | date: Thu Jan 01 00:00:20 1970 +0000
2550 2552 | | summary: (20) merge two known; two far right
2551 2553 | |
2552 2554 | o changeset: 19:31ddc2c1573b
2553 2555 | |\ parent: 15:1dda3f72782d
2554 2556 | | | parent: 17:44765d7c06e0
2555 2557 | | | user: test
2556 2558 | | | date: Thu Jan 01 00:00:19 1970 +0000
2557 2559 | | | summary: (19) expand
2558 2560 | | |
2559 2561 o | | changeset: 18:1aa84d96232a
2560 2562 |\| | parent: 1:6db2ef61d156
2561 2563 ~ | | parent: 15:1dda3f72782d
2562 2564 | | user: test
2563 2565 | | date: Thu Jan 01 00:00:18 1970 +0000
2564 2566 | | summary: (18) merge two known; two far left
2565 2567 / /
2566 2568 | o changeset: 17:44765d7c06e0
2567 2569 | |\ parent: 12:86b91144a6e9
2568 2570 | | | parent: 16:3677d192927d
2569 2571 | | | user: test
2570 2572 | | | date: Thu Jan 01 00:00:17 1970 +0000
2571 2573 | | | summary: (17) expand
2572 2574 | | |
2573 2575 | | o changeset: 16:3677d192927d
2574 2576 | | |\ parent: 0:e6eb3150255d
2575 2577 | | ~ ~ parent: 1:6db2ef61d156
2576 2578 | | user: test
2577 2579 | | date: Thu Jan 01 00:00:16 1970 +0000
2578 2580 | | summary: (16) merge two known; one immediate right, one near right
2579 2581 | |
2580 2582 o | changeset: 15:1dda3f72782d
2581 2583 |\ \ parent: 13:22d8966a97e3
2582 2584 | | | parent: 14:8eac370358ef
2583 2585 | | | user: test
2584 2586 | | | date: Thu Jan 01 00:00:15 1970 +0000
2585 2587 | | | summary: (15) expand
2586 2588 | | |
2587 2589 | o | changeset: 14:8eac370358ef
2588 2590 | |\| parent: 0:e6eb3150255d
2589 2591 | ~ | parent: 12:86b91144a6e9
2590 2592 | | user: test
2591 2593 | | date: Thu Jan 01 00:00:14 1970 +0000
2592 2594 | | summary: (14) merge two known; one immediate right, one far right
2593 2595 | /
2594 2596 o | changeset: 13:22d8966a97e3
2595 2597 |\ \ parent: 9:7010c0af0a35
2596 2598 | | | parent: 11:832d76e6bdf2
2597 2599 | | | user: test
2598 2600 | | | date: Thu Jan 01 00:00:13 1970 +0000
2599 2601 | | | summary: (13) expand
2600 2602 | | |
2601 2603 +---o changeset: 12:86b91144a6e9
2602 2604 | | | parent: 1:6db2ef61d156
2603 2605 | | ~ parent: 9:7010c0af0a35
2604 2606 | | user: test
2605 2607 | | date: Thu Jan 01 00:00:12 1970 +0000
2606 2608 | | summary: (12) merge two known; one immediate right, one far left
2607 2609 | |
2608 2610 | o changeset: 11:832d76e6bdf2
2609 2611 | |\ parent: 6:b105a072e251
2610 2612 | | | parent: 10:74c64d036d72
2611 2613 | | | user: test
2612 2614 | | | date: Thu Jan 01 00:00:11 1970 +0000
2613 2615 | | | summary: (11) expand
2614 2616 | | |
2615 2617 | | o changeset: 10:74c64d036d72
2616 2618 | |/| parent: 0:e6eb3150255d
2617 2619 | | ~ parent: 6:b105a072e251
2618 2620 | | user: test
2619 2621 | | date: Thu Jan 01 00:00:10 1970 +0000
2620 2622 | | summary: (10) merge two known; one immediate left, one near right
2621 2623 | |
2622 2624 o | changeset: 9:7010c0af0a35
2623 2625 |\ \ parent: 7:b632bb1b1224
2624 2626 | | | parent: 8:7a0b11f71937
2625 2627 | | | user: test
2626 2628 | | | date: Thu Jan 01 00:00:09 1970 +0000
2627 2629 | | | summary: (9) expand
2628 2630 | | |
2629 2631 | o | changeset: 8:7a0b11f71937
2630 2632 |/| | parent: 0:e6eb3150255d
2631 2633 | ~ | parent: 7:b632bb1b1224
2632 2634 | | user: test
2633 2635 | | date: Thu Jan 01 00:00:08 1970 +0000
2634 2636 | | summary: (8) merge two known; one immediate left, one far right
2635 2637 | /
2636 2638 o | changeset: 7:b632bb1b1224
2637 2639 |\ \ parent: 2:3d9a33b8d1e1
2638 2640 | ~ | parent: 5:4409d547b708
2639 2641 | | user: test
2640 2642 | | date: Thu Jan 01 00:00:07 1970 +0000
2641 2643 | | summary: (7) expand
2642 2644 | /
2643 2645 | o changeset: 6:b105a072e251
2644 2646 |/| parent: 2:3d9a33b8d1e1
2645 2647 | ~ parent: 5:4409d547b708
2646 2648 | user: test
2647 2649 | date: Thu Jan 01 00:00:06 1970 +0000
2648 2650 | summary: (6) merge two known; one immediate left, one far left
2649 2651 |
2650 2652 o changeset: 5:4409d547b708
2651 2653 |\ parent: 3:27eef8ed80b4
2652 2654 | ~ parent: 4:26a8bac39d9f
2653 2655 | user: test
2654 2656 | date: Thu Jan 01 00:00:05 1970 +0000
2655 2657 | summary: (5) expand
2656 2658 |
2657 2659 o changeset: 4:26a8bac39d9f
2658 2660 |\ parent: 1:6db2ef61d156
2659 2661 ~ ~ parent: 3:27eef8ed80b4
2660 2662 user: test
2661 2663 date: Thu Jan 01 00:00:04 1970 +0000
2662 2664 summary: (4) merge two known; one immediate left, one immediate right
2663 2665
2664 2666
2665 2667 Setting HGPLAIN ignores graphmod styling:
2666 2668
2667 2669 $ HGPLAIN=1 hg log -G -r 'file("a")' -m
2668 2670 @ changeset: 36:08a19a744424
2669 2671 | branch: branch
2670 2672 | tag: tip
2671 2673 | parent: 35:9159c3644c5e
2672 2674 | parent: 35:9159c3644c5e
2673 2675 | user: test
2674 2676 | date: Thu Jan 01 00:00:36 1970 +0000
2675 2677 | summary: (36) buggy merge: identical parents
2676 2678 |
2677 2679 o changeset: 32:d06dffa21a31
2678 2680 |\ parent: 27:886ed638191b
2679 2681 | | parent: 31:621d83e11f67
2680 2682 | | user: test
2681 2683 | | date: Thu Jan 01 00:00:32 1970 +0000
2682 2684 | | summary: (32) expand
2683 2685 | |
2684 2686 o | changeset: 31:621d83e11f67
2685 2687 |\| parent: 21:d42a756af44d
2686 2688 | | parent: 30:6e11cd4b648f
2687 2689 | | user: test
2688 2690 | | date: Thu Jan 01 00:00:31 1970 +0000
2689 2691 | | summary: (31) expand
2690 2692 | |
2691 2693 o | changeset: 30:6e11cd4b648f
2692 2694 |\ \ parent: 28:44ecd0b9ae99
2693 2695 | | | parent: 29:cd9bb2be7593
2694 2696 | | | user: test
2695 2697 | | | date: Thu Jan 01 00:00:30 1970 +0000
2696 2698 | | | summary: (30) expand
2697 2699 | | |
2698 2700 o | | changeset: 28:44ecd0b9ae99
2699 2701 |\ \ \ parent: 1:6db2ef61d156
2700 2702 | | | | parent: 26:7f25b6c2f0b9
2701 2703 | | | | user: test
2702 2704 | | | | date: Thu Jan 01 00:00:28 1970 +0000
2703 2705 | | | | summary: (28) merge zero known
2704 2706 | | | |
2705 2707 o | | | changeset: 26:7f25b6c2f0b9
2706 2708 |\ \ \ \ parent: 18:1aa84d96232a
2707 2709 | | | | | parent: 25:91da8ed57247
2708 2710 | | | | | user: test
2709 2711 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
2710 2712 | | | | | summary: (26) merge one known; far right
2711 2713 | | | | |
2712 2714 | o-----+ changeset: 25:91da8ed57247
2713 2715 | | | | | parent: 21:d42a756af44d
2714 2716 | | | | | parent: 24:a9c19a3d96b7
2715 2717 | | | | | user: test
2716 2718 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
2717 2719 | | | | | summary: (25) merge one known; far left
2718 2720 | | | | |
2719 2721 | o | | | changeset: 24:a9c19a3d96b7
2720 2722 | |\ \ \ \ parent: 0:e6eb3150255d
2721 2723 | | | | | | parent: 23:a01cddf0766d
2722 2724 | | | | | | user: test
2723 2725 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
2724 2726 | | | | | | summary: (24) merge one known; immediate right
2725 2727 | | | | | |
2726 2728 | o---+ | | changeset: 23:a01cddf0766d
2727 2729 | | | | | | parent: 1:6db2ef61d156
2728 2730 | | | | | | parent: 22:e0d9cccacb5d
2729 2731 | | | | | | user: test
2730 2732 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
2731 2733 | | | | | | summary: (23) merge one known; immediate left
2732 2734 | | | | | |
2733 2735 | o-------+ changeset: 22:e0d9cccacb5d
2734 2736 | | | | | | parent: 18:1aa84d96232a
2735 2737 |/ / / / / parent: 21:d42a756af44d
2736 2738 | | | | | user: test
2737 2739 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
2738 2740 | | | | | summary: (22) merge two known; one far left, one far right
2739 2741 | | | | |
2740 2742 | | | | o changeset: 21:d42a756af44d
2741 2743 | | | | |\ parent: 19:31ddc2c1573b
2742 2744 | | | | | | parent: 20:d30ed6450e32
2743 2745 | | | | | | user: test
2744 2746 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
2745 2747 | | | | | | summary: (21) expand
2746 2748 | | | | | |
2747 2749 +-+-------o changeset: 20:d30ed6450e32
2748 2750 | | | | | parent: 0:e6eb3150255d
2749 2751 | | | | | parent: 18:1aa84d96232a
2750 2752 | | | | | user: test
2751 2753 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
2752 2754 | | | | | summary: (20) merge two known; two far right
2753 2755 | | | | |
2754 2756 | | | | o changeset: 19:31ddc2c1573b
2755 2757 | | | | |\ parent: 15:1dda3f72782d
2756 2758 | | | | | | parent: 17:44765d7c06e0
2757 2759 | | | | | | user: test
2758 2760 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
2759 2761 | | | | | | summary: (19) expand
2760 2762 | | | | | |
2761 2763 o---+---+ | changeset: 18:1aa84d96232a
2762 2764 | | | | | parent: 1:6db2ef61d156
2763 2765 / / / / / parent: 15:1dda3f72782d
2764 2766 | | | | | user: test
2765 2767 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
2766 2768 | | | | | summary: (18) merge two known; two far left
2767 2769 | | | | |
2768 2770 | | | | o changeset: 17:44765d7c06e0
2769 2771 | | | | |\ parent: 12:86b91144a6e9
2770 2772 | | | | | | parent: 16:3677d192927d
2771 2773 | | | | | | user: test
2772 2774 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
2773 2775 | | | | | | summary: (17) expand
2774 2776 | | | | | |
2775 2777 +-+-------o changeset: 16:3677d192927d
2776 2778 | | | | | parent: 0:e6eb3150255d
2777 2779 | | | | | parent: 1:6db2ef61d156
2778 2780 | | | | | user: test
2779 2781 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
2780 2782 | | | | | summary: (16) merge two known; one immediate right, one near right
2781 2783 | | | | |
2782 2784 | | | o | changeset: 15:1dda3f72782d
2783 2785 | | | |\ \ parent: 13:22d8966a97e3
2784 2786 | | | | | | parent: 14:8eac370358ef
2785 2787 | | | | | | user: test
2786 2788 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
2787 2789 | | | | | | summary: (15) expand
2788 2790 | | | | | |
2789 2791 +-------o | changeset: 14:8eac370358ef
2790 2792 | | | | |/ parent: 0:e6eb3150255d
2791 2793 | | | | | parent: 12:86b91144a6e9
2792 2794 | | | | | user: test
2793 2795 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
2794 2796 | | | | | summary: (14) merge two known; one immediate right, one far right
2795 2797 | | | | |
2796 2798 | | | o | changeset: 13:22d8966a97e3
2797 2799 | | | |\ \ parent: 9:7010c0af0a35
2798 2800 | | | | | | parent: 11:832d76e6bdf2
2799 2801 | | | | | | user: test
2800 2802 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
2801 2803 | | | | | | summary: (13) expand
2802 2804 | | | | | |
2803 2805 | +---+---o changeset: 12:86b91144a6e9
2804 2806 | | | | | parent: 1:6db2ef61d156
2805 2807 | | | | | parent: 9:7010c0af0a35
2806 2808 | | | | | user: test
2807 2809 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
2808 2810 | | | | | summary: (12) merge two known; one immediate right, one far left
2809 2811 | | | | |
2810 2812 | | | | o changeset: 11:832d76e6bdf2
2811 2813 | | | | |\ parent: 6:b105a072e251
2812 2814 | | | | | | parent: 10:74c64d036d72
2813 2815 | | | | | | user: test
2814 2816 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
2815 2817 | | | | | | summary: (11) expand
2816 2818 | | | | | |
2817 2819 +---------o changeset: 10:74c64d036d72
2818 2820 | | | | |/ parent: 0:e6eb3150255d
2819 2821 | | | | | parent: 6:b105a072e251
2820 2822 | | | | | user: test
2821 2823 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
2822 2824 | | | | | summary: (10) merge two known; one immediate left, one near right
2823 2825 | | | | |
2824 2826 | | | o | changeset: 9:7010c0af0a35
2825 2827 | | | |\ \ parent: 7:b632bb1b1224
2826 2828 | | | | | | parent: 8:7a0b11f71937
2827 2829 | | | | | | user: test
2828 2830 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
2829 2831 | | | | | | summary: (9) expand
2830 2832 | | | | | |
2831 2833 +-------o | changeset: 8:7a0b11f71937
2832 2834 | | | |/ / parent: 0:e6eb3150255d
2833 2835 | | | | | parent: 7:b632bb1b1224
2834 2836 | | | | | user: test
2835 2837 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
2836 2838 | | | | | summary: (8) merge two known; one immediate left, one far right
2837 2839 | | | | |
2838 2840 | | | o | changeset: 7:b632bb1b1224
2839 2841 | | | |\ \ parent: 2:3d9a33b8d1e1
2840 2842 | | | | | | parent: 5:4409d547b708
2841 2843 | | | | | | user: test
2842 2844 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
2843 2845 | | | | | | summary: (7) expand
2844 2846 | | | | | |
2845 2847 | | | +---o changeset: 6:b105a072e251
2846 2848 | | | | |/ parent: 2:3d9a33b8d1e1
2847 2849 | | | | | parent: 5:4409d547b708
2848 2850 | | | | | user: test
2849 2851 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
2850 2852 | | | | | summary: (6) merge two known; one immediate left, one far left
2851 2853 | | | | |
2852 2854 | | | o | changeset: 5:4409d547b708
2853 2855 | | | |\ \ parent: 3:27eef8ed80b4
2854 2856 | | | | | | parent: 4:26a8bac39d9f
2855 2857 | | | | | | user: test
2856 2858 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
2857 2859 | | | | | | summary: (5) expand
2858 2860 | | | | | |
2859 2861 | +---o | | changeset: 4:26a8bac39d9f
2860 2862 | | | |/ / parent: 1:6db2ef61d156
2861 2863 | | | | | parent: 3:27eef8ed80b4
2862 2864 | | | | | user: test
2863 2865 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
2864 2866 | | | | | summary: (4) merge two known; one immediate left, one immediate right
2865 2867 | | | | |
2866 2868
2867 2869 .. unless HGPLAINEXCEPT=graph is set:
2868 2870
2869 2871 $ HGPLAIN=1 HGPLAINEXCEPT=graph hg log -G -r 'file("a")' -m
2870 2872 @ changeset: 36:08a19a744424
2871 2873 : branch: branch
2872 2874 : tag: tip
2873 2875 : parent: 35:9159c3644c5e
2874 2876 : parent: 35:9159c3644c5e
2875 2877 : user: test
2876 2878 : date: Thu Jan 01 00:00:36 1970 +0000
2877 2879 : summary: (36) buggy merge: identical parents
2878 2880 :
2879 2881 o changeset: 32:d06dffa21a31
2880 2882 |\ parent: 27:886ed638191b
2881 2883 | : parent: 31:621d83e11f67
2882 2884 | : user: test
2883 2885 | : date: Thu Jan 01 00:00:32 1970 +0000
2884 2886 | : summary: (32) expand
2885 2887 | :
2886 2888 o : changeset: 31:621d83e11f67
2887 2889 |\: parent: 21:d42a756af44d
2888 2890 | : parent: 30:6e11cd4b648f
2889 2891 | : user: test
2890 2892 | : date: Thu Jan 01 00:00:31 1970 +0000
2891 2893 | : summary: (31) expand
2892 2894 | :
2893 2895 o : changeset: 30:6e11cd4b648f
2894 2896 |\ \ parent: 28:44ecd0b9ae99
2895 2897 | ~ : parent: 29:cd9bb2be7593
2896 2898 | : user: test
2897 2899 | : date: Thu Jan 01 00:00:30 1970 +0000
2898 2900 | : summary: (30) expand
2899 2901 | /
2900 2902 o : changeset: 28:44ecd0b9ae99
2901 2903 |\ \ parent: 1:6db2ef61d156
2902 2904 | ~ : parent: 26:7f25b6c2f0b9
2903 2905 | : user: test
2904 2906 | : date: Thu Jan 01 00:00:28 1970 +0000
2905 2907 | : summary: (28) merge zero known
2906 2908 | /
2907 2909 o : changeset: 26:7f25b6c2f0b9
2908 2910 |\ \ parent: 18:1aa84d96232a
2909 2911 | | : parent: 25:91da8ed57247
2910 2912 | | : user: test
2911 2913 | | : date: Thu Jan 01 00:00:26 1970 +0000
2912 2914 | | : summary: (26) merge one known; far right
2913 2915 | | :
2914 2916 | o : changeset: 25:91da8ed57247
2915 2917 | |\: parent: 21:d42a756af44d
2916 2918 | | : parent: 24:a9c19a3d96b7
2917 2919 | | : user: test
2918 2920 | | : date: Thu Jan 01 00:00:25 1970 +0000
2919 2921 | | : summary: (25) merge one known; far left
2920 2922 | | :
2921 2923 | o : changeset: 24:a9c19a3d96b7
2922 2924 | |\ \ parent: 0:e6eb3150255d
2923 2925 | | ~ : parent: 23:a01cddf0766d
2924 2926 | | : user: test
2925 2927 | | : date: Thu Jan 01 00:00:24 1970 +0000
2926 2928 | | : summary: (24) merge one known; immediate right
2927 2929 | | /
2928 2930 | o : changeset: 23:a01cddf0766d
2929 2931 | |\ \ parent: 1:6db2ef61d156
2930 2932 | | ~ : parent: 22:e0d9cccacb5d
2931 2933 | | : user: test
2932 2934 | | : date: Thu Jan 01 00:00:23 1970 +0000
2933 2935 | | : summary: (23) merge one known; immediate left
2934 2936 | | /
2935 2937 | o : changeset: 22:e0d9cccacb5d
2936 2938 |/:/ parent: 18:1aa84d96232a
2937 2939 | : parent: 21:d42a756af44d
2938 2940 | : user: test
2939 2941 | : date: Thu Jan 01 00:00:22 1970 +0000
2940 2942 | : summary: (22) merge two known; one far left, one far right
2941 2943 | :
2942 2944 | o changeset: 21:d42a756af44d
2943 2945 | |\ parent: 19:31ddc2c1573b
2944 2946 | | | parent: 20:d30ed6450e32
2945 2947 | | | user: test
2946 2948 | | | date: Thu Jan 01 00:00:21 1970 +0000
2947 2949 | | | summary: (21) expand
2948 2950 | | |
2949 2951 +---o changeset: 20:d30ed6450e32
2950 2952 | | | parent: 0:e6eb3150255d
2951 2953 | | ~ parent: 18:1aa84d96232a
2952 2954 | | user: test
2953 2955 | | date: Thu Jan 01 00:00:20 1970 +0000
2954 2956 | | summary: (20) merge two known; two far right
2955 2957 | |
2956 2958 | o changeset: 19:31ddc2c1573b
2957 2959 | |\ parent: 15:1dda3f72782d
2958 2960 | | | parent: 17:44765d7c06e0
2959 2961 | | | user: test
2960 2962 | | | date: Thu Jan 01 00:00:19 1970 +0000
2961 2963 | | | summary: (19) expand
2962 2964 | | |
2963 2965 o | | changeset: 18:1aa84d96232a
2964 2966 |\| | parent: 1:6db2ef61d156
2965 2967 ~ | | parent: 15:1dda3f72782d
2966 2968 | | user: test
2967 2969 | | date: Thu Jan 01 00:00:18 1970 +0000
2968 2970 | | summary: (18) merge two known; two far left
2969 2971 / /
2970 2972 | o changeset: 17:44765d7c06e0
2971 2973 | |\ parent: 12:86b91144a6e9
2972 2974 | | | parent: 16:3677d192927d
2973 2975 | | | user: test
2974 2976 | | | date: Thu Jan 01 00:00:17 1970 +0000
2975 2977 | | | summary: (17) expand
2976 2978 | | |
2977 2979 | | o changeset: 16:3677d192927d
2978 2980 | | |\ parent: 0:e6eb3150255d
2979 2981 | | ~ ~ parent: 1:6db2ef61d156
2980 2982 | | user: test
2981 2983 | | date: Thu Jan 01 00:00:16 1970 +0000
2982 2984 | | summary: (16) merge two known; one immediate right, one near right
2983 2985 | |
2984 2986 o | changeset: 15:1dda3f72782d
2985 2987 |\ \ parent: 13:22d8966a97e3
2986 2988 | | | parent: 14:8eac370358ef
2987 2989 | | | user: test
2988 2990 | | | date: Thu Jan 01 00:00:15 1970 +0000
2989 2991 | | | summary: (15) expand
2990 2992 | | |
2991 2993 | o | changeset: 14:8eac370358ef
2992 2994 | |\| parent: 0:e6eb3150255d
2993 2995 | ~ | parent: 12:86b91144a6e9
2994 2996 | | user: test
2995 2997 | | date: Thu Jan 01 00:00:14 1970 +0000
2996 2998 | | summary: (14) merge two known; one immediate right, one far right
2997 2999 | /
2998 3000 o | changeset: 13:22d8966a97e3
2999 3001 |\ \ parent: 9:7010c0af0a35
3000 3002 | | | parent: 11:832d76e6bdf2
3001 3003 | | | user: test
3002 3004 | | | date: Thu Jan 01 00:00:13 1970 +0000
3003 3005 | | | summary: (13) expand
3004 3006 | | |
3005 3007 +---o changeset: 12:86b91144a6e9
3006 3008 | | | parent: 1:6db2ef61d156
3007 3009 | | ~ parent: 9:7010c0af0a35
3008 3010 | | user: test
3009 3011 | | date: Thu Jan 01 00:00:12 1970 +0000
3010 3012 | | summary: (12) merge two known; one immediate right, one far left
3011 3013 | |
3012 3014 | o changeset: 11:832d76e6bdf2
3013 3015 | |\ parent: 6:b105a072e251
3014 3016 | | | parent: 10:74c64d036d72
3015 3017 | | | user: test
3016 3018 | | | date: Thu Jan 01 00:00:11 1970 +0000
3017 3019 | | | summary: (11) expand
3018 3020 | | |
3019 3021 | | o changeset: 10:74c64d036d72
3020 3022 | |/| parent: 0:e6eb3150255d
3021 3023 | | ~ parent: 6:b105a072e251
3022 3024 | | user: test
3023 3025 | | date: Thu Jan 01 00:00:10 1970 +0000
3024 3026 | | summary: (10) merge two known; one immediate left, one near right
3025 3027 | |
3026 3028 o | changeset: 9:7010c0af0a35
3027 3029 |\ \ parent: 7:b632bb1b1224
3028 3030 | | | parent: 8:7a0b11f71937
3029 3031 | | | user: test
3030 3032 | | | date: Thu Jan 01 00:00:09 1970 +0000
3031 3033 | | | summary: (9) expand
3032 3034 | | |
3033 3035 | o | changeset: 8:7a0b11f71937
3034 3036 |/| | parent: 0:e6eb3150255d
3035 3037 | ~ | parent: 7:b632bb1b1224
3036 3038 | | user: test
3037 3039 | | date: Thu Jan 01 00:00:08 1970 +0000
3038 3040 | | summary: (8) merge two known; one immediate left, one far right
3039 3041 | /
3040 3042 o | changeset: 7:b632bb1b1224
3041 3043 |\ \ parent: 2:3d9a33b8d1e1
3042 3044 | ~ | parent: 5:4409d547b708
3043 3045 | | user: test
3044 3046 | | date: Thu Jan 01 00:00:07 1970 +0000
3045 3047 | | summary: (7) expand
3046 3048 | /
3047 3049 | o changeset: 6:b105a072e251
3048 3050 |/| parent: 2:3d9a33b8d1e1
3049 3051 | ~ parent: 5:4409d547b708
3050 3052 | user: test
3051 3053 | date: Thu Jan 01 00:00:06 1970 +0000
3052 3054 | summary: (6) merge two known; one immediate left, one far left
3053 3055 |
3054 3056 o changeset: 5:4409d547b708
3055 3057 |\ parent: 3:27eef8ed80b4
3056 3058 | ~ parent: 4:26a8bac39d9f
3057 3059 | user: test
3058 3060 | date: Thu Jan 01 00:00:05 1970 +0000
3059 3061 | summary: (5) expand
3060 3062 |
3061 3063 o changeset: 4:26a8bac39d9f
3062 3064 |\ parent: 1:6db2ef61d156
3063 3065 ~ ~ parent: 3:27eef8ed80b4
3064 3066 user: test
3065 3067 date: Thu Jan 01 00:00:04 1970 +0000
3066 3068 summary: (4) merge two known; one immediate left, one immediate right
3067 3069
3068 3070 Draw only part of a grandparent line differently with "<N><char>"; only the
3069 3071 last N lines (for positive N) or everything but the first N lines (for
3070 3072 negative N) along the current node use the style, the rest of the edge uses
3071 3073 the parent edge styling.
3072 3074
3073 3075 Last 3 lines:
3074 3076
3075 3077 $ cat << EOF >> $HGRCPATH
3076 3078 > [experimental]
3077 3079 > graphstyle.parent = !
3078 3080 > graphstyle.grandparent = 3.
3079 3081 > graphstyle.missing =
3080 3082 > EOF
3081 3083 $ hg log -G -r '36:18 & file("a")' -m
3082 3084 @ changeset: 36:08a19a744424
3083 3085 ! branch: branch
3084 3086 ! tag: tip
3085 3087 ! parent: 35:9159c3644c5e
3086 3088 ! parent: 35:9159c3644c5e
3087 3089 ! user: test
3088 3090 . date: Thu Jan 01 00:00:36 1970 +0000
3089 3091 . summary: (36) buggy merge: identical parents
3090 3092 .
3091 3093 o changeset: 32:d06dffa21a31
3092 3094 !\ parent: 27:886ed638191b
3093 3095 ! ! parent: 31:621d83e11f67
3094 3096 ! ! user: test
3095 3097 ! . date: Thu Jan 01 00:00:32 1970 +0000
3096 3098 ! . summary: (32) expand
3097 3099 ! .
3098 3100 o ! changeset: 31:621d83e11f67
3099 3101 !\! parent: 21:d42a756af44d
3100 3102 ! ! parent: 30:6e11cd4b648f
3101 3103 ! ! user: test
3102 3104 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3103 3105 ! ! summary: (31) expand
3104 3106 ! !
3105 3107 o ! changeset: 30:6e11cd4b648f
3106 3108 !\ \ parent: 28:44ecd0b9ae99
3107 3109 ! ~ ! parent: 29:cd9bb2be7593
3108 3110 ! ! user: test
3109 3111 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3110 3112 ! ! summary: (30) expand
3111 3113 ! /
3112 3114 o ! changeset: 28:44ecd0b9ae99
3113 3115 !\ \ parent: 1:6db2ef61d156
3114 3116 ! ~ ! parent: 26:7f25b6c2f0b9
3115 3117 ! ! user: test
3116 3118 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3117 3119 ! ! summary: (28) merge zero known
3118 3120 ! /
3119 3121 o ! changeset: 26:7f25b6c2f0b9
3120 3122 !\ \ parent: 18:1aa84d96232a
3121 3123 ! ! ! parent: 25:91da8ed57247
3122 3124 ! ! ! user: test
3123 3125 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3124 3126 ! ! ! summary: (26) merge one known; far right
3125 3127 ! ! !
3126 3128 ! o ! changeset: 25:91da8ed57247
3127 3129 ! !\! parent: 21:d42a756af44d
3128 3130 ! ! ! parent: 24:a9c19a3d96b7
3129 3131 ! ! ! user: test
3130 3132 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3131 3133 ! ! ! summary: (25) merge one known; far left
3132 3134 ! ! !
3133 3135 ! o ! changeset: 24:a9c19a3d96b7
3134 3136 ! !\ \ parent: 0:e6eb3150255d
3135 3137 ! ! ~ ! parent: 23:a01cddf0766d
3136 3138 ! ! ! user: test
3137 3139 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3138 3140 ! ! ! summary: (24) merge one known; immediate right
3139 3141 ! ! /
3140 3142 ! o ! changeset: 23:a01cddf0766d
3141 3143 ! !\ \ parent: 1:6db2ef61d156
3142 3144 ! ! ~ ! parent: 22:e0d9cccacb5d
3143 3145 ! ! ! user: test
3144 3146 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3145 3147 ! ! ! summary: (23) merge one known; immediate left
3146 3148 ! ! /
3147 3149 ! o ! changeset: 22:e0d9cccacb5d
3148 3150 !/!/ parent: 18:1aa84d96232a
3149 3151 ! ! parent: 21:d42a756af44d
3150 3152 ! ! user: test
3151 3153 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3152 3154 ! ! summary: (22) merge two known; one far left, one far right
3153 3155 ! !
3154 3156 ! o changeset: 21:d42a756af44d
3155 3157 ! !\ parent: 19:31ddc2c1573b
3156 3158 ! ! ! parent: 20:d30ed6450e32
3157 3159 ! ! ! user: test
3158 3160 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3159 3161 ! ! ! summary: (21) expand
3160 3162 ! ! !
3161 3163 +---o changeset: 20:d30ed6450e32
3162 3164 ! ! | parent: 0:e6eb3150255d
3163 3165 ! ! ~ parent: 18:1aa84d96232a
3164 3166 ! ! user: test
3165 3167 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3166 3168 ! ! summary: (20) merge two known; two far right
3167 3169 ! !
3168 3170 ! o changeset: 19:31ddc2c1573b
3169 3171 ! |\ parent: 15:1dda3f72782d
3170 3172 ! ~ ~ parent: 17:44765d7c06e0
3171 3173 ! user: test
3172 3174 ! date: Thu Jan 01 00:00:19 1970 +0000
3173 3175 ! summary: (19) expand
3174 3176 !
3175 3177 o changeset: 18:1aa84d96232a
3176 3178 |\ parent: 1:6db2ef61d156
3177 3179 ~ ~ parent: 15:1dda3f72782d
3178 3180 user: test
3179 3181 date: Thu Jan 01 00:00:18 1970 +0000
3180 3182 summary: (18) merge two known; two far left
3181 3183
3182 3184 All but the first 3 lines:
3183 3185
3184 3186 $ cat << EOF >> $HGRCPATH
3185 3187 > [experimental]
3186 3188 > graphstyle.parent = !
3187 3189 > graphstyle.grandparent = -3.
3188 3190 > graphstyle.missing =
3189 3191 > EOF
3190 3192 $ hg log -G -r '36:18 & file("a")' -m
3191 3193 @ changeset: 36:08a19a744424
3192 3194 ! branch: branch
3193 3195 ! tag: tip
3194 3196 . parent: 35:9159c3644c5e
3195 3197 . parent: 35:9159c3644c5e
3196 3198 . user: test
3197 3199 . date: Thu Jan 01 00:00:36 1970 +0000
3198 3200 . summary: (36) buggy merge: identical parents
3199 3201 .
3200 3202 o changeset: 32:d06dffa21a31
3201 3203 !\ parent: 27:886ed638191b
3202 3204 ! ! parent: 31:621d83e11f67
3203 3205 ! . user: test
3204 3206 ! . date: Thu Jan 01 00:00:32 1970 +0000
3205 3207 ! . summary: (32) expand
3206 3208 ! .
3207 3209 o ! changeset: 31:621d83e11f67
3208 3210 !\! parent: 21:d42a756af44d
3209 3211 ! ! parent: 30:6e11cd4b648f
3210 3212 ! ! user: test
3211 3213 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3212 3214 ! ! summary: (31) expand
3213 3215 ! !
3214 3216 o ! changeset: 30:6e11cd4b648f
3215 3217 !\ \ parent: 28:44ecd0b9ae99
3216 3218 ! ~ ! parent: 29:cd9bb2be7593
3217 3219 ! ! user: test
3218 3220 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3219 3221 ! ! summary: (30) expand
3220 3222 ! /
3221 3223 o ! changeset: 28:44ecd0b9ae99
3222 3224 !\ \ parent: 1:6db2ef61d156
3223 3225 ! ~ ! parent: 26:7f25b6c2f0b9
3224 3226 ! ! user: test
3225 3227 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3226 3228 ! ! summary: (28) merge zero known
3227 3229 ! /
3228 3230 o ! changeset: 26:7f25b6c2f0b9
3229 3231 !\ \ parent: 18:1aa84d96232a
3230 3232 ! ! ! parent: 25:91da8ed57247
3231 3233 ! ! ! user: test
3232 3234 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3233 3235 ! ! ! summary: (26) merge one known; far right
3234 3236 ! ! !
3235 3237 ! o ! changeset: 25:91da8ed57247
3236 3238 ! !\! parent: 21:d42a756af44d
3237 3239 ! ! ! parent: 24:a9c19a3d96b7
3238 3240 ! ! ! user: test
3239 3241 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3240 3242 ! ! ! summary: (25) merge one known; far left
3241 3243 ! ! !
3242 3244 ! o ! changeset: 24:a9c19a3d96b7
3243 3245 ! !\ \ parent: 0:e6eb3150255d
3244 3246 ! ! ~ ! parent: 23:a01cddf0766d
3245 3247 ! ! ! user: test
3246 3248 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3247 3249 ! ! ! summary: (24) merge one known; immediate right
3248 3250 ! ! /
3249 3251 ! o ! changeset: 23:a01cddf0766d
3250 3252 ! !\ \ parent: 1:6db2ef61d156
3251 3253 ! ! ~ ! parent: 22:e0d9cccacb5d
3252 3254 ! ! ! user: test
3253 3255 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3254 3256 ! ! ! summary: (23) merge one known; immediate left
3255 3257 ! ! /
3256 3258 ! o ! changeset: 22:e0d9cccacb5d
3257 3259 !/!/ parent: 18:1aa84d96232a
3258 3260 ! ! parent: 21:d42a756af44d
3259 3261 ! ! user: test
3260 3262 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3261 3263 ! ! summary: (22) merge two known; one far left, one far right
3262 3264 ! !
3263 3265 ! o changeset: 21:d42a756af44d
3264 3266 ! !\ parent: 19:31ddc2c1573b
3265 3267 ! ! ! parent: 20:d30ed6450e32
3266 3268 ! ! ! user: test
3267 3269 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3268 3270 ! ! ! summary: (21) expand
3269 3271 ! ! !
3270 3272 +---o changeset: 20:d30ed6450e32
3271 3273 ! ! | parent: 0:e6eb3150255d
3272 3274 ! ! ~ parent: 18:1aa84d96232a
3273 3275 ! ! user: test
3274 3276 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3275 3277 ! ! summary: (20) merge two known; two far right
3276 3278 ! !
3277 3279 ! o changeset: 19:31ddc2c1573b
3278 3280 ! |\ parent: 15:1dda3f72782d
3279 3281 ! ~ ~ parent: 17:44765d7c06e0
3280 3282 ! user: test
3281 3283 ! date: Thu Jan 01 00:00:19 1970 +0000
3282 3284 ! summary: (19) expand
3283 3285 !
3284 3286 o changeset: 18:1aa84d96232a
3285 3287 |\ parent: 1:6db2ef61d156
3286 3288 ~ ~ parent: 15:1dda3f72782d
3287 3289 user: test
3288 3290 date: Thu Jan 01 00:00:18 1970 +0000
3289 3291 summary: (18) merge two known; two far left
3290 3292
3291 3293 $ cd ..
3292 3294
3293 3295 Change graph shorten, test better with graphstyle.missing not none
3294 3296
3295 3297 $ cd repo
3296 3298 $ cat << EOF >> $HGRCPATH
3297 3299 > [experimental]
3298 3300 > graphstyle.parent = |
3299 3301 > graphstyle.grandparent = :
3300 3302 > graphstyle.missing = '
3301 3303 > graphshorten = true
3302 3304 > EOF
3303 3305 $ hg log -G -r 'file("a")' -m -T '{rev} {desc}'
3304 3306 @ 36 (36) buggy merge: identical parents
3305 3307 o 32 (32) expand
3306 3308 |\
3307 3309 o : 31 (31) expand
3308 3310 |\:
3309 3311 o : 30 (30) expand
3310 3312 |\ \
3311 3313 o \ \ 28 (28) merge zero known
3312 3314 |\ \ \
3313 3315 o \ \ \ 26 (26) merge one known; far right
3314 3316 |\ \ \ \
3315 3317 | o-----+ 25 (25) merge one known; far left
3316 3318 | o ' ' : 24 (24) merge one known; immediate right
3317 3319 | |\ \ \ \
3318 3320 | o---+ ' : 23 (23) merge one known; immediate left
3319 3321 | o-------+ 22 (22) merge two known; one far left, one far right
3320 3322 |/ / / / /
3321 3323 | ' ' ' o 21 (21) expand
3322 3324 | ' ' ' |\
3323 3325 +-+-------o 20 (20) merge two known; two far right
3324 3326 | ' ' ' o 19 (19) expand
3325 3327 | ' ' ' |\
3326 3328 o---+---+ | 18 (18) merge two known; two far left
3327 3329 / / / / /
3328 3330 ' ' ' | o 17 (17) expand
3329 3331 ' ' ' | |\
3330 3332 +-+-------o 16 (16) merge two known; one immediate right, one near right
3331 3333 ' ' ' o | 15 (15) expand
3332 3334 ' ' ' |\ \
3333 3335 +-------o | 14 (14) merge two known; one immediate right, one far right
3334 3336 ' ' ' | |/
3335 3337 ' ' ' o | 13 (13) expand
3336 3338 ' ' ' |\ \
3337 3339 ' +---+---o 12 (12) merge two known; one immediate right, one far left
3338 3340 ' ' ' | o 11 (11) expand
3339 3341 ' ' ' | |\
3340 3342 +---------o 10 (10) merge two known; one immediate left, one near right
3341 3343 ' ' ' | |/
3342 3344 ' ' ' o | 9 (9) expand
3343 3345 ' ' ' |\ \
3344 3346 +-------o | 8 (8) merge two known; one immediate left, one far right
3345 3347 ' ' ' |/ /
3346 3348 ' ' ' o | 7 (7) expand
3347 3349 ' ' ' |\ \
3348 3350 ' ' ' +---o 6 (6) merge two known; one immediate left, one far left
3349 3351 ' ' ' | '/
3350 3352 ' ' ' o ' 5 (5) expand
3351 3353 ' ' ' |\ \
3352 3354 ' +---o ' ' 4 (4) merge two known; one immediate left, one immediate right
3353 3355 ' ' ' '/ /
3354 3356
3355 3357 behavior with newlines
3356 3358
3357 3359 $ hg log -G -r ::2 -T '{rev} {desc}'
3358 3360 o 2 (2) collapse
3359 3361 o 1 (1) collapse
3360 3362 o 0 (0) root
3361 3363
3362 3364 $ hg log -G -r ::2 -T '{rev} {desc}\n'
3363 3365 o 2 (2) collapse
3364 3366 o 1 (1) collapse
3365 3367 o 0 (0) root
3366 3368
3367 3369 $ hg log -G -r ::2 -T '{rev} {desc}\n\n'
3368 3370 o 2 (2) collapse
3369 3371 |
3370 3372 o 1 (1) collapse
3371 3373 |
3372 3374 o 0 (0) root
3373 3375
3374 3376
3375 3377 $ hg log -G -r ::2 -T '\n{rev} {desc}'
3376 3378 o
3377 3379 | 2 (2) collapse
3378 3380 o
3379 3381 | 1 (1) collapse
3380 3382 o
3381 3383 0 (0) root
3382 3384
3383 3385 $ hg log -G -r ::2 -T '{rev} {desc}\n\n\n'
3384 3386 o 2 (2) collapse
3385 3387 |
3386 3388 |
3387 3389 o 1 (1) collapse
3388 3390 |
3389 3391 |
3390 3392 o 0 (0) root
3391 3393
3392 3394
3393 3395 $ cd ..
3394 3396
3395 3397 When inserting extra line nodes to handle more than 2 parents, ensure that
3396 3398 the right node styles are used (issue5174):
3397 3399
3398 3400 $ hg init repo-issue5174
3399 3401 $ cd repo-issue5174
3400 3402 $ echo a > f0
3401 3403 $ hg ci -Aqm 0
3402 3404 $ echo a > f1
3403 3405 $ hg ci -Aqm 1
3404 3406 $ echo a > f2
3405 3407 $ hg ci -Aqm 2
3406 3408 $ hg co ".^"
3407 3409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3408 3410 $ echo a > f3
3409 3411 $ hg ci -Aqm 3
3410 3412 $ hg co ".^^"
3411 3413 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
3412 3414 $ echo a > f4
3413 3415 $ hg ci -Aqm 4
3414 3416 $ hg merge -r 2
3415 3417 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3416 3418 (branch merge, don't forget to commit)
3417 3419 $ hg ci -qm 5
3418 3420 $ hg merge -r 3
3419 3421 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3420 3422 (branch merge, don't forget to commit)
3421 3423 $ hg ci -qm 6
3422 3424 $ hg log -G -r '0 | 1 | 2 | 6'
3423 3425 @ changeset: 6:851fe89689ad
3424 3426 :\ tag: tip
3425 3427 : : parent: 5:4f1e3cf15f5d
3426 3428 : : parent: 3:b74ba7084d2d
3427 3429 : : user: test
3428 3430 : : date: Thu Jan 01 00:00:00 1970 +0000
3429 3431 : : summary: 6
3430 3432 : :
3431 3433 : \
3432 3434 : :\
3433 3435 : o : changeset: 2:3e6599df4cce
3434 3436 : :/ user: test
3435 3437 : : date: Thu Jan 01 00:00:00 1970 +0000
3436 3438 : : summary: 2
3437 3439 : :
3438 3440 : o changeset: 1:bd9a55143933
3439 3441 :/ user: test
3440 3442 : date: Thu Jan 01 00:00:00 1970 +0000
3441 3443 : summary: 1
3442 3444 :
3443 3445 o changeset: 0:870a5edc339c
3444 3446 user: test
3445 3447 date: Thu Jan 01 00:00:00 1970 +0000
3446 3448 summary: 0
3447 3449
3448 3450
3449 3451 $ cd ..
3450 3452
3451 3453 Multiple roots (issue5440):
3452 3454
3453 3455 $ hg init multiroots
3454 3456 $ cd multiroots
3455 3457 $ cat <<EOF > .hg/hgrc
3456 3458 > [ui]
3457 3459 > logtemplate = '{rev} {desc}\n\n'
3458 3460 > EOF
3459 3461
3460 3462 $ touch foo
3461 3463 $ hg ci -Aqm foo
3462 3464 $ hg co -q null
3463 3465 $ touch bar
3464 3466 $ hg ci -Aqm bar
3465 3467
3466 3468 $ hg log -Gr null:
3467 3469 @ 1 bar
3468 3470 |
3469 3471 | o 0 foo
3470 3472 |/
3471 3473 o -1
3472 3474
3473 3475 $ hg log -Gr null+0
3474 3476 o 0 foo
3475 3477 |
3476 3478 o -1
3477 3479
3478 3480 $ hg log -Gr null+1
3479 3481 @ 1 bar
3480 3482 |
3481 3483 o -1
3482 3484
3483 3485
3484 3486 $ cd ..
@@ -1,778 +1,792 b''
1 1 This file focuses mainly on updating largefiles in the working
2 2 directory (and ".hg/largefiles/dirstate")
3 3
4 4 $ cat >> $HGRCPATH <<EOF
5 5 > [ui]
6 6 > merge = internal:fail
7 7 > [extensions]
8 8 > largefiles =
9 9 > [extdiff]
10 10 > # for portability:
11 11 > pdiff = sh "$RUNTESTDIR/pdiff"
12 12 > EOF
13 13
14 14 $ hg init repo
15 15 $ cd repo
16 16
17 17 $ echo large1 > large1
18 18 $ echo large2 > large2
19 19 $ hg add --large large1 large2
20 20 $ echo normal1 > normal1
21 21 $ hg add normal1
22 22 $ hg commit -m '#0'
23 23 $ echo 'large1 in #1' > large1
24 24 $ echo 'normal1 in #1' > normal1
25 25 $ hg commit -m '#1'
26 26 $ hg pdiff -r '.^' --config extensions.extdiff=
27 27 diff -Nru repo.0d9d9b8dc9a3/.hglf/large1 repo/.hglf/large1
28 28 --- repo.0d9d9b8dc9a3/.hglf/large1 * (glob)
29 29 +++ repo/.hglf/large1 * (glob)
30 30 @@ -1* +1* @@ (glob)
31 31 -4669e532d5b2c093a78eca010077e708a071bb64
32 32 +58e24f733a964da346e2407a2bee99d9001184f5
33 33 diff -Nru repo.0d9d9b8dc9a3/normal1 repo/normal1
34 34 --- repo.0d9d9b8dc9a3/normal1 * (glob)
35 35 +++ repo/normal1 * (glob)
36 36 @@ -1* +1* @@ (glob)
37 37 -normal1
38 38 +normal1 in #1
39 39 [1]
40 40 $ hg update -q -C 0
41 41 $ echo 'large2 in #2' > large2
42 42 $ hg commit -m '#2'
43 43 created new head
44 44
45 45 Test that update also updates the lfdirstate of 'unsure' largefiles after
46 46 hashing them:
47 47
48 48 The previous operations will usually have left us with largefiles with a mtime
49 49 within the same second as the dirstate was written.
50 50 The lfdirstate entries will thus have been written with an invalidated/unset
51 51 mtime to make sure further changes within the same second is detected.
52 52 We will however occasionally be "lucky" and get a tick between writing
53 53 largefiles and writing dirstate so we get valid lfdirstate timestamps. The
54 54 following verification is thus disabled but can be verified manually.
55 55
56 56 #if false
57 57 $ hg debugdirstate --large --nodate
58 58 n 644 7 unset large1
59 59 n 644 13 unset large2
60 60 #endif
61 61
62 62 Wait to make sure we get a tick so the mtime of the largefiles become valid.
63 63
64 64 $ sleep 1
65 65
66 66 A linear merge will update standins before performing the actual merge. It will
67 67 do a lfdirstate status walk and find 'unset'/'unsure' files, hash them, and
68 68 update the corresponding standins.
69 69 Verify that it actually marks the clean files as clean in lfdirstate so
70 70 we don't have to hash them again next time we update.
71 71
72 72 $ hg up
73 73 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 74 updated to "f74e50bd9e55: #2"
75 75 1 other heads for branch "default"
76 76 $ hg debugdirstate --large --nodate
77 77 n 644 7 set large1
78 78 n 644 13 set large2
79 79
80 80 Test that lfdirstate keeps track of last modification of largefiles and
81 81 prevents unnecessary hashing of content - also after linear/noop update
82 82
83 83 $ sleep 1
84 84 $ hg st
85 85 $ hg debugdirstate --large --nodate
86 86 n 644 7 set large1
87 87 n 644 13 set large2
88 88 $ hg up
89 89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 90 updated to "f74e50bd9e55: #2"
91 91 1 other heads for branch "default"
92 92 $ hg debugdirstate --large --nodate
93 93 n 644 7 set large1
94 94 n 644 13 set large2
95 95
96 96 Test that "hg merge" updates largefiles from "other" correctly
97 97
98 98 (getting largefiles from "other" normally)
99 99
100 100 $ hg status -A large1
101 101 C large1
102 102 $ cat large1
103 103 large1
104 104 $ cat .hglf/large1
105 105 4669e532d5b2c093a78eca010077e708a071bb64
106 106 $ hg merge --config debug.dirstate.delaywrite=2
107 107 getting changed largefiles
108 108 1 largefiles updated, 0 removed
109 109 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 110 (branch merge, don't forget to commit)
111 111 $ hg status -A large1
112 112 M large1
113 113 $ cat large1
114 114 large1 in #1
115 115 $ cat .hglf/large1
116 116 58e24f733a964da346e2407a2bee99d9001184f5
117 117 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
118 118 -4669e532d5b2c093a78eca010077e708a071bb64
119 119 +58e24f733a964da346e2407a2bee99d9001184f5
120 120
121 121 (getting largefiles from "other" via conflict prompt)
122 122
123 123 $ hg update -q -C 2
124 124 $ echo 'large1 in #3' > large1
125 125 $ echo 'normal1 in #3' > normal1
126 126 $ hg commit -m '#3'
127 127 $ cat .hglf/large1
128 128 e5bb990443d6a92aaf7223813720f7566c9dd05b
129 129 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
130 130 > o
131 131 > EOF
132 132 largefile large1 has a merge conflict
133 133 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
134 134 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
135 135 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
136 136 merging normal1
137 137 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
138 138 getting changed largefiles
139 139 1 largefiles updated, 0 removed
140 140 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
141 141 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
142 142 [1]
143 143 $ hg status -A large1
144 144 M large1
145 145 $ cat large1
146 146 large1 in #1
147 147 $ cat .hglf/large1
148 148 58e24f733a964da346e2407a2bee99d9001184f5
149 149 $ rm normal1.orig
150 150
151 151 (merge non-existing largefiles from "other" via conflict prompt -
152 152 make sure the following commit doesn't abort in a confusing way when trying to
153 153 mark the non-existing file as normal in lfdirstate)
154 154
155 155 $ mv .hg/largefiles/58e24f733a964da346e2407a2bee99d9001184f5 .
156 156 $ hg update -q -C 3
157 157 $ hg merge --config largefiles.usercache=not --config debug.dirstate.delaywrite=2 --tool :local --config ui.interactive=True <<EOF
158 158 > o
159 159 > EOF
160 160 largefile large1 has a merge conflict
161 161 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
162 162 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
163 163 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
164 164 getting changed largefiles
165 165 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
166 166 0 largefiles updated, 0 removed
167 167 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
168 168 (branch merge, don't forget to commit)
169 169 $ hg commit -m '1-2-3 testing' --config largefiles.usercache=not
170 170 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from local store
171 171 $ hg up -C . --config largefiles.usercache=not
172 172 getting changed largefiles
173 173 large1: largefile 58e24f733a964da346e2407a2bee99d9001184f5 not available from file:/*/$TESTTMP/repo (glob)
174 174 0 largefiles updated, 0 removed
175 175 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
176 176 $ hg st large1
177 177 ! large1
178 178 $ hg rollback -q
179 179 $ mv 58e24f733a964da346e2407a2bee99d9001184f5 .hg/largefiles/
180 180
181 181 Test that "hg revert -r REV" updates largefiles from "REV" correctly
182 182
183 183 $ hg update -q -C 3
184 184 $ hg status -A large1
185 185 C large1
186 186 $ cat large1
187 187 large1 in #3
188 188 $ cat .hglf/large1
189 189 e5bb990443d6a92aaf7223813720f7566c9dd05b
190 190 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
191 191 -4669e532d5b2c093a78eca010077e708a071bb64
192 192 +58e24f733a964da346e2407a2bee99d9001184f5
193 193 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
194 194 $ hg status -A large1
195 195 M large1
196 196 $ cat large1
197 197 large1 in #1
198 198 $ cat .hglf/large1
199 199 58e24f733a964da346e2407a2bee99d9001184f5
200 200
201 201 Test that "hg rollback" restores status of largefiles correctly
202 202
203 203 $ hg update -C -q
204 204 $ hg remove large1
205 205 $ test -f .hglf/large1
206 206 [1]
207 207 $ hg forget large2
208 208 $ test -f .hglf/large2
209 209 [1]
210 210 $ echo largeX > largeX
211 211 $ hg add --large largeX
212 212 $ cat .hglf/largeX
213 213
214 214 $ hg commit -m 'will be rollback-ed soon'
215 215 $ echo largeY > largeY
216 216 $ hg add --large largeY
217 217
218 218 $ hg status -A large1
219 219 large1: $ENOENT$
220 220
221 221 $ hg status -A large2
222 222 ? large2
223 223 $ hg status -A largeX
224 224 C largeX
225 225 $ hg status -A largeY
226 226 A largeY
227 227 $ hg rollback
228 228 repository tip rolled back to revision 3 (undo commit)
229 229 working directory now based on revision 3
230 230 $ hg status -A large1
231 231 R large1
232 232 $ test -f .hglf/large1
233 233 [1]
234 234 $ hg status -A large2
235 235 R large2
236 236 $ test -f .hglf/large2
237 237 [1]
238 238 $ hg status -A largeX
239 239 A largeX
240 240 $ cat .hglf/largeX
241 241
242 242 $ hg status -A largeY
243 243 ? largeY
244 244 $ test -f .hglf/largeY
245 245 [1]
246 246 $ rm largeY
247 247
248 248 Test that "hg rollback" restores standins correctly
249 249
250 250 $ hg commit -m 'will be rollback-ed soon'
251 251 $ hg update -q -C 2
252 252 $ cat large1
253 253 large1
254 254 $ cat .hglf/large1
255 255 4669e532d5b2c093a78eca010077e708a071bb64
256 256 $ cat large2
257 257 large2 in #2
258 258 $ cat .hglf/large2
259 259 3cfce6277e7668985707b6887ce56f9f62f6ccd9
260 260
261 261 $ hg rollback -q -f
262 262 $ cat large1
263 263 large1
264 264 $ cat .hglf/large1
265 265 4669e532d5b2c093a78eca010077e708a071bb64
266 266 $ cat large2
267 267 large2 in #2
268 268 $ cat .hglf/large2
269 269 3cfce6277e7668985707b6887ce56f9f62f6ccd9
270 270
271 271 (rollback the parent of the working directory, when the parent of it
272 272 is not branch-tip)
273 273
274 274 $ hg update -q -C 1
275 275 $ cat .hglf/large1
276 276 58e24f733a964da346e2407a2bee99d9001184f5
277 277 $ cat .hglf/large2
278 278 1deebade43c8c498a3c8daddac0244dc55d1331d
279 279
280 280 $ echo normalX > normalX
281 281 $ hg add normalX
282 282 $ hg commit -m 'will be rollback-ed soon'
283 283 $ hg rollback -q
284 284
285 285 $ cat .hglf/large1
286 286 58e24f733a964da346e2407a2bee99d9001184f5
287 287 $ cat .hglf/large2
288 288 1deebade43c8c498a3c8daddac0244dc55d1331d
289 289 $ rm normalX
290 290
291 291 Test that "hg status" shows status of largefiles correctly just after
292 292 automated commit like rebase/transplant
293 293
294 294 $ cat >> .hg/hgrc <<EOF
295 295 > [extensions]
296 296 > rebase =
297 297 > strip =
298 298 > transplant =
299 299 > EOF
300 300 $ hg update -q -C 1
301 301 $ hg remove large1
302 302 $ echo largeX > largeX
303 303 $ hg add --large largeX
304 304 $ hg commit -m '#4'
305 305
306 306 $ hg rebase -s 1 -d 2 --keep
307 307 rebasing 1:72518492caa6 "#1"
308 308 rebasing 4:07d6153b5c04 "#4" (tip)
309 309
310 310 $ hg status -A large1
311 311 large1: $ENOENT$
312 312
313 313 $ hg status -A largeX
314 314 C largeX
315 315 $ hg strip -q 5
316 316
317 317 $ hg update -q -C 2
318 318 $ hg transplant -q 1 4
319 319
320 320 $ hg status -A large1
321 321 large1: $ENOENT$
322 322
323 323 $ hg status -A largeX
324 324 C largeX
325 325 $ hg strip -q 5
326 326
327 327 $ hg update -q -C 2
328 328 $ hg transplant -q --merge 1 --merge 4
329 329
330 330 $ hg status -A large1
331 331 large1: $ENOENT$
332 332
333 333 $ hg status -A largeX
334 334 C largeX
335 335 $ hg strip -q 5
336 336
337 337 Test that linear merge can detect modification (and conflict) correctly
338 338
339 339 (linear merge without conflict)
340 340
341 341 $ echo 'large2 for linear merge (no conflict)' > large2
342 342 $ hg update 3 --config debug.dirstate.delaywrite=2
343 343 getting changed largefiles
344 344 1 largefiles updated, 0 removed
345 345 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
346 346 $ hg status -A large2
347 347 M large2
348 348 $ cat large2
349 349 large2 for linear merge (no conflict)
350 350 $ cat .hglf/large2
351 351 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
352 352
353 353 (linear merge with conflict, choosing "other")
354 354
355 355 $ hg update -q -C 2
356 356 $ echo 'large1 for linear merge (conflict)' > large1
357 357 $ hg update 3 --config ui.interactive=True <<EOF
358 358 > o
359 359 > EOF
360 360 largefile large1 has a merge conflict
361 361 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
362 362 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
363 363 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? o
364 364 getting changed largefiles
365 365 1 largefiles updated, 0 removed
366 366 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
367 367 $ hg status -A large1
368 368 C large1
369 369 $ cat large1
370 370 large1 in #3
371 371 $ cat .hglf/large1
372 372 e5bb990443d6a92aaf7223813720f7566c9dd05b
373 373
374 374 (linear merge with conflict, choosing "local")
375 375
376 376 $ hg update -q -C 2
377 377 $ echo 'large1 for linear merge (conflict)' > large1
378 378 $ hg update 3 --config debug.dirstate.delaywrite=2
379 379 largefile large1 has a merge conflict
380 380 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
381 381 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
382 382 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
383 383 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
384 384 $ hg status -A large1
385 385 M large1
386 386 $ cat large1
387 387 large1 for linear merge (conflict)
388 388 $ cat .hglf/large1
389 389 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
390 390
391 391 Test a linear merge to a revision containing same-name normal file
392 392
393 393 $ hg update -q -C 3
394 394 $ hg remove large2
395 395 $ echo 'large2 as normal file' > large2
396 396 $ hg add large2
397 397 $ echo 'large3 as normal file' > large3
398 398 $ hg add large3
399 399 $ hg commit -m '#5'
400 400 $ hg manifest
401 401 .hglf/large1
402 402 large2
403 403 large3
404 404 normal1
405 405
406 406 (modified largefile is already switched to normal)
407 407
408 408 $ hg update -q -C 2
409 409 $ echo 'modified large2 for linear merge' > large2
410 410 $ hg update -q 5
411 411 remote turned local largefile large2 into a normal file
412 412 keep (l)argefile or use (n)ormal file? l
413 413 $ hg debugdirstate --nodates | grep large2
414 414 a 0 -1 unset .hglf/large2
415 415 r 0 0 set large2
416 416 $ hg status -A large2
417 417 A large2
418 418 $ cat large2
419 419 modified large2 for linear merge
420 420
421 421 (added largefile is already committed as normal)
422 422
423 423 $ hg update -q -C 2
424 424 $ echo 'large3 as large file for linear merge' > large3
425 425 $ hg add --large large3
426 426 $ hg update -q 5
427 427 remote turned local largefile large3 into a normal file
428 428 keep (l)argefile or use (n)ormal file? l
429 429 $ hg debugdirstate --nodates | grep large3
430 430 a 0 -1 unset .hglf/large3
431 431 r 0 0 set large3
432 432 $ hg status -A large3
433 433 A large3
434 434 $ cat large3
435 435 large3 as large file for linear merge
436 436 $ rm -f large3 .hglf/large3
437 437
438 438 Test that the internal linear merging works correctly
439 439 (both heads are stripped to keep pairing of revision number and commit log)
440 440
441 441 $ hg update -q -C 2
442 442 $ hg strip 3 4
443 443 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-2e7b195d-backup.hg
444 444 $ mv .hg/strip-backup/9530e27857f7-2e7b195d-backup.hg $TESTTMP
445 445
446 446 (internal linear merging at "hg pull --update")
447 447
448 448 $ echo 'large1 for linear merge (conflict)' > large1
449 449 $ echo 'large2 for linear merge (conflict with normal file)' > large2
450 450 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
451 451 pulling from $TESTTMP/9530e27857f7-2e7b195d-backup.hg
452 452 searching for changes
453 453 adding changesets
454 454 adding manifests
455 455 adding file changes
456 456 added 3 changesets with 5 changes to 5 files
457 457 new changesets 9530e27857f7:d65e59e952a9
458 458 remote turned local largefile large2 into a normal file
459 459 keep (l)argefile or use (n)ormal file? l
460 460 largefile large1 has a merge conflict
461 461 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
462 462 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
463 463 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
464 464 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
465 465 updated to "d65e59e952a9: #5"
466 466 1 other heads for branch "default"
467 467
468 468 $ hg status -A large1
469 469 M large1
470 470 $ cat large1
471 471 large1 for linear merge (conflict)
472 472 $ cat .hglf/large1
473 473 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
474 474 $ hg status -A large2
475 475 A large2
476 476 $ cat large2
477 477 large2 for linear merge (conflict with normal file)
478 478 $ cat .hglf/large2
479 479 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
480 480
481 481 (internal linear merging at "hg unbundle --update")
482 482
483 483 $ hg update -q -C 2
484 484 $ hg rollback -q
485 485
486 486 $ echo 'large1 for linear merge (conflict)' > large1
487 487 $ echo 'large2 for linear merge (conflict with normal file)' > large2
488 488 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-2e7b195d-backup.hg
489 489 adding changesets
490 490 adding manifests
491 491 adding file changes
492 492 added 3 changesets with 5 changes to 5 files
493 493 new changesets 9530e27857f7:d65e59e952a9
494 494 remote turned local largefile large2 into a normal file
495 495 keep (l)argefile or use (n)ormal file? l
496 496 largefile large1 has a merge conflict
497 497 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
498 498 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
499 499 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
500 500 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
501 501 updated to "d65e59e952a9: #5"
502 502 1 other heads for branch "default"
503 503
504 504 $ hg status -A large1
505 505 M large1
506 506 $ cat large1
507 507 large1 for linear merge (conflict)
508 508 $ cat .hglf/large1
509 509 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
510 510 $ hg status -A large2
511 511 A large2
512 512 $ cat large2
513 513 large2 for linear merge (conflict with normal file)
514 514 $ cat .hglf/large2
515 515 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
516 516
517 517 (internal linear merging in subrepo at "hg update")
518 518
519 519 $ cd ..
520 520 $ hg init subparent
521 521 $ cd subparent
522 522
523 523 $ hg clone -q -u 2 ../repo sub
524 524 $ cat > .hgsub <<EOF
525 525 > sub = sub
526 526 > EOF
527 527 $ hg add .hgsub
528 528 $ hg commit -m '#0@parent'
529 529 $ cat .hgsubstate
530 530 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
531 531 $ hg -R sub update -q
532 532 $ hg commit -m '#1@parent'
533 533 $ cat .hgsubstate
534 534 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
535 535 $ hg update -q 0
536 536
537 537 $ echo 'large1 for linear merge (conflict)' > sub/large1
538 538 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
539 539 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
540 540 > m
541 541 > r
542 542 > l
543 543 > l
544 544 > EOF
545 545 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
546 546 (M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
547 547 subrepository sources for sub differ (in checked out version)
548 548 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
549 549 remote turned local largefile large2 into a normal file
550 550 keep (l)argefile or use (n)ormal file? l
551 551 largefile large1 has a merge conflict
552 552 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
553 553 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
554 554 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
555 555 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
556 556 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 557
558 558 $ hg -R sub status -A sub/large1
559 559 M sub/large1
560 560 $ cat sub/large1
561 561 large1 for linear merge (conflict)
562 562 $ cat sub/.hglf/large1
563 563 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
564 564 $ hg -R sub status -A sub/large2
565 565 A sub/large2
566 566 $ cat sub/large2
567 567 large2 for linear merge (conflict with normal file)
568 568 $ cat sub/.hglf/large2
569 569 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
570 570
571 571 $ cd ..
572 572 $ cd repo
573 573
574 574 Test that rebase updates largefiles in the working directory even if
575 575 it is aborted by conflict.
576 576
577 577 $ hg update -q -C 3
578 578 $ cat .hglf/large1
579 579 e5bb990443d6a92aaf7223813720f7566c9dd05b
580 580 $ cat large1
581 581 large1 in #3
582 582 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
583 583 > o
584 584 > EOF
585 585 rebasing 1:72518492caa6 "#1"
586 586 largefile large1 has a merge conflict
587 587 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
588 588 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
589 589 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
590 590 merging normal1
591 591 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark')
592 592 unresolved conflicts (see hg resolve, then hg rebase --continue)
593 593 [1]
594 594 $ cat .hglf/large1
595 595 58e24f733a964da346e2407a2bee99d9001184f5
596 596 $ cat large1
597 597 large1 in #1
598 598 $ rm normal1.orig
599 599
600 600 Test that rebase updates standins for manually modified largefiles at
601 601 the 1st commit of resuming.
602 602
603 603 $ echo "manually modified before 'hg rebase --continue'" > large1
604 604 $ hg resolve -m normal1
605 605 (no more unresolved files)
606 606 continue: hg rebase --continue
607 607 $ hg rebase --continue --config ui.interactive=True <<EOF
608 608 > c
609 609 > EOF
610 610 rebasing 1:72518492caa6 "#1"
611 611 rebasing 4:07d6153b5c04 "#4"
612 612 local [dest] changed .hglf/large1 which other [source] deleted
613 613 use (c)hanged version, (d)elete, or leave (u)nresolved? c
614 614
615 615 $ hg diff -c "tip~1" --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
616 616 -e5bb990443d6a92aaf7223813720f7566c9dd05b
617 617 +8a4f783556e7dea21139ca0466eafce954c75c13
618 618 $ rm -f large1
619 619 $ hg update -q -C tip
620 620 $ cat large1
621 621 manually modified before 'hg rebase --continue'
622 622
623 623 Test that transplant updates largefiles, of which standins are safely
624 624 changed, even if it is aborted by conflict of other.
625 625
626 626 $ hg update -q -C 5
627 627 $ cat .hglf/large1
628 628 e5bb990443d6a92aaf7223813720f7566c9dd05b
629 629 $ cat large1
630 630 large1 in #3
631 631 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
632 632 +fa44618ea25181aff4f48b70428294790cec9f61
633 633 $ hg transplant 4
634 634 applying 07d6153b5c04
635 635 patching file .hglf/large1
636 636 Hunk #1 FAILED at 0
637 637 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
638 638 patch failed to apply
639 639 abort: fix up the working directory and run hg transplant --continue
640 640 [255]
641 641 $ hg status -A large1
642 642 C large1
643 643 $ cat .hglf/large1
644 644 e5bb990443d6a92aaf7223813720f7566c9dd05b
645 645 $ cat large1
646 646 large1 in #3
647 647 $ hg status -A largeX
648 648 A largeX
649 649 $ cat .hglf/largeX
650 650 fa44618ea25181aff4f48b70428294790cec9f61
651 651 $ cat largeX
652 652 largeX
653 653
654 654 Test that transplant updates standins for manually modified largefiles
655 655 at the 1st commit of resuming.
656 656
657 657 $ echo "manually modified before 'hg transplant --continue'" > large1
658 658 $ hg transplant --continue
659 659 07d6153b5c04 transplanted as f1bf30eb88cc
660 660 $ hg diff -c tip .hglf/large1 | grep '^[+-][0-9a-z]'
661 661 -e5bb990443d6a92aaf7223813720f7566c9dd05b
662 662 +6a4f36d4075fbe0f30ec1d26ca44e63c05903671
663 663 $ rm -f large1
664 664 $ hg update -q -C tip
665 665 $ cat large1
666 666 manually modified before 'hg transplant --continue'
667 667
668 668 Test that "hg status" doesn't show removal of largefiles not managed
669 669 in the target context.
670 670
671 671 $ hg update -q -C 4
672 672 $ hg remove largeX
673 673 $ hg status -A largeX
674 674 R largeX
675 675 $ hg status -A --rev '.^1' largeX
676 676
677 677 #if execbit
678 678
679 679 Test that "hg status" against revisions other than parent notices exec
680 680 bit changes of largefiles.
681 681
682 682 $ hg update -q -C 4
683 683
684 684 (the case that large2 doesn't have exec bit in the target context but
685 685 in the working context)
686 686
687 687 $ chmod +x large2
688 688 $ hg status -A --rev 0 large2
689 689 M large2
690 690 $ hg commit -m 'chmod +x large2'
691 691
692 692 (the case that large2 has exec bit in the target context but not in
693 693 the working context)
694 694
695 695 $ echo dummy > dummy
696 696 $ hg add dummy
697 697 $ hg commit -m 'revision for separation'
698 698 $ chmod -x large2
699 699 $ hg status -A --rev '.^1' large2
700 700 M large2
701 701
702 702 #else
703 703
704 704 Test that "hg status" against revisions other than parent ignores exec
705 705 bit correctly on the platform being unaware of it.
706 706
707 707 $ hg update -q -C 4
708 708
709 709 $ cat > ../exec-bit.patch <<EOF
710 710 > # HG changeset patch
711 711 > # User test
712 712 > # Date 0 0
713 713 > # Thu Jan 01 00:00:00 1970 +0000
714 714 > # Node ID be1b433a65b12b27b5519d92213e14f7e1769b90
715 715 > # Parent 07d6153b5c04313efb75deec9ba577de7faeb727
716 716 > chmod +x large2
717 717 >
718 718 > diff --git a/.hglf/large2 b/.hglf/large2
719 719 > old mode 100644
720 720 > new mode 100755
721 721 > EOF
722 722 $ hg import --exact --bypass ../exec-bit.patch
723 723 applying ../exec-bit.patch
724 724 $ hg status -A --rev tip large2
725 725 C large2
726 726
727 727 #endif
728 728
729 The fileset revset is evaluated for each revision, instead of once on wdir(),
730 and then patterns matched on each revision. Here, no exec bits are set in
731 wdir(), but a matching revision is detected.
732
733 (Teach large2 is not an executable. Maybe this is a bug of largefiles.)
734 #if execbit
735 $ chmod -x .hglf/large2
736 #endif
737
738 $ hg files 'set:exec()'
739 [1]
740 $ hg log -qr 'file("set:exec()")'
741 9:be1b433a65b1
742
729 743 Test a fatal error interrupting an update. Verify that status report dirty
730 744 files correctly after an interrupted update. Also verify that checking all
731 745 hashes reveals it isn't clean.
732 746
733 747 Start with clean dirstates:
734 748 $ hg up --quiet --clean --rev "8^"
735 749 $ sleep 1
736 750 $ hg st
737 751 Update standins without updating largefiles - large1 is modified and largeX is
738 752 added:
739 753 $ cat << EOF > ../crashupdatelfiles.py
740 754 > import hgext.largefiles.lfutil
741 755 > def getlfilestoupdate(oldstandins, newstandins):
742 756 > raise SystemExit(7)
743 757 > hgext.largefiles.lfutil.getlfilestoupdate = getlfilestoupdate
744 758 > EOF
745 759 $ hg up -Cr "8" --config extensions.crashupdatelfiles=../crashupdatelfiles.py
746 760 [7]
747 761 Check large1 content and status ... and that update will undo modifications:
748 762 $ cat large1
749 763 large1 in #3
750 764 $ hg st
751 765 M large1
752 766 ! largeX
753 767 $ hg up -Cr .
754 768 getting changed largefiles
755 769 2 largefiles updated, 0 removed
756 770 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
757 771 $ cat large1
758 772 manually modified before 'hg transplant --continue'
759 773 $ hg st
760 774 Force largefiles rehashing and check that all changes have been caught by
761 775 status and update:
762 776 $ rm .hg/largefiles/dirstate
763 777 $ hg st
764 778
765 779 $ cd ..
766 780
767 781 Test that "hg convert" avoids copying largefiles from the working
768 782 directory into store, because "hg convert" doesn't update largefiles
769 783 in the working directory (removing files under ".cache/largefiles"
770 784 forces "hg convert" to copy corresponding largefiles)
771 785
772 786 $ cat >> $HGRCPATH <<EOF
773 787 > [extensions]
774 788 > convert =
775 789 > EOF
776 790
777 791 $ rm $TESTTMP/.cache/largefiles/6a4f36d4075fbe0f30ec1d26ca44e63c05903671
778 792 $ hg convert -q repo repo.converted
General Comments 0
You need to be logged in to leave comments. Login now