##// END OF EJS Templates
merge with stable
Yuya Nishihara -
r46030:4532e7eb merge default
parent child Browse files
Show More
@@ -1,82 +1,83 b''
1 # hgdemandimport - global demand-loading of modules for Mercurial
1 # hgdemandimport - global demand-loading of modules for Mercurial
2 #
2 #
3 # Copyright 2017 Facebook Inc.
3 # Copyright 2017 Facebook Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''demandimport - automatic demand-loading of modules'''
8 '''demandimport - automatic demand-loading of modules'''
9
9
10 # This is in a separate package from mercurial because in Python 3,
10 # This is in a separate package from mercurial because in Python 3,
11 # demand loading is per-package. Keeping demandimport in the mercurial package
11 # demand loading is per-package. Keeping demandimport in the mercurial package
12 # would disable demand loading for any modules in mercurial.
12 # would disable demand loading for any modules in mercurial.
13
13
14 from __future__ import absolute_import
14 from __future__ import absolute_import
15
15
16 import os
16 import os
17 import sys
17 import sys
18
18
19 if sys.version_info[0] >= 3:
19 if sys.version_info[0] >= 3:
20 from . import demandimportpy3 as demandimport
20 from . import demandimportpy3 as demandimport
21 else:
21 else:
22 from . import demandimportpy2 as demandimport
22 from . import demandimportpy2 as demandimport
23
23
24 # Full module names which can't be lazy imported.
24 # Full module names which can't be lazy imported.
25 # Extensions can add to this set.
25 # Extensions can add to this set.
26 IGNORES = {
26 IGNORES = {
27 '__future__',
27 '__future__',
28 '_hashlib',
28 '_hashlib',
29 # ImportError during pkg_resources/__init__.py:fixup_namespace_package
29 # ImportError during pkg_resources/__init__.py:fixup_namespace_package
30 '_imp',
30 '_imp',
31 '_xmlplus',
31 '_xmlplus',
32 'fcntl',
32 'fcntl',
33 'nt', # pathlib2 tests the existence of built-in 'nt' module
33 'nt', # pathlib2 tests the existence of built-in 'nt' module
34 'win32com.gen_py',
34 'win32com.gen_py',
35 'win32com.shell', # 'appdirs' tries to import win32com.shell
35 'win32com.shell', # 'appdirs' tries to import win32com.shell
36 '_winreg', # 2.7 mimetypes needs immediate ImportError
36 '_winreg', # 2.7 mimetypes needs immediate ImportError
37 'pythoncom',
37 'pythoncom',
38 # imported by tarfile, not available under Windows
38 # imported by tarfile, not available under Windows
39 'pwd',
39 'pwd',
40 'grp',
40 'grp',
41 # imported by profile, itself imported by hotshot.stats,
41 # imported by profile, itself imported by hotshot.stats,
42 # not available under Windows
42 # not available under Windows
43 'resource',
43 'resource',
44 # this trips up many extension authors
44 # this trips up many extension authors
45 'gtk',
45 'gtk',
46 # setuptools' pkg_resources.py expects "from __main__ import x" to
46 # setuptools' pkg_resources.py expects "from __main__ import x" to
47 # raise ImportError if x not defined
47 # raise ImportError if x not defined
48 '__main__',
48 '__main__',
49 '_ast', # https://bugs.python.org/issue41631
49 '_ssl', # conditional imports in the stdlib, issue1964
50 '_ssl', # conditional imports in the stdlib, issue1964
50 '_sre', # issue4920
51 '_sre', # issue4920
51 'rfc822',
52 'rfc822',
52 'mimetools',
53 'mimetools',
53 'sqlalchemy.events', # has import-time side effects (issue5085)
54 'sqlalchemy.events', # has import-time side effects (issue5085)
54 # setuptools 8 expects this module to explode early when not on windows
55 # setuptools 8 expects this module to explode early when not on windows
55 'distutils.msvc9compiler',
56 'distutils.msvc9compiler',
56 '__builtin__',
57 '__builtin__',
57 'builtins',
58 'builtins',
58 'urwid.command_map', # for pudb
59 'urwid.command_map', # for pudb
59 'lzma',
60 'lzma',
60 }
61 }
61
62
62 _pypy = '__pypy__' in sys.builtin_module_names
63 _pypy = '__pypy__' in sys.builtin_module_names
63
64
64 if _pypy:
65 if _pypy:
65 # _ctypes.pointer is shadowed by "from ... import pointer" (PyPy 5)
66 # _ctypes.pointer is shadowed by "from ... import pointer" (PyPy 5)
66 IGNORES.add('_ctypes.pointer')
67 IGNORES.add('_ctypes.pointer')
67
68
68 demandimport.init(IGNORES)
69 demandimport.init(IGNORES)
69
70
70 # Re-export.
71 # Re-export.
71 isenabled = demandimport.isenabled
72 isenabled = demandimport.isenabled
72 disable = demandimport.disable
73 disable = demandimport.disable
73 deactivated = demandimport.deactivated
74 deactivated = demandimport.deactivated
74
75
75
76
76 def enable():
77 def enable():
77 # chg pre-imports modules so do not enable demandimport for it
78 # chg pre-imports modules so do not enable demandimport for it
78 if (
79 if (
79 'CHGINTERNALMARK' not in os.environ
80 'CHGINTERNALMARK' not in os.environ
80 and os.environ.get('HGDEMANDIMPORT') != 'disable'
81 and os.environ.get('HGDEMANDIMPORT') != 'disable'
81 ):
82 ):
82 demandimport.enable()
83 demandimport.enable()
@@ -1,1113 +1,1114 b''
1 # dagop.py - graph ancestry and topology algorithm for revset
1 # dagop.py - graph ancestry and topology algorithm for revset
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import heapq
10 import heapq
11
11
12 from .node import nullrev
12 from .node import nullrev
13 from .thirdparty import attr
13 from .thirdparty import attr
14 from . import (
14 from . import (
15 error,
15 error,
16 mdiff,
16 mdiff,
17 node,
17 node,
18 patch,
18 patch,
19 pycompat,
19 pycompat,
20 scmutil,
20 smartset,
21 smartset,
21 )
22 )
22
23
23 baseset = smartset.baseset
24 baseset = smartset.baseset
24 generatorset = smartset.generatorset
25 generatorset = smartset.generatorset
25
26
26 # possible maximum depth between null and wdir()
27 # possible maximum depth between null and wdir()
27 maxlogdepth = 0x80000000
28 maxlogdepth = 0x80000000
28
29
29
30
30 def _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse):
31 def _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse):
31 """Walk DAG using 'pfunc' from the given 'revs' nodes
32 """Walk DAG using 'pfunc' from the given 'revs' nodes
32
33
33 'pfunc(rev)' should return the parent/child revisions of the given 'rev'
34 'pfunc(rev)' should return the parent/child revisions of the given 'rev'
34 if 'reverse' is True/False respectively.
35 if 'reverse' is True/False respectively.
35
36
36 Scan ends at the stopdepth (exlusive) if specified. Revisions found
37 Scan ends at the stopdepth (exlusive) if specified. Revisions found
37 earlier than the startdepth are omitted.
38 earlier than the startdepth are omitted.
38 """
39 """
39 if startdepth is None:
40 if startdepth is None:
40 startdepth = 0
41 startdepth = 0
41 if stopdepth is None:
42 if stopdepth is None:
42 stopdepth = maxlogdepth
43 stopdepth = maxlogdepth
43 if stopdepth == 0:
44 if stopdepth == 0:
44 return
45 return
45 if stopdepth < 0:
46 if stopdepth < 0:
46 raise error.ProgrammingError(b'negative stopdepth')
47 raise error.ProgrammingError(b'negative stopdepth')
47 if reverse:
48 if reverse:
48 heapsign = -1 # max heap
49 heapsign = -1 # max heap
49 else:
50 else:
50 heapsign = +1 # min heap
51 heapsign = +1 # min heap
51
52
52 # load input revs lazily to heap so earlier revisions can be yielded
53 # load input revs lazily to heap so earlier revisions can be yielded
53 # without fully computing the input revs
54 # without fully computing the input revs
54 revs.sort(reverse)
55 revs.sort(reverse)
55 irevs = iter(revs)
56 irevs = iter(revs)
56 pendingheap = [] # [(heapsign * rev, depth), ...] (i.e. lower depth first)
57 pendingheap = [] # [(heapsign * rev, depth), ...] (i.e. lower depth first)
57
58
58 inputrev = next(irevs, None)
59 inputrev = next(irevs, None)
59 if inputrev is not None:
60 if inputrev is not None:
60 heapq.heappush(pendingheap, (heapsign * inputrev, 0))
61 heapq.heappush(pendingheap, (heapsign * inputrev, 0))
61
62
62 lastrev = None
63 lastrev = None
63 while pendingheap:
64 while pendingheap:
64 currev, curdepth = heapq.heappop(pendingheap)
65 currev, curdepth = heapq.heappop(pendingheap)
65 currev = heapsign * currev
66 currev = heapsign * currev
66 if currev == inputrev:
67 if currev == inputrev:
67 inputrev = next(irevs, None)
68 inputrev = next(irevs, None)
68 if inputrev is not None:
69 if inputrev is not None:
69 heapq.heappush(pendingheap, (heapsign * inputrev, 0))
70 heapq.heappush(pendingheap, (heapsign * inputrev, 0))
70 # rescan parents until curdepth >= startdepth because queued entries
71 # rescan parents until curdepth >= startdepth because queued entries
71 # of the same revision are iterated from the lowest depth
72 # of the same revision are iterated from the lowest depth
72 foundnew = currev != lastrev
73 foundnew = currev != lastrev
73 if foundnew and curdepth >= startdepth:
74 if foundnew and curdepth >= startdepth:
74 lastrev = currev
75 lastrev = currev
75 yield currev
76 yield currev
76 pdepth = curdepth + 1
77 pdepth = curdepth + 1
77 if foundnew and pdepth < stopdepth:
78 if foundnew and pdepth < stopdepth:
78 for prev in pfunc(currev):
79 for prev in pfunc(currev):
79 if prev != node.nullrev:
80 if prev != node.nullrev:
80 heapq.heappush(pendingheap, (heapsign * prev, pdepth))
81 heapq.heappush(pendingheap, (heapsign * prev, pdepth))
81
82
82
83
83 def filectxancestors(fctxs, followfirst=False):
84 def filectxancestors(fctxs, followfirst=False):
84 """Like filectx.ancestors(), but can walk from multiple files/revisions,
85 """Like filectx.ancestors(), but can walk from multiple files/revisions,
85 and includes the given fctxs themselves
86 and includes the given fctxs themselves
86
87
87 Yields (rev, {fctx, ...}) pairs in descending order.
88 Yields (rev, {fctx, ...}) pairs in descending order.
88 """
89 """
89 visit = {}
90 visit = {}
90 visitheap = []
91 visitheap = []
91
92
92 def addvisit(fctx):
93 def addvisit(fctx):
93 rev = fctx.rev()
94 rev = scmutil.intrev(fctx)
94 if rev not in visit:
95 if rev not in visit:
95 visit[rev] = set()
96 visit[rev] = set()
96 heapq.heappush(visitheap, -rev) # max heap
97 heapq.heappush(visitheap, -rev) # max heap
97 visit[rev].add(fctx)
98 visit[rev].add(fctx)
98
99
99 if followfirst:
100 if followfirst:
100 cut = 1
101 cut = 1
101 else:
102 else:
102 cut = None
103 cut = None
103
104
104 for c in fctxs:
105 for c in fctxs:
105 addvisit(c)
106 addvisit(c)
106 while visit:
107 while visit:
107 currev = -(heapq.heappop(visitheap))
108 currev = -(heapq.heappop(visitheap))
108 curfctxs = visit.pop(currev)
109 curfctxs = visit.pop(currev)
109 yield currev, curfctxs
110 yield currev, curfctxs
110 for c in curfctxs:
111 for c in curfctxs:
111 for parent in c.parents()[:cut]:
112 for parent in c.parents()[:cut]:
112 addvisit(parent)
113 addvisit(parent)
113 assert not visitheap
114 assert not visitheap
114
115
115
116
116 def filerevancestors(fctxs, followfirst=False):
117 def filerevancestors(fctxs, followfirst=False):
117 """Like filectx.ancestors(), but can walk from multiple files/revisions,
118 """Like filectx.ancestors(), but can walk from multiple files/revisions,
118 and includes the given fctxs themselves
119 and includes the given fctxs themselves
119
120
120 Returns a smartset.
121 Returns a smartset.
121 """
122 """
122 gen = (rev for rev, _cs in filectxancestors(fctxs, followfirst))
123 gen = (rev for rev, _cs in filectxancestors(fctxs, followfirst))
123 return generatorset(gen, iterasc=False)
124 return generatorset(gen, iterasc=False)
124
125
125
126
126 def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth, cutfunc):
127 def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth, cutfunc):
127 if followfirst:
128 if followfirst:
128 cut = 1
129 cut = 1
129 else:
130 else:
130 cut = None
131 cut = None
131 cl = repo.changelog
132 cl = repo.changelog
132
133
133 def plainpfunc(rev):
134 def plainpfunc(rev):
134 try:
135 try:
135 return cl.parentrevs(rev)[:cut]
136 return cl.parentrevs(rev)[:cut]
136 except error.WdirUnsupported:
137 except error.WdirUnsupported:
137 return (pctx.rev() for pctx in repo[rev].parents()[:cut])
138 return (pctx.rev() for pctx in repo[rev].parents()[:cut])
138
139
139 if cutfunc is None:
140 if cutfunc is None:
140 pfunc = plainpfunc
141 pfunc = plainpfunc
141 else:
142 else:
142 pfunc = lambda rev: [r for r in plainpfunc(rev) if not cutfunc(r)]
143 pfunc = lambda rev: [r for r in plainpfunc(rev) if not cutfunc(r)]
143 revs = revs.filter(lambda rev: not cutfunc(rev))
144 revs = revs.filter(lambda rev: not cutfunc(rev))
144 return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
145 return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
145
146
146
147
147 def revancestors(
148 def revancestors(
148 repo, revs, followfirst=False, startdepth=None, stopdepth=None, cutfunc=None
149 repo, revs, followfirst=False, startdepth=None, stopdepth=None, cutfunc=None
149 ):
150 ):
150 r"""Like revlog.ancestors(), but supports additional options, includes
151 r"""Like revlog.ancestors(), but supports additional options, includes
151 the given revs themselves, and returns a smartset
152 the given revs themselves, and returns a smartset
152
153
153 Scan ends at the stopdepth (exlusive) if specified. Revisions found
154 Scan ends at the stopdepth (exlusive) if specified. Revisions found
154 earlier than the startdepth are omitted.
155 earlier than the startdepth are omitted.
155
156
156 If cutfunc is provided, it will be used to cut the traversal of the DAG.
157 If cutfunc is provided, it will be used to cut the traversal of the DAG.
157 When cutfunc(X) returns True, the DAG traversal stops - revision X and
158 When cutfunc(X) returns True, the DAG traversal stops - revision X and
158 X's ancestors in the traversal path will be skipped. This could be an
159 X's ancestors in the traversal path will be skipped. This could be an
159 optimization sometimes.
160 optimization sometimes.
160
161
161 Note: if Y is an ancestor of X, cutfunc(X) returning True does not
162 Note: if Y is an ancestor of X, cutfunc(X) returning True does not
162 necessarily mean Y will also be cut. Usually cutfunc(Y) also wants to
163 necessarily mean Y will also be cut. Usually cutfunc(Y) also wants to
163 return True in this case. For example,
164 return True in this case. For example,
164
165
165 D # revancestors(repo, D, cutfunc=lambda rev: rev == B)
166 D # revancestors(repo, D, cutfunc=lambda rev: rev == B)
166 |\ # will include "A", because the path D -> C -> A was not cut.
167 |\ # will include "A", because the path D -> C -> A was not cut.
167 B C # If "B" gets cut, "A" might want to be cut too.
168 B C # If "B" gets cut, "A" might want to be cut too.
168 |/
169 |/
169 A
170 A
170 """
171 """
171 gen = _genrevancestors(
172 gen = _genrevancestors(
172 repo, revs, followfirst, startdepth, stopdepth, cutfunc
173 repo, revs, followfirst, startdepth, stopdepth, cutfunc
173 )
174 )
174 return generatorset(gen, iterasc=False)
175 return generatorset(gen, iterasc=False)
175
176
176
177
177 def _genrevdescendants(repo, revs, followfirst):
178 def _genrevdescendants(repo, revs, followfirst):
178 if followfirst:
179 if followfirst:
179 cut = 1
180 cut = 1
180 else:
181 else:
181 cut = None
182 cut = None
182
183
183 cl = repo.changelog
184 cl = repo.changelog
184 first = revs.min()
185 first = revs.min()
185 nullrev = node.nullrev
186 nullrev = node.nullrev
186 if first == nullrev:
187 if first == nullrev:
187 # Are there nodes with a null first parent and a non-null
188 # Are there nodes with a null first parent and a non-null
188 # second one? Maybe. Do we care? Probably not.
189 # second one? Maybe. Do we care? Probably not.
189 yield first
190 yield first
190 for i in cl:
191 for i in cl:
191 yield i
192 yield i
192 else:
193 else:
193 seen = set(revs)
194 seen = set(revs)
194 for i in cl.revs(first):
195 for i in cl.revs(first):
195 if i in seen:
196 if i in seen:
196 yield i
197 yield i
197 continue
198 continue
198 for x in cl.parentrevs(i)[:cut]:
199 for x in cl.parentrevs(i)[:cut]:
199 if x != nullrev and x in seen:
200 if x != nullrev and x in seen:
200 seen.add(i)
201 seen.add(i)
201 yield i
202 yield i
202 break
203 break
203
204
204
205
205 def _builddescendantsmap(repo, startrev, followfirst):
206 def _builddescendantsmap(repo, startrev, followfirst):
206 """Build map of 'rev -> child revs', offset from startrev"""
207 """Build map of 'rev -> child revs', offset from startrev"""
207 cl = repo.changelog
208 cl = repo.changelog
208 nullrev = node.nullrev
209 nullrev = node.nullrev
209 descmap = [[] for _rev in pycompat.xrange(startrev, len(cl))]
210 descmap = [[] for _rev in pycompat.xrange(startrev, len(cl))]
210 for currev in cl.revs(startrev + 1):
211 for currev in cl.revs(startrev + 1):
211 p1rev, p2rev = cl.parentrevs(currev)
212 p1rev, p2rev = cl.parentrevs(currev)
212 if p1rev >= startrev:
213 if p1rev >= startrev:
213 descmap[p1rev - startrev].append(currev)
214 descmap[p1rev - startrev].append(currev)
214 if not followfirst and p2rev != nullrev and p2rev >= startrev:
215 if not followfirst and p2rev != nullrev and p2rev >= startrev:
215 descmap[p2rev - startrev].append(currev)
216 descmap[p2rev - startrev].append(currev)
216 return descmap
217 return descmap
217
218
218
219
219 def _genrevdescendantsofdepth(repo, revs, followfirst, startdepth, stopdepth):
220 def _genrevdescendantsofdepth(repo, revs, followfirst, startdepth, stopdepth):
220 startrev = revs.min()
221 startrev = revs.min()
221 descmap = _builddescendantsmap(repo, startrev, followfirst)
222 descmap = _builddescendantsmap(repo, startrev, followfirst)
222
223
223 def pfunc(rev):
224 def pfunc(rev):
224 return descmap[rev - startrev]
225 return descmap[rev - startrev]
225
226
226 return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=False)
227 return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=False)
227
228
228
229
229 def revdescendants(repo, revs, followfirst, startdepth=None, stopdepth=None):
230 def revdescendants(repo, revs, followfirst, startdepth=None, stopdepth=None):
230 """Like revlog.descendants() but supports additional options, includes
231 """Like revlog.descendants() but supports additional options, includes
231 the given revs themselves, and returns a smartset
232 the given revs themselves, and returns a smartset
232
233
233 Scan ends at the stopdepth (exlusive) if specified. Revisions found
234 Scan ends at the stopdepth (exlusive) if specified. Revisions found
234 earlier than the startdepth are omitted.
235 earlier than the startdepth are omitted.
235 """
236 """
236 if startdepth is None and (stopdepth is None or stopdepth >= maxlogdepth):
237 if startdepth is None and (stopdepth is None or stopdepth >= maxlogdepth):
237 gen = _genrevdescendants(repo, revs, followfirst)
238 gen = _genrevdescendants(repo, revs, followfirst)
238 else:
239 else:
239 gen = _genrevdescendantsofdepth(
240 gen = _genrevdescendantsofdepth(
240 repo, revs, followfirst, startdepth, stopdepth
241 repo, revs, followfirst, startdepth, stopdepth
241 )
242 )
242 return generatorset(gen, iterasc=True)
243 return generatorset(gen, iterasc=True)
243
244
244
245
245 def descendantrevs(revs, revsfn, parentrevsfn):
246 def descendantrevs(revs, revsfn, parentrevsfn):
246 """Generate revision number descendants in revision order.
247 """Generate revision number descendants in revision order.
247
248
248 Yields revision numbers starting with a child of some rev in
249 Yields revision numbers starting with a child of some rev in
249 ``revs``. Results are ordered by revision number and are
250 ``revs``. Results are ordered by revision number and are
250 therefore topological. Each revision is not considered a descendant
251 therefore topological. Each revision is not considered a descendant
251 of itself.
252 of itself.
252
253
253 ``revsfn`` is a callable that with no argument iterates over all
254 ``revsfn`` is a callable that with no argument iterates over all
254 revision numbers and with a ``start`` argument iterates over revision
255 revision numbers and with a ``start`` argument iterates over revision
255 numbers beginning with that value.
256 numbers beginning with that value.
256
257
257 ``parentrevsfn`` is a callable that receives a revision number and
258 ``parentrevsfn`` is a callable that receives a revision number and
258 returns an iterable of parent revision numbers, whose values may include
259 returns an iterable of parent revision numbers, whose values may include
259 nullrev.
260 nullrev.
260 """
261 """
261 first = min(revs)
262 first = min(revs)
262
263
263 if first == nullrev:
264 if first == nullrev:
264 for rev in revsfn():
265 for rev in revsfn():
265 yield rev
266 yield rev
266 return
267 return
267
268
268 seen = set(revs)
269 seen = set(revs)
269 for rev in revsfn(start=first + 1):
270 for rev in revsfn(start=first + 1):
270 for prev in parentrevsfn(rev):
271 for prev in parentrevsfn(rev):
271 if prev != nullrev and prev in seen:
272 if prev != nullrev and prev in seen:
272 seen.add(rev)
273 seen.add(rev)
273 yield rev
274 yield rev
274 break
275 break
275
276
276
277
277 class subsetparentswalker(object):
278 class subsetparentswalker(object):
278 r"""Scan adjacent ancestors in the graph given by the subset
279 r"""Scan adjacent ancestors in the graph given by the subset
279
280
280 This computes parent-child relations in the sub graph filtered by
281 This computes parent-child relations in the sub graph filtered by
281 a revset. Primary use case is to draw a revisions graph.
282 a revset. Primary use case is to draw a revisions graph.
282
283
283 In the following example, we consider that the node 'f' has edges to all
284 In the following example, we consider that the node 'f' has edges to all
284 ancestor nodes, but redundant paths are eliminated. The edge 'f'->'b'
285 ancestor nodes, but redundant paths are eliminated. The edge 'f'->'b'
285 is eliminated because there is a path 'f'->'c'->'b' for example.
286 is eliminated because there is a path 'f'->'c'->'b' for example.
286
287
287 - d - e -
288 - d - e -
288 / \
289 / \
289 a - b - c - f
290 a - b - c - f
290
291
291 If the node 'c' is filtered out, the edge 'f'->'b' is activated.
292 If the node 'c' is filtered out, the edge 'f'->'b' is activated.
292
293
293 - d - e -
294 - d - e -
294 / \
295 / \
295 a - b -(c)- f
296 a - b -(c)- f
296
297
297 Likewise, if 'd' and 'e' are filtered out, this edge is fully eliminated
298 Likewise, if 'd' and 'e' are filtered out, this edge is fully eliminated
298 since there is a path 'f'->'c'->'b'->'a' for 'f'->'a'.
299 since there is a path 'f'->'c'->'b'->'a' for 'f'->'a'.
299
300
300 (d) (e)
301 (d) (e)
301
302
302 a - b - c - f
303 a - b - c - f
303
304
304 Implementation-wise, 'f' is passed down to 'a' as unresolved through the
305 Implementation-wise, 'f' is passed down to 'a' as unresolved through the
305 'f'->'e'->'d'->'a' path, whereas we do also remember that 'f' has already
306 'f'->'e'->'d'->'a' path, whereas we do also remember that 'f' has already
306 been resolved while walking down the 'f'->'c'->'b'->'a' path. When
307 been resolved while walking down the 'f'->'c'->'b'->'a' path. When
307 processing the node 'a', the unresolved 'f'->'a' path is eliminated as
308 processing the node 'a', the unresolved 'f'->'a' path is eliminated as
308 the 'f' end is marked as resolved.
309 the 'f' end is marked as resolved.
309
310
310 Ancestors are searched from the tipmost revision in the subset so the
311 Ancestors are searched from the tipmost revision in the subset so the
311 results can be cached. You should specify startrev to narrow the search
312 results can be cached. You should specify startrev to narrow the search
312 space to ':startrev'.
313 space to ':startrev'.
313 """
314 """
314
315
315 def __init__(self, repo, subset, startrev=None):
316 def __init__(self, repo, subset, startrev=None):
316 if startrev is not None:
317 if startrev is not None:
317 subset = repo.revs(b'%d:null', startrev) & subset
318 subset = repo.revs(b'%d:null', startrev) & subset
318
319
319 # equivalent to 'subset = subset.sorted(reverse=True)', but there's
320 # equivalent to 'subset = subset.sorted(reverse=True)', but there's
320 # no such function.
321 # no such function.
321 fastdesc = subset.fastdesc
322 fastdesc = subset.fastdesc
322 if fastdesc:
323 if fastdesc:
323 desciter = fastdesc()
324 desciter = fastdesc()
324 else:
325 else:
325 if not subset.isdescending() and not subset.istopo():
326 if not subset.isdescending() and not subset.istopo():
326 subset = smartset.baseset(subset)
327 subset = smartset.baseset(subset)
327 subset.sort(reverse=True)
328 subset.sort(reverse=True)
328 desciter = iter(subset)
329 desciter = iter(subset)
329
330
330 self._repo = repo
331 self._repo = repo
331 self._changelog = repo.changelog
332 self._changelog = repo.changelog
332 self._subset = subset
333 self._subset = subset
333
334
334 # scanning state (see _scanparents):
335 # scanning state (see _scanparents):
335 self._tovisit = []
336 self._tovisit = []
336 self._pendingcnt = {}
337 self._pendingcnt = {}
337 self._pointers = {}
338 self._pointers = {}
338 self._parents = {}
339 self._parents = {}
339 self._inputhead = nullrev # reassigned by self._advanceinput()
340 self._inputhead = nullrev # reassigned by self._advanceinput()
340 self._inputtail = desciter
341 self._inputtail = desciter
341 self._bottomrev = nullrev
342 self._bottomrev = nullrev
342 self._advanceinput()
343 self._advanceinput()
343
344
344 def parentsset(self, rev):
345 def parentsset(self, rev):
345 """Look up parents of the given revision in the subset, and returns
346 """Look up parents of the given revision in the subset, and returns
346 as a smartset"""
347 as a smartset"""
347 return smartset.baseset(self.parents(rev))
348 return smartset.baseset(self.parents(rev))
348
349
349 def parents(self, rev):
350 def parents(self, rev):
350 """Look up parents of the given revision in the subset
351 """Look up parents of the given revision in the subset
351
352
352 The returned revisions are sorted by parent index (p1/p2).
353 The returned revisions are sorted by parent index (p1/p2).
353 """
354 """
354 self._scanparents(rev)
355 self._scanparents(rev)
355 return [r for _c, r in sorted(self._parents.get(rev, []))]
356 return [r for _c, r in sorted(self._parents.get(rev, []))]
356
357
357 def _parentrevs(self, rev):
358 def _parentrevs(self, rev):
358 try:
359 try:
359 revs = self._changelog.parentrevs(rev)
360 revs = self._changelog.parentrevs(rev)
360 if revs[-1] == nullrev:
361 if revs[-1] == nullrev:
361 return revs[:-1]
362 return revs[:-1]
362 return revs
363 return revs
363 except error.WdirUnsupported:
364 except error.WdirUnsupported:
364 return tuple(pctx.rev() for pctx in self._repo[None].parents())
365 return tuple(pctx.rev() for pctx in self._repo[None].parents())
365
366
366 def _advanceinput(self):
367 def _advanceinput(self):
367 """Advance the input iterator and set the next revision to _inputhead"""
368 """Advance the input iterator and set the next revision to _inputhead"""
368 if self._inputhead < nullrev:
369 if self._inputhead < nullrev:
369 return
370 return
370 try:
371 try:
371 self._inputhead = next(self._inputtail)
372 self._inputhead = next(self._inputtail)
372 except StopIteration:
373 except StopIteration:
373 self._bottomrev = self._inputhead
374 self._bottomrev = self._inputhead
374 self._inputhead = nullrev - 1
375 self._inputhead = nullrev - 1
375
376
376 def _scanparents(self, stoprev):
377 def _scanparents(self, stoprev):
377 """Scan ancestors until the parents of the specified stoprev are
378 """Scan ancestors until the parents of the specified stoprev are
378 resolved"""
379 resolved"""
379
380
380 # 'tovisit' is the queue of the input revisions and their ancestors.
381 # 'tovisit' is the queue of the input revisions and their ancestors.
381 # It will be populated incrementally to minimize the initial cost
382 # It will be populated incrementally to minimize the initial cost
382 # of computing the given subset.
383 # of computing the given subset.
383 #
384 #
384 # For to-visit revisions, we keep track of
385 # For to-visit revisions, we keep track of
385 # - the number of the unresolved paths: pendingcnt[rev],
386 # - the number of the unresolved paths: pendingcnt[rev],
386 # - dict of the unresolved descendants and chains: pointers[rev][0],
387 # - dict of the unresolved descendants and chains: pointers[rev][0],
387 # - set of the already resolved descendants: pointers[rev][1].
388 # - set of the already resolved descendants: pointers[rev][1].
388 #
389 #
389 # When a revision is visited, 'pointers[rev]' should be popped and
390 # When a revision is visited, 'pointers[rev]' should be popped and
390 # propagated to its parents accordingly.
391 # propagated to its parents accordingly.
391 #
392 #
392 # Once all pending paths have been resolved, 'pendingcnt[rev]' becomes
393 # Once all pending paths have been resolved, 'pendingcnt[rev]' becomes
393 # 0 and 'parents[rev]' contains the unsorted list of parent revisions
394 # 0 and 'parents[rev]' contains the unsorted list of parent revisions
394 # and p1/p2 chains (excluding linear paths.) The p1/p2 chains will be
395 # and p1/p2 chains (excluding linear paths.) The p1/p2 chains will be
395 # used as a sort key preferring p1. 'len(chain)' should be the number
396 # used as a sort key preferring p1. 'len(chain)' should be the number
396 # of merges between two revisions.
397 # of merges between two revisions.
397
398
398 subset = self._subset
399 subset = self._subset
399 tovisit = self._tovisit # heap queue of [-rev]
400 tovisit = self._tovisit # heap queue of [-rev]
400 pendingcnt = self._pendingcnt # {rev: count} for visited revisions
401 pendingcnt = self._pendingcnt # {rev: count} for visited revisions
401 pointers = self._pointers # {rev: [{unresolved_rev: chain}, resolved]}
402 pointers = self._pointers # {rev: [{unresolved_rev: chain}, resolved]}
402 parents = self._parents # {rev: [(chain, rev)]}
403 parents = self._parents # {rev: [(chain, rev)]}
403
404
404 while tovisit or self._inputhead >= nullrev:
405 while tovisit or self._inputhead >= nullrev:
405 if pendingcnt.get(stoprev) == 0:
406 if pendingcnt.get(stoprev) == 0:
406 return
407 return
407
408
408 # feed greater revisions from input set to queue
409 # feed greater revisions from input set to queue
409 if not tovisit:
410 if not tovisit:
410 heapq.heappush(tovisit, -self._inputhead)
411 heapq.heappush(tovisit, -self._inputhead)
411 self._advanceinput()
412 self._advanceinput()
412 while self._inputhead >= -tovisit[0]:
413 while self._inputhead >= -tovisit[0]:
413 heapq.heappush(tovisit, -self._inputhead)
414 heapq.heappush(tovisit, -self._inputhead)
414 self._advanceinput()
415 self._advanceinput()
415
416
416 rev = -heapq.heappop(tovisit)
417 rev = -heapq.heappop(tovisit)
417 if rev < self._bottomrev:
418 if rev < self._bottomrev:
418 return
419 return
419 if rev in pendingcnt and rev not in pointers:
420 if rev in pendingcnt and rev not in pointers:
420 continue # already visited
421 continue # already visited
421
422
422 curactive = rev in subset
423 curactive = rev in subset
423 pendingcnt.setdefault(rev, 0) # mark as visited
424 pendingcnt.setdefault(rev, 0) # mark as visited
424 if curactive:
425 if curactive:
425 assert rev not in parents
426 assert rev not in parents
426 parents[rev] = []
427 parents[rev] = []
427 unresolved, resolved = pointers.pop(rev, ({}, set()))
428 unresolved, resolved = pointers.pop(rev, ({}, set()))
428
429
429 if curactive:
430 if curactive:
430 # reached to active rev, resolve pending descendants' parents
431 # reached to active rev, resolve pending descendants' parents
431 for r, c in unresolved.items():
432 for r, c in unresolved.items():
432 pendingcnt[r] -= 1
433 pendingcnt[r] -= 1
433 assert pendingcnt[r] >= 0
434 assert pendingcnt[r] >= 0
434 if r in resolved:
435 if r in resolved:
435 continue # eliminate redundant path
436 continue # eliminate redundant path
436 parents[r].append((c, rev))
437 parents[r].append((c, rev))
437 # mark the descendant 'r' as resolved through this path if
438 # mark the descendant 'r' as resolved through this path if
438 # there are still pending pointers. the 'resolved' set may
439 # there are still pending pointers. the 'resolved' set may
439 # be concatenated later at a fork revision.
440 # be concatenated later at a fork revision.
440 if pendingcnt[r] > 0:
441 if pendingcnt[r] > 0:
441 resolved.add(r)
442 resolved.add(r)
442 unresolved.clear()
443 unresolved.clear()
443 # occasionally clean resolved markers. otherwise the set
444 # occasionally clean resolved markers. otherwise the set
444 # would grow indefinitely.
445 # would grow indefinitely.
445 resolved = {r for r in resolved if pendingcnt[r] > 0}
446 resolved = {r for r in resolved if pendingcnt[r] > 0}
446
447
447 parentrevs = self._parentrevs(rev)
448 parentrevs = self._parentrevs(rev)
448 bothparentsactive = all(p in subset for p in parentrevs)
449 bothparentsactive = all(p in subset for p in parentrevs)
449
450
450 # set up or propagate tracking pointers if
451 # set up or propagate tracking pointers if
451 # - one of the parents is not active,
452 # - one of the parents is not active,
452 # - or descendants' parents are unresolved.
453 # - or descendants' parents are unresolved.
453 if not bothparentsactive or unresolved or resolved:
454 if not bothparentsactive or unresolved or resolved:
454 if len(parentrevs) <= 1:
455 if len(parentrevs) <= 1:
455 # can avoid copying the tracking pointer
456 # can avoid copying the tracking pointer
456 parentpointers = [(unresolved, resolved)]
457 parentpointers = [(unresolved, resolved)]
457 else:
458 else:
458 parentpointers = [
459 parentpointers = [
459 (unresolved, resolved),
460 (unresolved, resolved),
460 (unresolved.copy(), resolved.copy()),
461 (unresolved.copy(), resolved.copy()),
461 ]
462 ]
462 # 'rev' is a merge revision. increment the pending count
463 # 'rev' is a merge revision. increment the pending count
463 # as the 'unresolved' dict will be duplicated, and append
464 # as the 'unresolved' dict will be duplicated, and append
464 # p1/p2 code to the existing chains.
465 # p1/p2 code to the existing chains.
465 for r in unresolved:
466 for r in unresolved:
466 pendingcnt[r] += 1
467 pendingcnt[r] += 1
467 parentpointers[0][0][r] += b'1'
468 parentpointers[0][0][r] += b'1'
468 parentpointers[1][0][r] += b'2'
469 parentpointers[1][0][r] += b'2'
469 for i, p in enumerate(parentrevs):
470 for i, p in enumerate(parentrevs):
470 assert p < rev
471 assert p < rev
471 heapq.heappush(tovisit, -p)
472 heapq.heappush(tovisit, -p)
472 if p in pointers:
473 if p in pointers:
473 # 'p' is a fork revision. concatenate tracking pointers
474 # 'p' is a fork revision. concatenate tracking pointers
474 # and decrement the pending count accordingly.
475 # and decrement the pending count accordingly.
475 knownunresolved, knownresolved = pointers[p]
476 knownunresolved, knownresolved = pointers[p]
476 unresolved, resolved = parentpointers[i]
477 unresolved, resolved = parentpointers[i]
477 for r, c in unresolved.items():
478 for r, c in unresolved.items():
478 if r in knownunresolved:
479 if r in knownunresolved:
479 # unresolved at both paths
480 # unresolved at both paths
480 pendingcnt[r] -= 1
481 pendingcnt[r] -= 1
481 assert pendingcnt[r] > 0
482 assert pendingcnt[r] > 0
482 # take shorter chain
483 # take shorter chain
483 knownunresolved[r] = min(c, knownunresolved[r])
484 knownunresolved[r] = min(c, knownunresolved[r])
484 else:
485 else:
485 knownunresolved[r] = c
486 knownunresolved[r] = c
486 # simply propagate the 'resolved' set as deduplicating
487 # simply propagate the 'resolved' set as deduplicating
487 # 'unresolved' here would be slightly complicated.
488 # 'unresolved' here would be slightly complicated.
488 knownresolved.update(resolved)
489 knownresolved.update(resolved)
489 else:
490 else:
490 pointers[p] = parentpointers[i]
491 pointers[p] = parentpointers[i]
491
492
492 # then, populate the active parents directly and add the current
493 # then, populate the active parents directly and add the current
493 # 'rev' to the tracking pointers of the inactive parents.
494 # 'rev' to the tracking pointers of the inactive parents.
494 # 'pointers[p]' may be optimized out if both parents are active.
495 # 'pointers[p]' may be optimized out if both parents are active.
495 chaincodes = [b''] if len(parentrevs) <= 1 else [b'1', b'2']
496 chaincodes = [b''] if len(parentrevs) <= 1 else [b'1', b'2']
496 if curactive and bothparentsactive:
497 if curactive and bothparentsactive:
497 for i, p in enumerate(parentrevs):
498 for i, p in enumerate(parentrevs):
498 c = chaincodes[i]
499 c = chaincodes[i]
499 parents[rev].append((c, p))
500 parents[rev].append((c, p))
500 # no need to mark 'rev' as resolved since the 'rev' should
501 # no need to mark 'rev' as resolved since the 'rev' should
501 # be fully resolved (i.e. pendingcnt[rev] == 0)
502 # be fully resolved (i.e. pendingcnt[rev] == 0)
502 assert pendingcnt[rev] == 0
503 assert pendingcnt[rev] == 0
503 elif curactive:
504 elif curactive:
504 for i, p in enumerate(parentrevs):
505 for i, p in enumerate(parentrevs):
505 unresolved, resolved = pointers[p]
506 unresolved, resolved = pointers[p]
506 assert rev not in unresolved
507 assert rev not in unresolved
507 c = chaincodes[i]
508 c = chaincodes[i]
508 if p in subset:
509 if p in subset:
509 parents[rev].append((c, p))
510 parents[rev].append((c, p))
510 # mark 'rev' as resolved through this path
511 # mark 'rev' as resolved through this path
511 resolved.add(rev)
512 resolved.add(rev)
512 else:
513 else:
513 pendingcnt[rev] += 1
514 pendingcnt[rev] += 1
514 unresolved[rev] = c
515 unresolved[rev] = c
515 assert 0 < pendingcnt[rev] <= 2
516 assert 0 < pendingcnt[rev] <= 2
516
517
517
518
518 def _reachablerootspure(pfunc, minroot, roots, heads, includepath):
519 def _reachablerootspure(pfunc, minroot, roots, heads, includepath):
519 """See revlog.reachableroots"""
520 """See revlog.reachableroots"""
520 if not roots:
521 if not roots:
521 return []
522 return []
522 roots = set(roots)
523 roots = set(roots)
523 visit = list(heads)
524 visit = list(heads)
524 reachable = set()
525 reachable = set()
525 seen = {}
526 seen = {}
526 # prefetch all the things! (because python is slow)
527 # prefetch all the things! (because python is slow)
527 reached = reachable.add
528 reached = reachable.add
528 dovisit = visit.append
529 dovisit = visit.append
529 nextvisit = visit.pop
530 nextvisit = visit.pop
530 # open-code the post-order traversal due to the tiny size of
531 # open-code the post-order traversal due to the tiny size of
531 # sys.getrecursionlimit()
532 # sys.getrecursionlimit()
532 while visit:
533 while visit:
533 rev = nextvisit()
534 rev = nextvisit()
534 if rev in roots:
535 if rev in roots:
535 reached(rev)
536 reached(rev)
536 if not includepath:
537 if not includepath:
537 continue
538 continue
538 parents = pfunc(rev)
539 parents = pfunc(rev)
539 seen[rev] = parents
540 seen[rev] = parents
540 for parent in parents:
541 for parent in parents:
541 if parent >= minroot and parent not in seen:
542 if parent >= minroot and parent not in seen:
542 dovisit(parent)
543 dovisit(parent)
543 if not reachable:
544 if not reachable:
544 return baseset()
545 return baseset()
545 if not includepath:
546 if not includepath:
546 return reachable
547 return reachable
547 for rev in sorted(seen):
548 for rev in sorted(seen):
548 for parent in seen[rev]:
549 for parent in seen[rev]:
549 if parent in reachable:
550 if parent in reachable:
550 reached(rev)
551 reached(rev)
551 return reachable
552 return reachable
552
553
553
554
554 def reachableroots(repo, roots, heads, includepath=False):
555 def reachableroots(repo, roots, heads, includepath=False):
555 """See revlog.reachableroots"""
556 """See revlog.reachableroots"""
556 if not roots:
557 if not roots:
557 return baseset()
558 return baseset()
558 minroot = roots.min()
559 minroot = roots.min()
559 roots = list(roots)
560 roots = list(roots)
560 heads = list(heads)
561 heads = list(heads)
561 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath)
562 revs = repo.changelog.reachableroots(minroot, heads, roots, includepath)
562 revs = baseset(revs)
563 revs = baseset(revs)
563 revs.sort()
564 revs.sort()
564 return revs
565 return revs
565
566
566
567
567 def _changesrange(fctx1, fctx2, linerange2, diffopts):
568 def _changesrange(fctx1, fctx2, linerange2, diffopts):
568 """Return `(diffinrange, linerange1)` where `diffinrange` is True
569 """Return `(diffinrange, linerange1)` where `diffinrange` is True
569 if diff from fctx2 to fctx1 has changes in linerange2 and
570 if diff from fctx2 to fctx1 has changes in linerange2 and
570 `linerange1` is the new line range for fctx1.
571 `linerange1` is the new line range for fctx1.
571 """
572 """
572 blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts)
573 blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts)
573 filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2)
574 filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2)
574 diffinrange = any(stype == b'!' for _, stype in filteredblocks)
575 diffinrange = any(stype == b'!' for _, stype in filteredblocks)
575 return diffinrange, linerange1
576 return diffinrange, linerange1
576
577
577
578
578 def blockancestors(fctx, fromline, toline, followfirst=False):
579 def blockancestors(fctx, fromline, toline, followfirst=False):
579 """Yield ancestors of `fctx` with respect to the block of lines within
580 """Yield ancestors of `fctx` with respect to the block of lines within
580 `fromline`-`toline` range.
581 `fromline`-`toline` range.
581 """
582 """
582 diffopts = patch.diffopts(fctx._repo.ui)
583 diffopts = patch.diffopts(fctx._repo.ui)
583 fctx = fctx.introfilectx()
584 fctx = fctx.introfilectx()
584 visit = {(fctx.linkrev(), fctx.filenode()): (fctx, (fromline, toline))}
585 visit = {(fctx.linkrev(), fctx.filenode()): (fctx, (fromline, toline))}
585 while visit:
586 while visit:
586 c, linerange2 = visit.pop(max(visit))
587 c, linerange2 = visit.pop(max(visit))
587 pl = c.parents()
588 pl = c.parents()
588 if followfirst:
589 if followfirst:
589 pl = pl[:1]
590 pl = pl[:1]
590 if not pl:
591 if not pl:
591 # The block originates from the initial revision.
592 # The block originates from the initial revision.
592 yield c, linerange2
593 yield c, linerange2
593 continue
594 continue
594 inrange = False
595 inrange = False
595 for p in pl:
596 for p in pl:
596 inrangep, linerange1 = _changesrange(p, c, linerange2, diffopts)
597 inrangep, linerange1 = _changesrange(p, c, linerange2, diffopts)
597 inrange = inrange or inrangep
598 inrange = inrange or inrangep
598 if linerange1[0] == linerange1[1]:
599 if linerange1[0] == linerange1[1]:
599 # Parent's linerange is empty, meaning that the block got
600 # Parent's linerange is empty, meaning that the block got
600 # introduced in this revision; no need to go futher in this
601 # introduced in this revision; no need to go futher in this
601 # branch.
602 # branch.
602 continue
603 continue
603 # Set _descendantrev with 'c' (a known descendant) so that, when
604 # Set _descendantrev with 'c' (a known descendant) so that, when
604 # _adjustlinkrev is called for 'p', it receives this descendant
605 # _adjustlinkrev is called for 'p', it receives this descendant
605 # (as srcrev) instead possibly topmost introrev.
606 # (as srcrev) instead possibly topmost introrev.
606 p._descendantrev = c.rev()
607 p._descendantrev = c.rev()
607 visit[p.linkrev(), p.filenode()] = p, linerange1
608 visit[p.linkrev(), p.filenode()] = p, linerange1
608 if inrange:
609 if inrange:
609 yield c, linerange2
610 yield c, linerange2
610
611
611
612
612 def blockdescendants(fctx, fromline, toline):
613 def blockdescendants(fctx, fromline, toline):
613 """Yield descendants of `fctx` with respect to the block of lines within
614 """Yield descendants of `fctx` with respect to the block of lines within
614 `fromline`-`toline` range.
615 `fromline`-`toline` range.
615 """
616 """
616 # First possibly yield 'fctx' if it has changes in range with respect to
617 # First possibly yield 'fctx' if it has changes in range with respect to
617 # its parents.
618 # its parents.
618 try:
619 try:
619 c, linerange1 = next(blockancestors(fctx, fromline, toline))
620 c, linerange1 = next(blockancestors(fctx, fromline, toline))
620 except StopIteration:
621 except StopIteration:
621 pass
622 pass
622 else:
623 else:
623 if c == fctx:
624 if c == fctx:
624 yield c, linerange1
625 yield c, linerange1
625
626
626 diffopts = patch.diffopts(fctx._repo.ui)
627 diffopts = patch.diffopts(fctx._repo.ui)
627 fl = fctx.filelog()
628 fl = fctx.filelog()
628 seen = {fctx.filerev(): (fctx, (fromline, toline))}
629 seen = {fctx.filerev(): (fctx, (fromline, toline))}
629 for i in fl.descendants([fctx.filerev()]):
630 for i in fl.descendants([fctx.filerev()]):
630 c = fctx.filectx(i)
631 c = fctx.filectx(i)
631 inrange = False
632 inrange = False
632 for x in fl.parentrevs(i):
633 for x in fl.parentrevs(i):
633 try:
634 try:
634 p, linerange2 = seen[x]
635 p, linerange2 = seen[x]
635 except KeyError:
636 except KeyError:
636 # nullrev or other branch
637 # nullrev or other branch
637 continue
638 continue
638 inrangep, linerange1 = _changesrange(c, p, linerange2, diffopts)
639 inrangep, linerange1 = _changesrange(c, p, linerange2, diffopts)
639 inrange = inrange or inrangep
640 inrange = inrange or inrangep
640 # If revision 'i' has been seen (it's a merge) and the line range
641 # If revision 'i' has been seen (it's a merge) and the line range
641 # previously computed differs from the one we just got, we take the
642 # previously computed differs from the one we just got, we take the
642 # surrounding interval. This is conservative but avoids loosing
643 # surrounding interval. This is conservative but avoids loosing
643 # information.
644 # information.
644 if i in seen and seen[i][1] != linerange1:
645 if i in seen and seen[i][1] != linerange1:
645 lbs, ubs = zip(linerange1, seen[i][1])
646 lbs, ubs = zip(linerange1, seen[i][1])
646 linerange1 = min(lbs), max(ubs)
647 linerange1 = min(lbs), max(ubs)
647 seen[i] = c, linerange1
648 seen[i] = c, linerange1
648 if inrange:
649 if inrange:
649 yield c, linerange1
650 yield c, linerange1
650
651
651
652
652 @attr.s(slots=True, frozen=True)
653 @attr.s(slots=True, frozen=True)
653 class annotateline(object):
654 class annotateline(object):
654 fctx = attr.ib()
655 fctx = attr.ib()
655 lineno = attr.ib()
656 lineno = attr.ib()
656 # Whether this annotation was the result of a skip-annotate.
657 # Whether this annotation was the result of a skip-annotate.
657 skip = attr.ib(default=False)
658 skip = attr.ib(default=False)
658 text = attr.ib(default=None)
659 text = attr.ib(default=None)
659
660
660
661
661 @attr.s(slots=True, frozen=True)
662 @attr.s(slots=True, frozen=True)
662 class _annotatedfile(object):
663 class _annotatedfile(object):
663 # list indexed by lineno - 1
664 # list indexed by lineno - 1
664 fctxs = attr.ib()
665 fctxs = attr.ib()
665 linenos = attr.ib()
666 linenos = attr.ib()
666 skips = attr.ib()
667 skips = attr.ib()
667 # full file content
668 # full file content
668 text = attr.ib()
669 text = attr.ib()
669
670
670
671
671 def _countlines(text):
672 def _countlines(text):
672 if text.endswith(b"\n"):
673 if text.endswith(b"\n"):
673 return text.count(b"\n")
674 return text.count(b"\n")
674 return text.count(b"\n") + int(bool(text))
675 return text.count(b"\n") + int(bool(text))
675
676
676
677
677 def _decoratelines(text, fctx):
678 def _decoratelines(text, fctx):
678 n = _countlines(text)
679 n = _countlines(text)
679 linenos = pycompat.rangelist(1, n + 1)
680 linenos = pycompat.rangelist(1, n + 1)
680 return _annotatedfile([fctx] * n, linenos, [False] * n, text)
681 return _annotatedfile([fctx] * n, linenos, [False] * n, text)
681
682
682
683
683 def _annotatepair(parents, childfctx, child, skipchild, diffopts):
684 def _annotatepair(parents, childfctx, child, skipchild, diffopts):
684 r'''
685 r'''
685 Given parent and child fctxes and annotate data for parents, for all lines
686 Given parent and child fctxes and annotate data for parents, for all lines
686 in either parent that match the child, annotate the child with the parent's
687 in either parent that match the child, annotate the child with the parent's
687 data.
688 data.
688
689
689 Additionally, if `skipchild` is True, replace all other lines with parent
690 Additionally, if `skipchild` is True, replace all other lines with parent
690 annotate data as well such that child is never blamed for any lines.
691 annotate data as well such that child is never blamed for any lines.
691
692
692 See test-annotate.py for unit tests.
693 See test-annotate.py for unit tests.
693 '''
694 '''
694 pblocks = [
695 pblocks = [
695 (parent, mdiff.allblocks(parent.text, child.text, opts=diffopts))
696 (parent, mdiff.allblocks(parent.text, child.text, opts=diffopts))
696 for parent in parents
697 for parent in parents
697 ]
698 ]
698
699
699 if skipchild:
700 if skipchild:
700 # Need to iterate over the blocks twice -- make it a list
701 # Need to iterate over the blocks twice -- make it a list
701 pblocks = [(p, list(blocks)) for (p, blocks) in pblocks]
702 pblocks = [(p, list(blocks)) for (p, blocks) in pblocks]
702 # Mercurial currently prefers p2 over p1 for annotate.
703 # Mercurial currently prefers p2 over p1 for annotate.
703 # TODO: change this?
704 # TODO: change this?
704 for parent, blocks in pblocks:
705 for parent, blocks in pblocks:
705 for (a1, a2, b1, b2), t in blocks:
706 for (a1, a2, b1, b2), t in blocks:
706 # Changed blocks ('!') or blocks made only of blank lines ('~')
707 # Changed blocks ('!') or blocks made only of blank lines ('~')
707 # belong to the child.
708 # belong to the child.
708 if t == b'=':
709 if t == b'=':
709 child.fctxs[b1:b2] = parent.fctxs[a1:a2]
710 child.fctxs[b1:b2] = parent.fctxs[a1:a2]
710 child.linenos[b1:b2] = parent.linenos[a1:a2]
711 child.linenos[b1:b2] = parent.linenos[a1:a2]
711 child.skips[b1:b2] = parent.skips[a1:a2]
712 child.skips[b1:b2] = parent.skips[a1:a2]
712
713
713 if skipchild:
714 if skipchild:
714 # Now try and match up anything that couldn't be matched,
715 # Now try and match up anything that couldn't be matched,
715 # Reversing pblocks maintains bias towards p2, matching above
716 # Reversing pblocks maintains bias towards p2, matching above
716 # behavior.
717 # behavior.
717 pblocks.reverse()
718 pblocks.reverse()
718
719
719 # The heuristics are:
720 # The heuristics are:
720 # * Work on blocks of changed lines (effectively diff hunks with -U0).
721 # * Work on blocks of changed lines (effectively diff hunks with -U0).
721 # This could potentially be smarter but works well enough.
722 # This could potentially be smarter but works well enough.
722 # * For a non-matching section, do a best-effort fit. Match lines in
723 # * For a non-matching section, do a best-effort fit. Match lines in
723 # diff hunks 1:1, dropping lines as necessary.
724 # diff hunks 1:1, dropping lines as necessary.
724 # * Repeat the last line as a last resort.
725 # * Repeat the last line as a last resort.
725
726
726 # First, replace as much as possible without repeating the last line.
727 # First, replace as much as possible without repeating the last line.
727 remaining = [(parent, []) for parent, _blocks in pblocks]
728 remaining = [(parent, []) for parent, _blocks in pblocks]
728 for idx, (parent, blocks) in enumerate(pblocks):
729 for idx, (parent, blocks) in enumerate(pblocks):
729 for (a1, a2, b1, b2), _t in blocks:
730 for (a1, a2, b1, b2), _t in blocks:
730 if a2 - a1 >= b2 - b1:
731 if a2 - a1 >= b2 - b1:
731 for bk in pycompat.xrange(b1, b2):
732 for bk in pycompat.xrange(b1, b2):
732 if child.fctxs[bk] == childfctx:
733 if child.fctxs[bk] == childfctx:
733 ak = min(a1 + (bk - b1), a2 - 1)
734 ak = min(a1 + (bk - b1), a2 - 1)
734 child.fctxs[bk] = parent.fctxs[ak]
735 child.fctxs[bk] = parent.fctxs[ak]
735 child.linenos[bk] = parent.linenos[ak]
736 child.linenos[bk] = parent.linenos[ak]
736 child.skips[bk] = True
737 child.skips[bk] = True
737 else:
738 else:
738 remaining[idx][1].append((a1, a2, b1, b2))
739 remaining[idx][1].append((a1, a2, b1, b2))
739
740
740 # Then, look at anything left, which might involve repeating the last
741 # Then, look at anything left, which might involve repeating the last
741 # line.
742 # line.
742 for parent, blocks in remaining:
743 for parent, blocks in remaining:
743 for a1, a2, b1, b2 in blocks:
744 for a1, a2, b1, b2 in blocks:
744 for bk in pycompat.xrange(b1, b2):
745 for bk in pycompat.xrange(b1, b2):
745 if child.fctxs[bk] == childfctx:
746 if child.fctxs[bk] == childfctx:
746 ak = min(a1 + (bk - b1), a2 - 1)
747 ak = min(a1 + (bk - b1), a2 - 1)
747 child.fctxs[bk] = parent.fctxs[ak]
748 child.fctxs[bk] = parent.fctxs[ak]
748 child.linenos[bk] = parent.linenos[ak]
749 child.linenos[bk] = parent.linenos[ak]
749 child.skips[bk] = True
750 child.skips[bk] = True
750 return child
751 return child
751
752
752
753
753 def annotate(base, parents, skiprevs=None, diffopts=None):
754 def annotate(base, parents, skiprevs=None, diffopts=None):
754 """Core algorithm for filectx.annotate()
755 """Core algorithm for filectx.annotate()
755
756
756 `parents(fctx)` is a function returning a list of parent filectxs.
757 `parents(fctx)` is a function returning a list of parent filectxs.
757 """
758 """
758
759
759 # This algorithm would prefer to be recursive, but Python is a
760 # This algorithm would prefer to be recursive, but Python is a
760 # bit recursion-hostile. Instead we do an iterative
761 # bit recursion-hostile. Instead we do an iterative
761 # depth-first search.
762 # depth-first search.
762
763
763 # 1st DFS pre-calculates pcache and needed
764 # 1st DFS pre-calculates pcache and needed
764 visit = [base]
765 visit = [base]
765 pcache = {}
766 pcache = {}
766 needed = {base: 1}
767 needed = {base: 1}
767 while visit:
768 while visit:
768 f = visit.pop()
769 f = visit.pop()
769 if f in pcache:
770 if f in pcache:
770 continue
771 continue
771 pl = parents(f)
772 pl = parents(f)
772 pcache[f] = pl
773 pcache[f] = pl
773 for p in pl:
774 for p in pl:
774 needed[p] = needed.get(p, 0) + 1
775 needed[p] = needed.get(p, 0) + 1
775 if p not in pcache:
776 if p not in pcache:
776 visit.append(p)
777 visit.append(p)
777
778
778 # 2nd DFS does the actual annotate
779 # 2nd DFS does the actual annotate
779 visit[:] = [base]
780 visit[:] = [base]
780 hist = {}
781 hist = {}
781 while visit:
782 while visit:
782 f = visit[-1]
783 f = visit[-1]
783 if f in hist:
784 if f in hist:
784 visit.pop()
785 visit.pop()
785 continue
786 continue
786
787
787 ready = True
788 ready = True
788 pl = pcache[f]
789 pl = pcache[f]
789 for p in pl:
790 for p in pl:
790 if p not in hist:
791 if p not in hist:
791 ready = False
792 ready = False
792 visit.append(p)
793 visit.append(p)
793 if ready:
794 if ready:
794 visit.pop()
795 visit.pop()
795 curr = _decoratelines(f.data(), f)
796 curr = _decoratelines(f.data(), f)
796 skipchild = False
797 skipchild = False
797 if skiprevs is not None:
798 if skiprevs is not None:
798 skipchild = f._changeid in skiprevs
799 skipchild = f._changeid in skiprevs
799 curr = _annotatepair(
800 curr = _annotatepair(
800 [hist[p] for p in pl], f, curr, skipchild, diffopts
801 [hist[p] for p in pl], f, curr, skipchild, diffopts
801 )
802 )
802 for p in pl:
803 for p in pl:
803 if needed[p] == 1:
804 if needed[p] == 1:
804 del hist[p]
805 del hist[p]
805 del needed[p]
806 del needed[p]
806 else:
807 else:
807 needed[p] -= 1
808 needed[p] -= 1
808
809
809 hist[f] = curr
810 hist[f] = curr
810 del pcache[f]
811 del pcache[f]
811
812
812 a = hist[base]
813 a = hist[base]
813 return [
814 return [
814 annotateline(*r)
815 annotateline(*r)
815 for r in zip(a.fctxs, a.linenos, a.skips, mdiff.splitnewlines(a.text))
816 for r in zip(a.fctxs, a.linenos, a.skips, mdiff.splitnewlines(a.text))
816 ]
817 ]
817
818
818
819
819 def toposort(revs, parentsfunc, firstbranch=()):
820 def toposort(revs, parentsfunc, firstbranch=()):
820 """Yield revisions from heads to roots one (topo) branch at a time.
821 """Yield revisions from heads to roots one (topo) branch at a time.
821
822
822 This function aims to be used by a graph generator that wishes to minimize
823 This function aims to be used by a graph generator that wishes to minimize
823 the number of parallel branches and their interleaving.
824 the number of parallel branches and their interleaving.
824
825
825 Example iteration order (numbers show the "true" order in a changelog):
826 Example iteration order (numbers show the "true" order in a changelog):
826
827
827 o 4
828 o 4
828 |
829 |
829 o 1
830 o 1
830 |
831 |
831 | o 3
832 | o 3
832 | |
833 | |
833 | o 2
834 | o 2
834 |/
835 |/
835 o 0
836 o 0
836
837
837 Note that the ancestors of merges are understood by the current
838 Note that the ancestors of merges are understood by the current
838 algorithm to be on the same branch. This means no reordering will
839 algorithm to be on the same branch. This means no reordering will
839 occur behind a merge.
840 occur behind a merge.
840 """
841 """
841
842
842 ### Quick summary of the algorithm
843 ### Quick summary of the algorithm
843 #
844 #
844 # This function is based around a "retention" principle. We keep revisions
845 # This function is based around a "retention" principle. We keep revisions
845 # in memory until we are ready to emit a whole branch that immediately
846 # in memory until we are ready to emit a whole branch that immediately
846 # "merges" into an existing one. This reduces the number of parallel
847 # "merges" into an existing one. This reduces the number of parallel
847 # branches with interleaved revisions.
848 # branches with interleaved revisions.
848 #
849 #
849 # During iteration revs are split into two groups:
850 # During iteration revs are split into two groups:
850 # A) revision already emitted
851 # A) revision already emitted
851 # B) revision in "retention". They are stored as different subgroups.
852 # B) revision in "retention". They are stored as different subgroups.
852 #
853 #
853 # for each REV, we do the following logic:
854 # for each REV, we do the following logic:
854 #
855 #
855 # 1) if REV is a parent of (A), we will emit it. If there is a
856 # 1) if REV is a parent of (A), we will emit it. If there is a
856 # retention group ((B) above) that is blocked on REV being
857 # retention group ((B) above) that is blocked on REV being
857 # available, we emit all the revisions out of that retention
858 # available, we emit all the revisions out of that retention
858 # group first.
859 # group first.
859 #
860 #
860 # 2) else, we'll search for a subgroup in (B) awaiting for REV to be
861 # 2) else, we'll search for a subgroup in (B) awaiting for REV to be
861 # available, if such subgroup exist, we add REV to it and the subgroup is
862 # available, if such subgroup exist, we add REV to it and the subgroup is
862 # now awaiting for REV.parents() to be available.
863 # now awaiting for REV.parents() to be available.
863 #
864 #
864 # 3) finally if no such group existed in (B), we create a new subgroup.
865 # 3) finally if no such group existed in (B), we create a new subgroup.
865 #
866 #
866 #
867 #
867 # To bootstrap the algorithm, we emit the tipmost revision (which
868 # To bootstrap the algorithm, we emit the tipmost revision (which
868 # puts it in group (A) from above).
869 # puts it in group (A) from above).
869
870
870 revs.sort(reverse=True)
871 revs.sort(reverse=True)
871
872
872 # Set of parents of revision that have been emitted. They can be considered
873 # Set of parents of revision that have been emitted. They can be considered
873 # unblocked as the graph generator is already aware of them so there is no
874 # unblocked as the graph generator is already aware of them so there is no
874 # need to delay the revisions that reference them.
875 # need to delay the revisions that reference them.
875 #
876 #
876 # If someone wants to prioritize a branch over the others, pre-filling this
877 # If someone wants to prioritize a branch over the others, pre-filling this
877 # set will force all other branches to wait until this branch is ready to be
878 # set will force all other branches to wait until this branch is ready to be
878 # emitted.
879 # emitted.
879 unblocked = set(firstbranch)
880 unblocked = set(firstbranch)
880
881
881 # list of groups waiting to be displayed, each group is defined by:
882 # list of groups waiting to be displayed, each group is defined by:
882 #
883 #
883 # (revs: lists of revs waiting to be displayed,
884 # (revs: lists of revs waiting to be displayed,
884 # blocked: set of that cannot be displayed before those in 'revs')
885 # blocked: set of that cannot be displayed before those in 'revs')
885 #
886 #
886 # The second value ('blocked') correspond to parents of any revision in the
887 # The second value ('blocked') correspond to parents of any revision in the
887 # group ('revs') that is not itself contained in the group. The main idea
888 # group ('revs') that is not itself contained in the group. The main idea
888 # of this algorithm is to delay as much as possible the emission of any
889 # of this algorithm is to delay as much as possible the emission of any
889 # revision. This means waiting for the moment we are about to display
890 # revision. This means waiting for the moment we are about to display
890 # these parents to display the revs in a group.
891 # these parents to display the revs in a group.
891 #
892 #
892 # This first implementation is smart until it encounters a merge: it will
893 # This first implementation is smart until it encounters a merge: it will
893 # emit revs as soon as any parent is about to be emitted and can grow an
894 # emit revs as soon as any parent is about to be emitted and can grow an
894 # arbitrary number of revs in 'blocked'. In practice this mean we properly
895 # arbitrary number of revs in 'blocked'. In practice this mean we properly
895 # retains new branches but gives up on any special ordering for ancestors
896 # retains new branches but gives up on any special ordering for ancestors
896 # of merges. The implementation can be improved to handle this better.
897 # of merges. The implementation can be improved to handle this better.
897 #
898 #
898 # The first subgroup is special. It corresponds to all the revision that
899 # The first subgroup is special. It corresponds to all the revision that
899 # were already emitted. The 'revs' lists is expected to be empty and the
900 # were already emitted. The 'revs' lists is expected to be empty and the
900 # 'blocked' set contains the parents revisions of already emitted revision.
901 # 'blocked' set contains the parents revisions of already emitted revision.
901 #
902 #
902 # You could pre-seed the <parents> set of groups[0] to a specific
903 # You could pre-seed the <parents> set of groups[0] to a specific
903 # changesets to select what the first emitted branch should be.
904 # changesets to select what the first emitted branch should be.
904 groups = [([], unblocked)]
905 groups = [([], unblocked)]
905 pendingheap = []
906 pendingheap = []
906 pendingset = set()
907 pendingset = set()
907
908
908 heapq.heapify(pendingheap)
909 heapq.heapify(pendingheap)
909 heappop = heapq.heappop
910 heappop = heapq.heappop
910 heappush = heapq.heappush
911 heappush = heapq.heappush
911 for currentrev in revs:
912 for currentrev in revs:
912 # Heap works with smallest element, we want highest so we invert
913 # Heap works with smallest element, we want highest so we invert
913 if currentrev not in pendingset:
914 if currentrev not in pendingset:
914 heappush(pendingheap, -currentrev)
915 heappush(pendingheap, -currentrev)
915 pendingset.add(currentrev)
916 pendingset.add(currentrev)
916 # iterates on pending rev until after the current rev have been
917 # iterates on pending rev until after the current rev have been
917 # processed.
918 # processed.
918 rev = None
919 rev = None
919 while rev != currentrev:
920 while rev != currentrev:
920 rev = -heappop(pendingheap)
921 rev = -heappop(pendingheap)
921 pendingset.remove(rev)
922 pendingset.remove(rev)
922
923
923 # Seek for a subgroup blocked, waiting for the current revision.
924 # Seek for a subgroup blocked, waiting for the current revision.
924 matching = [i for i, g in enumerate(groups) if rev in g[1]]
925 matching = [i for i, g in enumerate(groups) if rev in g[1]]
925
926
926 if matching:
927 if matching:
927 # The main idea is to gather together all sets that are blocked
928 # The main idea is to gather together all sets that are blocked
928 # on the same revision.
929 # on the same revision.
929 #
930 #
930 # Groups are merged when a common blocking ancestor is
931 # Groups are merged when a common blocking ancestor is
931 # observed. For example, given two groups:
932 # observed. For example, given two groups:
932 #
933 #
933 # revs [5, 4] waiting for 1
934 # revs [5, 4] waiting for 1
934 # revs [3, 2] waiting for 1
935 # revs [3, 2] waiting for 1
935 #
936 #
936 # These two groups will be merged when we process
937 # These two groups will be merged when we process
937 # 1. In theory, we could have merged the groups when
938 # 1. In theory, we could have merged the groups when
938 # we added 2 to the group it is now in (we could have
939 # we added 2 to the group it is now in (we could have
939 # noticed the groups were both blocked on 1 then), but
940 # noticed the groups were both blocked on 1 then), but
940 # the way it works now makes the algorithm simpler.
941 # the way it works now makes the algorithm simpler.
941 #
942 #
942 # We also always keep the oldest subgroup first. We can
943 # We also always keep the oldest subgroup first. We can
943 # probably improve the behavior by having the longest set
944 # probably improve the behavior by having the longest set
944 # first. That way, graph algorithms could minimise the length
945 # first. That way, graph algorithms could minimise the length
945 # of parallel lines their drawing. This is currently not done.
946 # of parallel lines their drawing. This is currently not done.
946 targetidx = matching.pop(0)
947 targetidx = matching.pop(0)
947 trevs, tparents = groups[targetidx]
948 trevs, tparents = groups[targetidx]
948 for i in matching:
949 for i in matching:
949 gr = groups[i]
950 gr = groups[i]
950 trevs.extend(gr[0])
951 trevs.extend(gr[0])
951 tparents |= gr[1]
952 tparents |= gr[1]
952 # delete all merged subgroups (except the one we kept)
953 # delete all merged subgroups (except the one we kept)
953 # (starting from the last subgroup for performance and
954 # (starting from the last subgroup for performance and
954 # sanity reasons)
955 # sanity reasons)
955 for i in reversed(matching):
956 for i in reversed(matching):
956 del groups[i]
957 del groups[i]
957 else:
958 else:
958 # This is a new head. We create a new subgroup for it.
959 # This is a new head. We create a new subgroup for it.
959 targetidx = len(groups)
960 targetidx = len(groups)
960 groups.append(([], {rev}))
961 groups.append(([], {rev}))
961
962
962 gr = groups[targetidx]
963 gr = groups[targetidx]
963
964
964 # We now add the current nodes to this subgroups. This is done
965 # We now add the current nodes to this subgroups. This is done
965 # after the subgroup merging because all elements from a subgroup
966 # after the subgroup merging because all elements from a subgroup
966 # that relied on this rev must precede it.
967 # that relied on this rev must precede it.
967 #
968 #
968 # we also update the <parents> set to include the parents of the
969 # we also update the <parents> set to include the parents of the
969 # new nodes.
970 # new nodes.
970 if rev == currentrev: # only display stuff in rev
971 if rev == currentrev: # only display stuff in rev
971 gr[0].append(rev)
972 gr[0].append(rev)
972 gr[1].remove(rev)
973 gr[1].remove(rev)
973 parents = [p for p in parentsfunc(rev) if p > node.nullrev]
974 parents = [p for p in parentsfunc(rev) if p > node.nullrev]
974 gr[1].update(parents)
975 gr[1].update(parents)
975 for p in parents:
976 for p in parents:
976 if p not in pendingset:
977 if p not in pendingset:
977 pendingset.add(p)
978 pendingset.add(p)
978 heappush(pendingheap, -p)
979 heappush(pendingheap, -p)
979
980
980 # Look for a subgroup to display
981 # Look for a subgroup to display
981 #
982 #
982 # When unblocked is empty (if clause), we were not waiting for any
983 # When unblocked is empty (if clause), we were not waiting for any
983 # revisions during the first iteration (if no priority was given) or
984 # revisions during the first iteration (if no priority was given) or
984 # if we emitted a whole disconnected set of the graph (reached a
985 # if we emitted a whole disconnected set of the graph (reached a
985 # root). In that case we arbitrarily take the oldest known
986 # root). In that case we arbitrarily take the oldest known
986 # subgroup. The heuristic could probably be better.
987 # subgroup. The heuristic could probably be better.
987 #
988 #
988 # Otherwise (elif clause) if the subgroup is blocked on
989 # Otherwise (elif clause) if the subgroup is blocked on
989 # a revision we just emitted, we can safely emit it as
990 # a revision we just emitted, we can safely emit it as
990 # well.
991 # well.
991 if not unblocked:
992 if not unblocked:
992 if len(groups) > 1: # display other subset
993 if len(groups) > 1: # display other subset
993 targetidx = 1
994 targetidx = 1
994 gr = groups[1]
995 gr = groups[1]
995 elif not gr[1] & unblocked:
996 elif not gr[1] & unblocked:
996 gr = None
997 gr = None
997
998
998 if gr is not None:
999 if gr is not None:
999 # update the set of awaited revisions with the one from the
1000 # update the set of awaited revisions with the one from the
1000 # subgroup
1001 # subgroup
1001 unblocked |= gr[1]
1002 unblocked |= gr[1]
1002 # output all revisions in the subgroup
1003 # output all revisions in the subgroup
1003 for r in gr[0]:
1004 for r in gr[0]:
1004 yield r
1005 yield r
1005 # delete the subgroup that you just output
1006 # delete the subgroup that you just output
1006 # unless it is groups[0] in which case you just empty it.
1007 # unless it is groups[0] in which case you just empty it.
1007 if targetidx:
1008 if targetidx:
1008 del groups[targetidx]
1009 del groups[targetidx]
1009 else:
1010 else:
1010 gr[0][:] = []
1011 gr[0][:] = []
1011 # Check if we have some subgroup waiting for revisions we are not going to
1012 # Check if we have some subgroup waiting for revisions we are not going to
1012 # iterate over
1013 # iterate over
1013 for g in groups:
1014 for g in groups:
1014 for r in g[0]:
1015 for r in g[0]:
1015 yield r
1016 yield r
1016
1017
1017
1018
1018 def headrevs(revs, parentsfn):
1019 def headrevs(revs, parentsfn):
1019 """Resolve the set of heads from a set of revisions.
1020 """Resolve the set of heads from a set of revisions.
1020
1021
1021 Receives an iterable of revision numbers and a callbable that receives a
1022 Receives an iterable of revision numbers and a callbable that receives a
1022 revision number and returns an iterable of parent revision numbers, possibly
1023 revision number and returns an iterable of parent revision numbers, possibly
1023 including nullrev.
1024 including nullrev.
1024
1025
1025 Returns a set of revision numbers that are DAG heads within the passed
1026 Returns a set of revision numbers that are DAG heads within the passed
1026 subset.
1027 subset.
1027
1028
1028 ``nullrev`` is never included in the returned set, even if it is provided in
1029 ``nullrev`` is never included in the returned set, even if it is provided in
1029 the input set.
1030 the input set.
1030 """
1031 """
1031 headrevs = set(revs)
1032 headrevs = set(revs)
1032 parents = {node.nullrev}
1033 parents = {node.nullrev}
1033 up = parents.update
1034 up = parents.update
1034
1035
1035 for rev in revs:
1036 for rev in revs:
1036 up(parentsfn(rev))
1037 up(parentsfn(rev))
1037 headrevs.difference_update(parents)
1038 headrevs.difference_update(parents)
1038 return headrevs
1039 return headrevs
1039
1040
1040
1041
1041 def headrevssubset(revsfn, parentrevsfn, startrev=None, stoprevs=None):
1042 def headrevssubset(revsfn, parentrevsfn, startrev=None, stoprevs=None):
1042 """Returns the set of all revs that have no children with control.
1043 """Returns the set of all revs that have no children with control.
1043
1044
1044 ``revsfn`` is a callable that with no arguments returns an iterator over
1045 ``revsfn`` is a callable that with no arguments returns an iterator over
1045 all revision numbers in topological order. With a ``start`` argument, it
1046 all revision numbers in topological order. With a ``start`` argument, it
1046 returns revision numbers starting at that number.
1047 returns revision numbers starting at that number.
1047
1048
1048 ``parentrevsfn`` is a callable receiving a revision number and returns an
1049 ``parentrevsfn`` is a callable receiving a revision number and returns an
1049 iterable of parent revision numbers, where values can include nullrev.
1050 iterable of parent revision numbers, where values can include nullrev.
1050
1051
1051 ``startrev`` is a revision number at which to start the search.
1052 ``startrev`` is a revision number at which to start the search.
1052
1053
1053 ``stoprevs`` is an iterable of revision numbers that, when encountered,
1054 ``stoprevs`` is an iterable of revision numbers that, when encountered,
1054 will stop DAG traversal beyond them. Parents of revisions in this
1055 will stop DAG traversal beyond them. Parents of revisions in this
1055 collection will be heads.
1056 collection will be heads.
1056 """
1057 """
1057 if startrev is None:
1058 if startrev is None:
1058 startrev = nullrev
1059 startrev = nullrev
1059
1060
1060 stoprevs = set(stoprevs or [])
1061 stoprevs = set(stoprevs or [])
1061
1062
1062 reachable = {startrev}
1063 reachable = {startrev}
1063 heads = {startrev}
1064 heads = {startrev}
1064
1065
1065 for rev in revsfn(start=startrev + 1):
1066 for rev in revsfn(start=startrev + 1):
1066 for prev in parentrevsfn(rev):
1067 for prev in parentrevsfn(rev):
1067 if prev in reachable:
1068 if prev in reachable:
1068 if rev not in stoprevs:
1069 if rev not in stoprevs:
1069 reachable.add(rev)
1070 reachable.add(rev)
1070 heads.add(rev)
1071 heads.add(rev)
1071
1072
1072 if prev in heads and prev not in stoprevs:
1073 if prev in heads and prev not in stoprevs:
1073 heads.remove(prev)
1074 heads.remove(prev)
1074
1075
1075 return heads
1076 return heads
1076
1077
1077
1078
1078 def linearize(revs, parentsfn):
1079 def linearize(revs, parentsfn):
1079 """Linearize and topologically sort a list of revisions.
1080 """Linearize and topologically sort a list of revisions.
1080
1081
1081 The linearization process tries to create long runs of revs where a child
1082 The linearization process tries to create long runs of revs where a child
1082 rev comes immediately after its first parent. This is done by visiting the
1083 rev comes immediately after its first parent. This is done by visiting the
1083 heads of the revs in inverse topological order, and for each visited rev,
1084 heads of the revs in inverse topological order, and for each visited rev,
1084 visiting its second parent, then its first parent, then adding the rev
1085 visiting its second parent, then its first parent, then adding the rev
1085 itself to the output list.
1086 itself to the output list.
1086
1087
1087 Returns a list of revision numbers.
1088 Returns a list of revision numbers.
1088 """
1089 """
1089 visit = list(sorted(headrevs(revs, parentsfn), reverse=True))
1090 visit = list(sorted(headrevs(revs, parentsfn), reverse=True))
1090 finished = set()
1091 finished = set()
1091 result = []
1092 result = []
1092
1093
1093 while visit:
1094 while visit:
1094 rev = visit.pop()
1095 rev = visit.pop()
1095 if rev < 0:
1096 if rev < 0:
1096 rev = -rev - 1
1097 rev = -rev - 1
1097
1098
1098 if rev not in finished:
1099 if rev not in finished:
1099 result.append(rev)
1100 result.append(rev)
1100 finished.add(rev)
1101 finished.add(rev)
1101
1102
1102 else:
1103 else:
1103 visit.append(-rev - 1)
1104 visit.append(-rev - 1)
1104
1105
1105 for prev in parentsfn(rev):
1106 for prev in parentsfn(rev):
1106 if prev == node.nullrev or prev not in revs or prev in finished:
1107 if prev == node.nullrev or prev not in revs or prev in finished:
1107 continue
1108 continue
1108
1109
1109 visit.append(prev)
1110 visit.append(prev)
1110
1111
1111 assert len(result) == len(revs)
1112 assert len(result) == len(revs)
1112
1113
1113 return result
1114 return result
@@ -1,1085 +1,1085 b''
1 # logcmdutil.py - utility for log-like commands
1 # logcmdutil.py - utility for log-like commands
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import itertools
10 import itertools
11 import os
11 import os
12 import posixpath
12 import posixpath
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 nullid,
16 nullid,
17 wdirid,
17 wdirid,
18 wdirrev,
18 wdirrev,
19 )
19 )
20
20
21 from . import (
21 from . import (
22 dagop,
22 dagop,
23 error,
23 error,
24 formatter,
24 formatter,
25 graphmod,
25 graphmod,
26 match as matchmod,
26 match as matchmod,
27 mdiff,
27 mdiff,
28 patch,
28 patch,
29 pathutil,
29 pathutil,
30 pycompat,
30 pycompat,
31 revset,
31 revset,
32 revsetlang,
32 revsetlang,
33 scmutil,
33 scmutil,
34 smartset,
34 smartset,
35 templatekw,
35 templatekw,
36 templater,
36 templater,
37 util,
37 util,
38 )
38 )
39 from .utils import (
39 from .utils import (
40 dateutil,
40 dateutil,
41 stringutil,
41 stringutil,
42 )
42 )
43
43
44
44
45 if pycompat.TYPE_CHECKING:
45 if pycompat.TYPE_CHECKING:
46 from typing import (
46 from typing import (
47 Any,
47 Any,
48 Optional,
48 Optional,
49 Tuple,
49 Tuple,
50 )
50 )
51
51
52 for t in (Any, Optional, Tuple):
52 for t in (Any, Optional, Tuple):
53 assert t
53 assert t
54
54
55
55
56 def getlimit(opts):
56 def getlimit(opts):
57 """get the log limit according to option -l/--limit"""
57 """get the log limit according to option -l/--limit"""
58 limit = opts.get(b'limit')
58 limit = opts.get(b'limit')
59 if limit:
59 if limit:
60 try:
60 try:
61 limit = int(limit)
61 limit = int(limit)
62 except ValueError:
62 except ValueError:
63 raise error.Abort(_(b'limit must be a positive integer'))
63 raise error.Abort(_(b'limit must be a positive integer'))
64 if limit <= 0:
64 if limit <= 0:
65 raise error.Abort(_(b'limit must be positive'))
65 raise error.Abort(_(b'limit must be positive'))
66 else:
66 else:
67 limit = None
67 limit = None
68 return limit
68 return limit
69
69
70
70
71 def diffordiffstat(
71 def diffordiffstat(
72 ui,
72 ui,
73 repo,
73 repo,
74 diffopts,
74 diffopts,
75 ctx1,
75 ctx1,
76 ctx2,
76 ctx2,
77 match,
77 match,
78 changes=None,
78 changes=None,
79 stat=False,
79 stat=False,
80 fp=None,
80 fp=None,
81 graphwidth=0,
81 graphwidth=0,
82 prefix=b'',
82 prefix=b'',
83 root=b'',
83 root=b'',
84 listsubrepos=False,
84 listsubrepos=False,
85 hunksfilterfn=None,
85 hunksfilterfn=None,
86 ):
86 ):
87 '''show diff or diffstat.'''
87 '''show diff or diffstat.'''
88 if root:
88 if root:
89 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
89 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
90 else:
90 else:
91 relroot = b''
91 relroot = b''
92 copysourcematch = None
92 copysourcematch = None
93
93
94 def compose(f, g):
94 def compose(f, g):
95 return lambda x: f(g(x))
95 return lambda x: f(g(x))
96
96
97 def pathfn(f):
97 def pathfn(f):
98 return posixpath.join(prefix, f)
98 return posixpath.join(prefix, f)
99
99
100 if relroot != b'':
100 if relroot != b'':
101 # XXX relative roots currently don't work if the root is within a
101 # XXX relative roots currently don't work if the root is within a
102 # subrepo
102 # subrepo
103 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
103 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
104 uirelroot = uipathfn(pathfn(relroot))
104 uirelroot = uipathfn(pathfn(relroot))
105 relroot += b'/'
105 relroot += b'/'
106 for matchroot in match.files():
106 for matchroot in match.files():
107 if not matchroot.startswith(relroot):
107 if not matchroot.startswith(relroot):
108 ui.warn(
108 ui.warn(
109 _(b'warning: %s not inside relative root %s\n')
109 _(b'warning: %s not inside relative root %s\n')
110 % (uipathfn(pathfn(matchroot)), uirelroot)
110 % (uipathfn(pathfn(matchroot)), uirelroot)
111 )
111 )
112
112
113 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path')
113 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path')
114 match = matchmod.intersectmatchers(match, relrootmatch)
114 match = matchmod.intersectmatchers(match, relrootmatch)
115 copysourcematch = relrootmatch
115 copysourcematch = relrootmatch
116
116
117 checkroot = repo.ui.configbool(
117 checkroot = repo.ui.configbool(
118 b'devel', b'all-warnings'
118 b'devel', b'all-warnings'
119 ) or repo.ui.configbool(b'devel', b'check-relroot')
119 ) or repo.ui.configbool(b'devel', b'check-relroot')
120
120
121 def relrootpathfn(f):
121 def relrootpathfn(f):
122 if checkroot and not f.startswith(relroot):
122 if checkroot and not f.startswith(relroot):
123 raise AssertionError(
123 raise AssertionError(
124 b"file %s doesn't start with relroot %s" % (f, relroot)
124 b"file %s doesn't start with relroot %s" % (f, relroot)
125 )
125 )
126 return f[len(relroot) :]
126 return f[len(relroot) :]
127
127
128 pathfn = compose(relrootpathfn, pathfn)
128 pathfn = compose(relrootpathfn, pathfn)
129
129
130 if stat:
130 if stat:
131 diffopts = diffopts.copy(context=0, noprefix=False)
131 diffopts = diffopts.copy(context=0, noprefix=False)
132 width = 80
132 width = 80
133 if not ui.plain():
133 if not ui.plain():
134 width = ui.termwidth() - graphwidth
134 width = ui.termwidth() - graphwidth
135 # If an explicit --root was given, don't respect ui.relative-paths
135 # If an explicit --root was given, don't respect ui.relative-paths
136 if not relroot:
136 if not relroot:
137 pathfn = compose(scmutil.getuipathfn(repo), pathfn)
137 pathfn = compose(scmutil.getuipathfn(repo), pathfn)
138
138
139 chunks = ctx2.diff(
139 chunks = ctx2.diff(
140 ctx1,
140 ctx1,
141 match,
141 match,
142 changes,
142 changes,
143 opts=diffopts,
143 opts=diffopts,
144 pathfn=pathfn,
144 pathfn=pathfn,
145 copysourcematch=copysourcematch,
145 copysourcematch=copysourcematch,
146 hunksfilterfn=hunksfilterfn,
146 hunksfilterfn=hunksfilterfn,
147 )
147 )
148
148
149 if fp is not None or ui.canwritewithoutlabels():
149 if fp is not None or ui.canwritewithoutlabels():
150 out = fp or ui
150 out = fp or ui
151 if stat:
151 if stat:
152 chunks = [patch.diffstat(util.iterlines(chunks), width=width)]
152 chunks = [patch.diffstat(util.iterlines(chunks), width=width)]
153 for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
153 for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
154 out.write(chunk)
154 out.write(chunk)
155 else:
155 else:
156 if stat:
156 if stat:
157 chunks = patch.diffstatui(util.iterlines(chunks), width=width)
157 chunks = patch.diffstatui(util.iterlines(chunks), width=width)
158 else:
158 else:
159 chunks = patch.difflabel(
159 chunks = patch.difflabel(
160 lambda chunks, **kwargs: chunks, chunks, opts=diffopts
160 lambda chunks, **kwargs: chunks, chunks, opts=diffopts
161 )
161 )
162 if ui.canbatchlabeledwrites():
162 if ui.canbatchlabeledwrites():
163
163
164 def gen():
164 def gen():
165 for chunk, label in chunks:
165 for chunk, label in chunks:
166 yield ui.label(chunk, label=label)
166 yield ui.label(chunk, label=label)
167
167
168 for chunk in util.filechunkiter(util.chunkbuffer(gen())):
168 for chunk in util.filechunkiter(util.chunkbuffer(gen())):
169 ui.write(chunk)
169 ui.write(chunk)
170 else:
170 else:
171 for chunk, label in chunks:
171 for chunk, label in chunks:
172 ui.write(chunk, label=label)
172 ui.write(chunk, label=label)
173
173
174 node2 = ctx2.node()
174 node2 = ctx2.node()
175 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
175 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
176 tempnode2 = node2
176 tempnode2 = node2
177 try:
177 try:
178 if node2 is not None:
178 if node2 is not None:
179 tempnode2 = ctx2.substate[subpath][1]
179 tempnode2 = ctx2.substate[subpath][1]
180 except KeyError:
180 except KeyError:
181 # A subrepo that existed in node1 was deleted between node1 and
181 # A subrepo that existed in node1 was deleted between node1 and
182 # node2 (inclusive). Thus, ctx2's substate won't contain that
182 # node2 (inclusive). Thus, ctx2's substate won't contain that
183 # subpath. The best we can do is to ignore it.
183 # subpath. The best we can do is to ignore it.
184 tempnode2 = None
184 tempnode2 = None
185 submatch = matchmod.subdirmatcher(subpath, match)
185 submatch = matchmod.subdirmatcher(subpath, match)
186 subprefix = repo.wvfs.reljoin(prefix, subpath)
186 subprefix = repo.wvfs.reljoin(prefix, subpath)
187 if listsubrepos or match.exact(subpath) or any(submatch.files()):
187 if listsubrepos or match.exact(subpath) or any(submatch.files()):
188 sub.diff(
188 sub.diff(
189 ui,
189 ui,
190 diffopts,
190 diffopts,
191 tempnode2,
191 tempnode2,
192 submatch,
192 submatch,
193 changes=changes,
193 changes=changes,
194 stat=stat,
194 stat=stat,
195 fp=fp,
195 fp=fp,
196 prefix=subprefix,
196 prefix=subprefix,
197 )
197 )
198
198
199
199
200 class changesetdiffer(object):
200 class changesetdiffer(object):
201 """Generate diff of changeset with pre-configured filtering functions"""
201 """Generate diff of changeset with pre-configured filtering functions"""
202
202
203 def _makefilematcher(self, ctx):
203 def _makefilematcher(self, ctx):
204 return scmutil.matchall(ctx.repo())
204 return scmutil.matchall(ctx.repo())
205
205
206 def _makehunksfilter(self, ctx):
206 def _makehunksfilter(self, ctx):
207 return None
207 return None
208
208
209 def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
209 def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
210 diffordiffstat(
210 diffordiffstat(
211 ui,
211 ui,
212 ctx.repo(),
212 ctx.repo(),
213 diffopts,
213 diffopts,
214 ctx.p1(),
214 ctx.p1(),
215 ctx,
215 ctx,
216 match=self._makefilematcher(ctx),
216 match=self._makefilematcher(ctx),
217 stat=stat,
217 stat=stat,
218 graphwidth=graphwidth,
218 graphwidth=graphwidth,
219 hunksfilterfn=self._makehunksfilter(ctx),
219 hunksfilterfn=self._makehunksfilter(ctx),
220 )
220 )
221
221
222
222
223 def changesetlabels(ctx):
223 def changesetlabels(ctx):
224 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()]
224 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()]
225 if ctx.obsolete():
225 if ctx.obsolete():
226 labels.append(b'changeset.obsolete')
226 labels.append(b'changeset.obsolete')
227 if ctx.isunstable():
227 if ctx.isunstable():
228 labels.append(b'changeset.unstable')
228 labels.append(b'changeset.unstable')
229 for instability in ctx.instabilities():
229 for instability in ctx.instabilities():
230 labels.append(b'instability.%s' % instability)
230 labels.append(b'instability.%s' % instability)
231 return b' '.join(labels)
231 return b' '.join(labels)
232
232
233
233
234 class changesetprinter(object):
234 class changesetprinter(object):
235 '''show changeset information when templating not requested.'''
235 '''show changeset information when templating not requested.'''
236
236
237 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
237 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
238 self.ui = ui
238 self.ui = ui
239 self.repo = repo
239 self.repo = repo
240 self.buffered = buffered
240 self.buffered = buffered
241 self._differ = differ or changesetdiffer()
241 self._differ = differ or changesetdiffer()
242 self._diffopts = patch.diffallopts(ui, diffopts)
242 self._diffopts = patch.diffallopts(ui, diffopts)
243 self._includestat = diffopts and diffopts.get(b'stat')
243 self._includestat = diffopts and diffopts.get(b'stat')
244 self._includediff = diffopts and diffopts.get(b'patch')
244 self._includediff = diffopts and diffopts.get(b'patch')
245 self.header = {}
245 self.header = {}
246 self.hunk = {}
246 self.hunk = {}
247 self.lastheader = None
247 self.lastheader = None
248 self.footer = None
248 self.footer = None
249 self._columns = templatekw.getlogcolumns()
249 self._columns = templatekw.getlogcolumns()
250
250
251 def flush(self, ctx):
251 def flush(self, ctx):
252 rev = ctx.rev()
252 rev = ctx.rev()
253 if rev in self.header:
253 if rev in self.header:
254 h = self.header[rev]
254 h = self.header[rev]
255 if h != self.lastheader:
255 if h != self.lastheader:
256 self.lastheader = h
256 self.lastheader = h
257 self.ui.write(h)
257 self.ui.write(h)
258 del self.header[rev]
258 del self.header[rev]
259 if rev in self.hunk:
259 if rev in self.hunk:
260 self.ui.write(self.hunk[rev])
260 self.ui.write(self.hunk[rev])
261 del self.hunk[rev]
261 del self.hunk[rev]
262
262
263 def close(self):
263 def close(self):
264 if self.footer:
264 if self.footer:
265 self.ui.write(self.footer)
265 self.ui.write(self.footer)
266
266
267 def show(self, ctx, copies=None, **props):
267 def show(self, ctx, copies=None, **props):
268 props = pycompat.byteskwargs(props)
268 props = pycompat.byteskwargs(props)
269 if self.buffered:
269 if self.buffered:
270 self.ui.pushbuffer(labeled=True)
270 self.ui.pushbuffer(labeled=True)
271 self._show(ctx, copies, props)
271 self._show(ctx, copies, props)
272 self.hunk[ctx.rev()] = self.ui.popbuffer()
272 self.hunk[ctx.rev()] = self.ui.popbuffer()
273 else:
273 else:
274 self._show(ctx, copies, props)
274 self._show(ctx, copies, props)
275
275
276 def _show(self, ctx, copies, props):
276 def _show(self, ctx, copies, props):
277 '''show a single changeset or file revision'''
277 '''show a single changeset or file revision'''
278 changenode = ctx.node()
278 changenode = ctx.node()
279 graphwidth = props.get(b'graphwidth', 0)
279 graphwidth = props.get(b'graphwidth', 0)
280
280
281 if self.ui.quiet:
281 if self.ui.quiet:
282 self.ui.write(
282 self.ui.write(
283 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node'
283 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node'
284 )
284 )
285 return
285 return
286
286
287 columns = self._columns
287 columns = self._columns
288 self.ui.write(
288 self.ui.write(
289 columns[b'changeset'] % scmutil.formatchangeid(ctx),
289 columns[b'changeset'] % scmutil.formatchangeid(ctx),
290 label=changesetlabels(ctx),
290 label=changesetlabels(ctx),
291 )
291 )
292
292
293 # branches are shown first before any other names due to backwards
293 # branches are shown first before any other names due to backwards
294 # compatibility
294 # compatibility
295 branch = ctx.branch()
295 branch = ctx.branch()
296 # don't show the default branch name
296 # don't show the default branch name
297 if branch != b'default':
297 if branch != b'default':
298 self.ui.write(columns[b'branch'] % branch, label=b'log.branch')
298 self.ui.write(columns[b'branch'] % branch, label=b'log.branch')
299
299
300 for nsname, ns in pycompat.iteritems(self.repo.names):
300 for nsname, ns in pycompat.iteritems(self.repo.names):
301 # branches has special logic already handled above, so here we just
301 # branches has special logic already handled above, so here we just
302 # skip it
302 # skip it
303 if nsname == b'branches':
303 if nsname == b'branches':
304 continue
304 continue
305 # we will use the templatename as the color name since those two
305 # we will use the templatename as the color name since those two
306 # should be the same
306 # should be the same
307 for name in ns.names(self.repo, changenode):
307 for name in ns.names(self.repo, changenode):
308 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname)
308 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname)
309 if self.ui.debugflag:
309 if self.ui.debugflag:
310 self.ui.write(
310 self.ui.write(
311 columns[b'phase'] % ctx.phasestr(), label=b'log.phase'
311 columns[b'phase'] % ctx.phasestr(), label=b'log.phase'
312 )
312 )
313 for pctx in scmutil.meaningfulparents(self.repo, ctx):
313 for pctx in scmutil.meaningfulparents(self.repo, ctx):
314 label = b'log.parent changeset.%s' % pctx.phasestr()
314 label = b'log.parent changeset.%s' % pctx.phasestr()
315 self.ui.write(
315 self.ui.write(
316 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label
316 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label
317 )
317 )
318
318
319 if self.ui.debugflag:
319 if self.ui.debugflag:
320 mnode = ctx.manifestnode()
320 mnode = ctx.manifestnode()
321 if mnode is None:
321 if mnode is None:
322 mnode = wdirid
322 mnode = wdirid
323 mrev = wdirrev
323 mrev = wdirrev
324 else:
324 else:
325 mrev = self.repo.manifestlog.rev(mnode)
325 mrev = self.repo.manifestlog.rev(mnode)
326 self.ui.write(
326 self.ui.write(
327 columns[b'manifest']
327 columns[b'manifest']
328 % scmutil.formatrevnode(self.ui, mrev, mnode),
328 % scmutil.formatrevnode(self.ui, mrev, mnode),
329 label=b'ui.debug log.manifest',
329 label=b'ui.debug log.manifest',
330 )
330 )
331 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user')
331 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user')
332 self.ui.write(
332 self.ui.write(
333 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date'
333 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date'
334 )
334 )
335
335
336 if ctx.isunstable():
336 if ctx.isunstable():
337 instabilities = ctx.instabilities()
337 instabilities = ctx.instabilities()
338 self.ui.write(
338 self.ui.write(
339 columns[b'instability'] % b', '.join(instabilities),
339 columns[b'instability'] % b', '.join(instabilities),
340 label=b'log.instability',
340 label=b'log.instability',
341 )
341 )
342
342
343 elif ctx.obsolete():
343 elif ctx.obsolete():
344 self._showobsfate(ctx)
344 self._showobsfate(ctx)
345
345
346 self._exthook(ctx)
346 self._exthook(ctx)
347
347
348 if self.ui.debugflag:
348 if self.ui.debugflag:
349 files = ctx.p1().status(ctx)
349 files = ctx.p1().status(ctx)
350 for key, value in zip(
350 for key, value in zip(
351 [b'files', b'files+', b'files-'],
351 [b'files', b'files+', b'files-'],
352 [files.modified, files.added, files.removed],
352 [files.modified, files.added, files.removed],
353 ):
353 ):
354 if value:
354 if value:
355 self.ui.write(
355 self.ui.write(
356 columns[key] % b" ".join(value),
356 columns[key] % b" ".join(value),
357 label=b'ui.debug log.files',
357 label=b'ui.debug log.files',
358 )
358 )
359 elif ctx.files() and self.ui.verbose:
359 elif ctx.files() and self.ui.verbose:
360 self.ui.write(
360 self.ui.write(
361 columns[b'files'] % b" ".join(ctx.files()),
361 columns[b'files'] % b" ".join(ctx.files()),
362 label=b'ui.note log.files',
362 label=b'ui.note log.files',
363 )
363 )
364 if copies and self.ui.verbose:
364 if copies and self.ui.verbose:
365 copies = [b'%s (%s)' % c for c in copies]
365 copies = [b'%s (%s)' % c for c in copies]
366 self.ui.write(
366 self.ui.write(
367 columns[b'copies'] % b' '.join(copies),
367 columns[b'copies'] % b' '.join(copies),
368 label=b'ui.note log.copies',
368 label=b'ui.note log.copies',
369 )
369 )
370
370
371 extra = ctx.extra()
371 extra = ctx.extra()
372 if extra and self.ui.debugflag:
372 if extra and self.ui.debugflag:
373 for key, value in sorted(extra.items()):
373 for key, value in sorted(extra.items()):
374 self.ui.write(
374 self.ui.write(
375 columns[b'extra'] % (key, stringutil.escapestr(value)),
375 columns[b'extra'] % (key, stringutil.escapestr(value)),
376 label=b'ui.debug log.extra',
376 label=b'ui.debug log.extra',
377 )
377 )
378
378
379 description = ctx.description().strip()
379 description = ctx.description().strip()
380 if description:
380 if description:
381 if self.ui.verbose:
381 if self.ui.verbose:
382 self.ui.write(
382 self.ui.write(
383 _(b"description:\n"), label=b'ui.note log.description'
383 _(b"description:\n"), label=b'ui.note log.description'
384 )
384 )
385 self.ui.write(description, label=b'ui.note log.description')
385 self.ui.write(description, label=b'ui.note log.description')
386 self.ui.write(b"\n\n")
386 self.ui.write(b"\n\n")
387 else:
387 else:
388 self.ui.write(
388 self.ui.write(
389 columns[b'summary'] % description.splitlines()[0],
389 columns[b'summary'] % description.splitlines()[0],
390 label=b'log.summary',
390 label=b'log.summary',
391 )
391 )
392 self.ui.write(b"\n")
392 self.ui.write(b"\n")
393
393
394 self._showpatch(ctx, graphwidth)
394 self._showpatch(ctx, graphwidth)
395
395
396 def _showobsfate(self, ctx):
396 def _showobsfate(self, ctx):
397 # TODO: do not depend on templater
397 # TODO: do not depend on templater
398 tres = formatter.templateresources(self.repo.ui, self.repo)
398 tres = formatter.templateresources(self.repo.ui, self.repo)
399 t = formatter.maketemplater(
399 t = formatter.maketemplater(
400 self.repo.ui,
400 self.repo.ui,
401 b'{join(obsfate, "\n")}',
401 b'{join(obsfate, "\n")}',
402 defaults=templatekw.keywords,
402 defaults=templatekw.keywords,
403 resources=tres,
403 resources=tres,
404 )
404 )
405 obsfate = t.renderdefault({b'ctx': ctx}).splitlines()
405 obsfate = t.renderdefault({b'ctx': ctx}).splitlines()
406
406
407 if obsfate:
407 if obsfate:
408 for obsfateline in obsfate:
408 for obsfateline in obsfate:
409 self.ui.write(
409 self.ui.write(
410 self._columns[b'obsolete'] % obsfateline,
410 self._columns[b'obsolete'] % obsfateline,
411 label=b'log.obsfate',
411 label=b'log.obsfate',
412 )
412 )
413
413
414 def _exthook(self, ctx):
414 def _exthook(self, ctx):
415 '''empty method used by extension as a hook point
415 '''empty method used by extension as a hook point
416 '''
416 '''
417
417
418 def _showpatch(self, ctx, graphwidth=0):
418 def _showpatch(self, ctx, graphwidth=0):
419 if self._includestat:
419 if self._includestat:
420 self._differ.showdiff(
420 self._differ.showdiff(
421 self.ui, ctx, self._diffopts, graphwidth, stat=True
421 self.ui, ctx, self._diffopts, graphwidth, stat=True
422 )
422 )
423 if self._includestat and self._includediff:
423 if self._includestat and self._includediff:
424 self.ui.write(b"\n")
424 self.ui.write(b"\n")
425 if self._includediff:
425 if self._includediff:
426 self._differ.showdiff(
426 self._differ.showdiff(
427 self.ui, ctx, self._diffopts, graphwidth, stat=False
427 self.ui, ctx, self._diffopts, graphwidth, stat=False
428 )
428 )
429 if self._includestat or self._includediff:
429 if self._includestat or self._includediff:
430 self.ui.write(b"\n")
430 self.ui.write(b"\n")
431
431
432
432
433 class changesetformatter(changesetprinter):
433 class changesetformatter(changesetprinter):
434 """Format changeset information by generic formatter"""
434 """Format changeset information by generic formatter"""
435
435
436 def __init__(
436 def __init__(
437 self, ui, repo, fm, differ=None, diffopts=None, buffered=False
437 self, ui, repo, fm, differ=None, diffopts=None, buffered=False
438 ):
438 ):
439 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
439 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
440 self._diffopts = patch.difffeatureopts(ui, diffopts, git=True)
440 self._diffopts = patch.difffeatureopts(ui, diffopts, git=True)
441 self._fm = fm
441 self._fm = fm
442
442
443 def close(self):
443 def close(self):
444 self._fm.end()
444 self._fm.end()
445
445
446 def _show(self, ctx, copies, props):
446 def _show(self, ctx, copies, props):
447 '''show a single changeset or file revision'''
447 '''show a single changeset or file revision'''
448 fm = self._fm
448 fm = self._fm
449 fm.startitem()
449 fm.startitem()
450 fm.context(ctx=ctx)
450 fm.context(ctx=ctx)
451 fm.data(rev=scmutil.intrev(ctx), node=fm.hexfunc(scmutil.binnode(ctx)))
451 fm.data(rev=scmutil.intrev(ctx), node=fm.hexfunc(scmutil.binnode(ctx)))
452
452
453 datahint = fm.datahint()
453 datahint = fm.datahint()
454 if self.ui.quiet and not datahint:
454 if self.ui.quiet and not datahint:
455 return
455 return
456
456
457 fm.data(
457 fm.data(
458 branch=ctx.branch(),
458 branch=ctx.branch(),
459 phase=ctx.phasestr(),
459 phase=ctx.phasestr(),
460 user=ctx.user(),
460 user=ctx.user(),
461 date=fm.formatdate(ctx.date()),
461 date=fm.formatdate(ctx.date()),
462 desc=ctx.description(),
462 desc=ctx.description(),
463 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'),
463 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'),
464 tags=fm.formatlist(ctx.tags(), name=b'tag'),
464 tags=fm.formatlist(ctx.tags(), name=b'tag'),
465 parents=fm.formatlist(
465 parents=fm.formatlist(
466 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node'
466 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node'
467 ),
467 ),
468 )
468 )
469
469
470 if self.ui.debugflag or b'manifest' in datahint:
470 if self.ui.debugflag or b'manifest' in datahint:
471 fm.data(manifest=fm.hexfunc(ctx.manifestnode() or wdirid))
471 fm.data(manifest=fm.hexfunc(ctx.manifestnode() or wdirid))
472 if self.ui.debugflag or b'extra' in datahint:
472 if self.ui.debugflag or b'extra' in datahint:
473 fm.data(extra=fm.formatdict(ctx.extra()))
473 fm.data(extra=fm.formatdict(ctx.extra()))
474
474
475 if (
475 if (
476 self.ui.debugflag
476 self.ui.debugflag
477 or b'modified' in datahint
477 or b'modified' in datahint
478 or b'added' in datahint
478 or b'added' in datahint
479 or b'removed' in datahint
479 or b'removed' in datahint
480 ):
480 ):
481 files = ctx.p1().status(ctx)
481 files = ctx.p1().status(ctx)
482 fm.data(
482 fm.data(
483 modified=fm.formatlist(files.modified, name=b'file'),
483 modified=fm.formatlist(files.modified, name=b'file'),
484 added=fm.formatlist(files.added, name=b'file'),
484 added=fm.formatlist(files.added, name=b'file'),
485 removed=fm.formatlist(files.removed, name=b'file'),
485 removed=fm.formatlist(files.removed, name=b'file'),
486 )
486 )
487
487
488 verbose = not self.ui.debugflag and self.ui.verbose
488 verbose = not self.ui.debugflag and self.ui.verbose
489 if verbose or b'files' in datahint:
489 if verbose or b'files' in datahint:
490 fm.data(files=fm.formatlist(ctx.files(), name=b'file'))
490 fm.data(files=fm.formatlist(ctx.files(), name=b'file'))
491 if verbose and copies or b'copies' in datahint:
491 if verbose and copies or b'copies' in datahint:
492 fm.data(
492 fm.data(
493 copies=fm.formatdict(copies or {}, key=b'name', value=b'source')
493 copies=fm.formatdict(copies or {}, key=b'name', value=b'source')
494 )
494 )
495
495
496 if self._includestat or b'diffstat' in datahint:
496 if self._includestat or b'diffstat' in datahint:
497 self.ui.pushbuffer()
497 self.ui.pushbuffer()
498 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True)
498 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True)
499 fm.data(diffstat=self.ui.popbuffer())
499 fm.data(diffstat=self.ui.popbuffer())
500 if self._includediff or b'diff' in datahint:
500 if self._includediff or b'diff' in datahint:
501 self.ui.pushbuffer()
501 self.ui.pushbuffer()
502 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False)
502 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False)
503 fm.data(diff=self.ui.popbuffer())
503 fm.data(diff=self.ui.popbuffer())
504
504
505
505
506 class changesettemplater(changesetprinter):
506 class changesettemplater(changesetprinter):
507 '''format changeset information.
507 '''format changeset information.
508
508
509 Note: there are a variety of convenience functions to build a
509 Note: there are a variety of convenience functions to build a
510 changesettemplater for common cases. See functions such as:
510 changesettemplater for common cases. See functions such as:
511 maketemplater, changesetdisplayer, buildcommittemplate, or other
511 maketemplater, changesetdisplayer, buildcommittemplate, or other
512 functions that use changesest_templater.
512 functions that use changesest_templater.
513 '''
513 '''
514
514
515 # Arguments before "buffered" used to be positional. Consider not
515 # Arguments before "buffered" used to be positional. Consider not
516 # adding/removing arguments before "buffered" to not break callers.
516 # adding/removing arguments before "buffered" to not break callers.
517 def __init__(
517 def __init__(
518 self, ui, repo, tmplspec, differ=None, diffopts=None, buffered=False
518 self, ui, repo, tmplspec, differ=None, diffopts=None, buffered=False
519 ):
519 ):
520 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
520 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
521 # tres is shared with _graphnodeformatter()
521 # tres is shared with _graphnodeformatter()
522 self._tresources = tres = formatter.templateresources(ui, repo)
522 self._tresources = tres = formatter.templateresources(ui, repo)
523 self.t = formatter.loadtemplater(
523 self.t = formatter.loadtemplater(
524 ui,
524 ui,
525 tmplspec,
525 tmplspec,
526 defaults=templatekw.keywords,
526 defaults=templatekw.keywords,
527 resources=tres,
527 resources=tres,
528 cache=templatekw.defaulttempl,
528 cache=templatekw.defaulttempl,
529 )
529 )
530 self._counter = itertools.count()
530 self._counter = itertools.count()
531
531
532 self._tref = tmplspec.ref
532 self._tref = tmplspec.ref
533 self._parts = {
533 self._parts = {
534 b'header': b'',
534 b'header': b'',
535 b'footer': b'',
535 b'footer': b'',
536 tmplspec.ref: tmplspec.ref,
536 tmplspec.ref: tmplspec.ref,
537 b'docheader': b'',
537 b'docheader': b'',
538 b'docfooter': b'',
538 b'docfooter': b'',
539 b'separator': b'',
539 b'separator': b'',
540 }
540 }
541 if tmplspec.mapfile:
541 if tmplspec.mapfile:
542 # find correct templates for current mode, for backward
542 # find correct templates for current mode, for backward
543 # compatibility with 'log -v/-q/--debug' using a mapfile
543 # compatibility with 'log -v/-q/--debug' using a mapfile
544 tmplmodes = [
544 tmplmodes = [
545 (True, b''),
545 (True, b''),
546 (self.ui.verbose, b'_verbose'),
546 (self.ui.verbose, b'_verbose'),
547 (self.ui.quiet, b'_quiet'),
547 (self.ui.quiet, b'_quiet'),
548 (self.ui.debugflag, b'_debug'),
548 (self.ui.debugflag, b'_debug'),
549 ]
549 ]
550 for mode, postfix in tmplmodes:
550 for mode, postfix in tmplmodes:
551 for t in self._parts:
551 for t in self._parts:
552 cur = t + postfix
552 cur = t + postfix
553 if mode and cur in self.t:
553 if mode and cur in self.t:
554 self._parts[t] = cur
554 self._parts[t] = cur
555 else:
555 else:
556 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
556 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
557 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
557 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
558 self._parts.update(m)
558 self._parts.update(m)
559
559
560 if self._parts[b'docheader']:
560 if self._parts[b'docheader']:
561 self.ui.write(self.t.render(self._parts[b'docheader'], {}))
561 self.ui.write(self.t.render(self._parts[b'docheader'], {}))
562
562
563 def close(self):
563 def close(self):
564 if self._parts[b'docfooter']:
564 if self._parts[b'docfooter']:
565 if not self.footer:
565 if not self.footer:
566 self.footer = b""
566 self.footer = b""
567 self.footer += self.t.render(self._parts[b'docfooter'], {})
567 self.footer += self.t.render(self._parts[b'docfooter'], {})
568 return super(changesettemplater, self).close()
568 return super(changesettemplater, self).close()
569
569
570 def _show(self, ctx, copies, props):
570 def _show(self, ctx, copies, props):
571 '''show a single changeset or file revision'''
571 '''show a single changeset or file revision'''
572 props = props.copy()
572 props = props.copy()
573 props[b'ctx'] = ctx
573 props[b'ctx'] = ctx
574 props[b'index'] = index = next(self._counter)
574 props[b'index'] = index = next(self._counter)
575 props[b'revcache'] = {b'copies': copies}
575 props[b'revcache'] = {b'copies': copies}
576 graphwidth = props.get(b'graphwidth', 0)
576 graphwidth = props.get(b'graphwidth', 0)
577
577
578 # write separator, which wouldn't work well with the header part below
578 # write separator, which wouldn't work well with the header part below
579 # since there's inherently a conflict between header (across items) and
579 # since there's inherently a conflict between header (across items) and
580 # separator (per item)
580 # separator (per item)
581 if self._parts[b'separator'] and index > 0:
581 if self._parts[b'separator'] and index > 0:
582 self.ui.write(self.t.render(self._parts[b'separator'], {}))
582 self.ui.write(self.t.render(self._parts[b'separator'], {}))
583
583
584 # write header
584 # write header
585 if self._parts[b'header']:
585 if self._parts[b'header']:
586 h = self.t.render(self._parts[b'header'], props)
586 h = self.t.render(self._parts[b'header'], props)
587 if self.buffered:
587 if self.buffered:
588 self.header[ctx.rev()] = h
588 self.header[ctx.rev()] = h
589 else:
589 else:
590 if self.lastheader != h:
590 if self.lastheader != h:
591 self.lastheader = h
591 self.lastheader = h
592 self.ui.write(h)
592 self.ui.write(h)
593
593
594 # write changeset metadata, then patch if requested
594 # write changeset metadata, then patch if requested
595 key = self._parts[self._tref]
595 key = self._parts[self._tref]
596 self.ui.write(self.t.render(key, props))
596 self.ui.write(self.t.render(key, props))
597 self._exthook(ctx)
597 self._exthook(ctx)
598 self._showpatch(ctx, graphwidth)
598 self._showpatch(ctx, graphwidth)
599
599
600 if self._parts[b'footer']:
600 if self._parts[b'footer']:
601 if not self.footer:
601 if not self.footer:
602 self.footer = self.t.render(self._parts[b'footer'], props)
602 self.footer = self.t.render(self._parts[b'footer'], props)
603
603
604
604
605 def templatespec(tmpl, mapfile):
605 def templatespec(tmpl, mapfile):
606 assert not (tmpl and mapfile)
606 assert not (tmpl and mapfile)
607 if mapfile:
607 if mapfile:
608 return formatter.mapfile_templatespec(b'changeset', mapfile)
608 return formatter.mapfile_templatespec(b'changeset', mapfile)
609 else:
609 else:
610 return formatter.literal_templatespec(tmpl)
610 return formatter.literal_templatespec(tmpl)
611
611
612
612
613 def _lookuptemplate(ui, tmpl, style):
613 def _lookuptemplate(ui, tmpl, style):
614 """Find the template matching the given template spec or style
614 """Find the template matching the given template spec or style
615
615
616 See formatter.lookuptemplate() for details.
616 See formatter.lookuptemplate() for details.
617 """
617 """
618
618
619 # ui settings
619 # ui settings
620 if not tmpl and not style: # template are stronger than style
620 if not tmpl and not style: # template are stronger than style
621 tmpl = ui.config(b'ui', b'logtemplate')
621 tmpl = ui.config(b'ui', b'logtemplate')
622 if tmpl:
622 if tmpl:
623 return formatter.literal_templatespec(templater.unquotestring(tmpl))
623 return formatter.literal_templatespec(templater.unquotestring(tmpl))
624 else:
624 else:
625 style = util.expandpath(ui.config(b'ui', b'style'))
625 style = util.expandpath(ui.config(b'ui', b'style'))
626
626
627 if not tmpl and style:
627 if not tmpl and style:
628 mapfile = style
628 mapfile = style
629 fp = None
629 fp = None
630 if not os.path.split(mapfile)[0]:
630 if not os.path.split(mapfile)[0]:
631 (mapname, fp) = templater.try_open_template(
631 (mapname, fp) = templater.try_open_template(
632 b'map-cmdline.' + mapfile
632 b'map-cmdline.' + mapfile
633 ) or templater.try_open_template(mapfile)
633 ) or templater.try_open_template(mapfile)
634 if mapname:
634 if mapname:
635 mapfile = mapname
635 mapfile = mapname
636 return formatter.mapfile_templatespec(b'changeset', mapfile, fp)
636 return formatter.mapfile_templatespec(b'changeset', mapfile, fp)
637
637
638 return formatter.lookuptemplate(ui, b'changeset', tmpl)
638 return formatter.lookuptemplate(ui, b'changeset', tmpl)
639
639
640
640
641 def maketemplater(ui, repo, tmpl, buffered=False):
641 def maketemplater(ui, repo, tmpl, buffered=False):
642 """Create a changesettemplater from a literal template 'tmpl'
642 """Create a changesettemplater from a literal template 'tmpl'
643 byte-string."""
643 byte-string."""
644 spec = formatter.literal_templatespec(tmpl)
644 spec = formatter.literal_templatespec(tmpl)
645 return changesettemplater(ui, repo, spec, buffered=buffered)
645 return changesettemplater(ui, repo, spec, buffered=buffered)
646
646
647
647
648 def changesetdisplayer(ui, repo, opts, differ=None, buffered=False):
648 def changesetdisplayer(ui, repo, opts, differ=None, buffered=False):
649 """show one changeset using template or regular display.
649 """show one changeset using template or regular display.
650
650
651 Display format will be the first non-empty hit of:
651 Display format will be the first non-empty hit of:
652 1. option 'template'
652 1. option 'template'
653 2. option 'style'
653 2. option 'style'
654 3. [ui] setting 'logtemplate'
654 3. [ui] setting 'logtemplate'
655 4. [ui] setting 'style'
655 4. [ui] setting 'style'
656 If all of these values are either the unset or the empty string,
656 If all of these values are either the unset or the empty string,
657 regular display via changesetprinter() is done.
657 regular display via changesetprinter() is done.
658 """
658 """
659 postargs = (differ, opts, buffered)
659 postargs = (differ, opts, buffered)
660 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style'))
660 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style'))
661
661
662 # machine-readable formats have slightly different keyword set than
662 # machine-readable formats have slightly different keyword set than
663 # plain templates, which are handled by changesetformatter.
663 # plain templates, which are handled by changesetformatter.
664 # note that {b'pickle', b'debug'} can also be added to the list if needed.
664 # note that {b'pickle', b'debug'} can also be added to the list if needed.
665 if spec.ref in {b'cbor', b'json'}:
665 if spec.ref in {b'cbor', b'json'}:
666 fm = ui.formatter(b'log', opts)
666 fm = ui.formatter(b'log', opts)
667 return changesetformatter(ui, repo, fm, *postargs)
667 return changesetformatter(ui, repo, fm, *postargs)
668
668
669 if not spec.ref and not spec.tmpl and not spec.mapfile:
669 if not spec.ref and not spec.tmpl and not spec.mapfile:
670 return changesetprinter(ui, repo, *postargs)
670 return changesetprinter(ui, repo, *postargs)
671
671
672 return changesettemplater(ui, repo, spec, *postargs)
672 return changesettemplater(ui, repo, spec, *postargs)
673
673
674
674
675 def _makematcher(repo, revs, pats, opts):
675 def _makematcher(repo, revs, pats, opts):
676 """Build matcher and expanded patterns from log options
676 """Build matcher and expanded patterns from log options
677
677
678 If --follow, revs are the revisions to follow from.
678 If --follow, revs are the revisions to follow from.
679
679
680 Returns (match, pats, slowpath) where
680 Returns (match, pats, slowpath) where
681 - match: a matcher built from the given pats and -I/-X opts
681 - match: a matcher built from the given pats and -I/-X opts
682 - pats: patterns used (globs are expanded on Windows)
682 - pats: patterns used (globs are expanded on Windows)
683 - slowpath: True if patterns aren't as simple as scanning filelogs
683 - slowpath: True if patterns aren't as simple as scanning filelogs
684 """
684 """
685 # pats/include/exclude are passed to match.match() directly in
685 # pats/include/exclude are passed to match.match() directly in
686 # _matchfiles() revset but walkchangerevs() builds its matcher with
686 # _matchfiles() revset but walkchangerevs() builds its matcher with
687 # scmutil.match(). The difference is input pats are globbed on
687 # scmutil.match(). The difference is input pats are globbed on
688 # platforms without shell expansion (windows).
688 # platforms without shell expansion (windows).
689 wctx = repo[None]
689 wctx = repo[None]
690 match, pats = scmutil.matchandpats(wctx, pats, opts)
690 match, pats = scmutil.matchandpats(wctx, pats, opts)
691 slowpath = match.anypats() or (not match.always() and opts.get(b'removed'))
691 slowpath = match.anypats() or (not match.always() and opts.get(b'removed'))
692 if not slowpath:
692 if not slowpath:
693 follow = opts.get(b'follow') or opts.get(b'follow_first')
693 follow = opts.get(b'follow') or opts.get(b'follow_first')
694 startctxs = []
694 startctxs = []
695 if follow and opts.get(b'rev'):
695 if follow and opts.get(b'rev'):
696 startctxs = [repo[r] for r in revs]
696 startctxs = [repo[r] for r in revs]
697 for f in match.files():
697 for f in match.files():
698 if follow and startctxs:
698 if follow and startctxs:
699 # No idea if the path was a directory at that revision, so
699 # No idea if the path was a directory at that revision, so
700 # take the slow path.
700 # take the slow path.
701 if any(f not in c for c in startctxs):
701 if any(f not in c for c in startctxs):
702 slowpath = True
702 slowpath = True
703 continue
703 continue
704 elif follow and f not in wctx:
704 elif follow and f not in wctx:
705 # If the file exists, it may be a directory, so let it
705 # If the file exists, it may be a directory, so let it
706 # take the slow path.
706 # take the slow path.
707 if os.path.exists(repo.wjoin(f)):
707 if os.path.exists(repo.wjoin(f)):
708 slowpath = True
708 slowpath = True
709 continue
709 continue
710 else:
710 else:
711 raise error.Abort(
711 raise error.Abort(
712 _(
712 _(
713 b'cannot follow file not in parent '
713 b'cannot follow file not in parent '
714 b'revision: "%s"'
714 b'revision: "%s"'
715 )
715 )
716 % f
716 % f
717 )
717 )
718 filelog = repo.file(f)
718 filelog = repo.file(f)
719 if not filelog:
719 if not filelog:
720 # A zero count may be a directory or deleted file, so
720 # A zero count may be a directory or deleted file, so
721 # try to find matching entries on the slow path.
721 # try to find matching entries on the slow path.
722 if follow:
722 if follow:
723 raise error.Abort(
723 raise error.Abort(
724 _(b'cannot follow nonexistent file: "%s"') % f
724 _(b'cannot follow nonexistent file: "%s"') % f
725 )
725 )
726 slowpath = True
726 slowpath = True
727
727
728 # We decided to fall back to the slowpath because at least one
728 # We decided to fall back to the slowpath because at least one
729 # of the paths was not a file. Check to see if at least one of them
729 # of the paths was not a file. Check to see if at least one of them
730 # existed in history - in that case, we'll continue down the
730 # existed in history - in that case, we'll continue down the
731 # slowpath; otherwise, we can turn off the slowpath
731 # slowpath; otherwise, we can turn off the slowpath
732 if slowpath:
732 if slowpath:
733 for path in match.files():
733 for path in match.files():
734 if path == b'.' or path in repo.store:
734 if path == b'.' or path in repo.store:
735 break
735 break
736 else:
736 else:
737 slowpath = False
737 slowpath = False
738
738
739 return match, pats, slowpath
739 return match, pats, slowpath
740
740
741
741
742 def _fileancestors(repo, revs, match, followfirst):
742 def _fileancestors(repo, revs, match, followfirst):
743 fctxs = []
743 fctxs = []
744 for r in revs:
744 for r in revs:
745 ctx = repo[r]
745 ctx = repo[r]
746 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
746 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
747
747
748 # When displaying a revision with --patch --follow FILE, we have
748 # When displaying a revision with --patch --follow FILE, we have
749 # to know which file of the revision must be diffed. With
749 # to know which file of the revision must be diffed. With
750 # --follow, we want the names of the ancestors of FILE in the
750 # --follow, we want the names of the ancestors of FILE in the
751 # revision, stored in "fcache". "fcache" is populated as a side effect
751 # revision, stored in "fcache". "fcache" is populated as a side effect
752 # of the graph traversal.
752 # of the graph traversal.
753 fcache = {}
753 fcache = {}
754
754
755 def filematcher(ctx):
755 def filematcher(ctx):
756 return scmutil.matchfiles(repo, fcache.get(ctx.rev(), []))
756 return scmutil.matchfiles(repo, fcache.get(scmutil.intrev(ctx), []))
757
757
758 def revgen():
758 def revgen():
759 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
759 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
760 fcache[rev] = [c.path() for c in cs]
760 fcache[rev] = [c.path() for c in cs]
761 yield rev
761 yield rev
762
762
763 return smartset.generatorset(revgen(), iterasc=False), filematcher
763 return smartset.generatorset(revgen(), iterasc=False), filematcher
764
764
765
765
766 def _makenofollowfilematcher(repo, pats, opts):
766 def _makenofollowfilematcher(repo, pats, opts):
767 '''hook for extensions to override the filematcher for non-follow cases'''
767 '''hook for extensions to override the filematcher for non-follow cases'''
768 return None
768 return None
769
769
770
770
771 _opt2logrevset = {
771 _opt2logrevset = {
772 b'no_merges': (b'not merge()', None),
772 b'no_merges': (b'not merge()', None),
773 b'only_merges': (b'merge()', None),
773 b'only_merges': (b'merge()', None),
774 b'_matchfiles': (None, b'_matchfiles(%ps)'),
774 b'_matchfiles': (None, b'_matchfiles(%ps)'),
775 b'date': (b'date(%s)', None),
775 b'date': (b'date(%s)', None),
776 b'branch': (b'branch(%s)', b'%lr'),
776 b'branch': (b'branch(%s)', b'%lr'),
777 b'_patslog': (b'filelog(%s)', b'%lr'),
777 b'_patslog': (b'filelog(%s)', b'%lr'),
778 b'keyword': (b'keyword(%s)', b'%lr'),
778 b'keyword': (b'keyword(%s)', b'%lr'),
779 b'prune': (b'ancestors(%s)', b'not %lr'),
779 b'prune': (b'ancestors(%s)', b'not %lr'),
780 b'user': (b'user(%s)', b'%lr'),
780 b'user': (b'user(%s)', b'%lr'),
781 }
781 }
782
782
783
783
784 def _makerevset(repo, match, pats, slowpath, opts):
784 def _makerevset(repo, match, pats, slowpath, opts):
785 """Return a revset string built from log options and file patterns"""
785 """Return a revset string built from log options and file patterns"""
786 opts = dict(opts)
786 opts = dict(opts)
787 # follow or not follow?
787 # follow or not follow?
788 follow = opts.get(b'follow') or opts.get(b'follow_first')
788 follow = opts.get(b'follow') or opts.get(b'follow_first')
789
789
790 # branch and only_branch are really aliases and must be handled at
790 # branch and only_branch are really aliases and must be handled at
791 # the same time
791 # the same time
792 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', [])
792 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', [])
793 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']]
793 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']]
794
794
795 if slowpath:
795 if slowpath:
796 # See walkchangerevs() slow path.
796 # See walkchangerevs() slow path.
797 #
797 #
798 # pats/include/exclude cannot be represented as separate
798 # pats/include/exclude cannot be represented as separate
799 # revset expressions as their filtering logic applies at file
799 # revset expressions as their filtering logic applies at file
800 # level. For instance "-I a -X b" matches a revision touching
800 # level. For instance "-I a -X b" matches a revision touching
801 # "a" and "b" while "file(a) and not file(b)" does
801 # "a" and "b" while "file(a) and not file(b)" does
802 # not. Besides, filesets are evaluated against the working
802 # not. Besides, filesets are evaluated against the working
803 # directory.
803 # directory.
804 matchargs = [b'r:', b'd:relpath']
804 matchargs = [b'r:', b'd:relpath']
805 for p in pats:
805 for p in pats:
806 matchargs.append(b'p:' + p)
806 matchargs.append(b'p:' + p)
807 for p in opts.get(b'include', []):
807 for p in opts.get(b'include', []):
808 matchargs.append(b'i:' + p)
808 matchargs.append(b'i:' + p)
809 for p in opts.get(b'exclude', []):
809 for p in opts.get(b'exclude', []):
810 matchargs.append(b'x:' + p)
810 matchargs.append(b'x:' + p)
811 opts[b'_matchfiles'] = matchargs
811 opts[b'_matchfiles'] = matchargs
812 elif not follow:
812 elif not follow:
813 opts[b'_patslog'] = list(pats)
813 opts[b'_patslog'] = list(pats)
814
814
815 expr = []
815 expr = []
816 for op, val in sorted(pycompat.iteritems(opts)):
816 for op, val in sorted(pycompat.iteritems(opts)):
817 if not val:
817 if not val:
818 continue
818 continue
819 if op not in _opt2logrevset:
819 if op not in _opt2logrevset:
820 continue
820 continue
821 revop, listop = _opt2logrevset[op]
821 revop, listop = _opt2logrevset[op]
822 if revop and b'%' not in revop:
822 if revop and b'%' not in revop:
823 expr.append(revop)
823 expr.append(revop)
824 elif not listop:
824 elif not listop:
825 expr.append(revsetlang.formatspec(revop, val))
825 expr.append(revsetlang.formatspec(revop, val))
826 else:
826 else:
827 if revop:
827 if revop:
828 val = [revsetlang.formatspec(revop, v) for v in val]
828 val = [revsetlang.formatspec(revop, v) for v in val]
829 expr.append(revsetlang.formatspec(listop, val))
829 expr.append(revsetlang.formatspec(listop, val))
830
830
831 if expr:
831 if expr:
832 expr = b'(' + b' and '.join(expr) + b')'
832 expr = b'(' + b' and '.join(expr) + b')'
833 else:
833 else:
834 expr = None
834 expr = None
835 return expr
835 return expr
836
836
837
837
838 def _initialrevs(repo, opts):
838 def _initialrevs(repo, opts):
839 """Return the initial set of revisions to be filtered or followed"""
839 """Return the initial set of revisions to be filtered or followed"""
840 follow = opts.get(b'follow') or opts.get(b'follow_first')
840 follow = opts.get(b'follow') or opts.get(b'follow_first')
841 if opts.get(b'rev'):
841 if opts.get(b'rev'):
842 revs = scmutil.revrange(repo, opts[b'rev'])
842 revs = scmutil.revrange(repo, opts[b'rev'])
843 elif follow and repo.dirstate.p1() == nullid:
843 elif follow and repo.dirstate.p1() == nullid:
844 revs = smartset.baseset()
844 revs = smartset.baseset()
845 elif follow:
845 elif follow:
846 revs = repo.revs(b'.')
846 revs = repo.revs(b'.')
847 else:
847 else:
848 revs = smartset.spanset(repo)
848 revs = smartset.spanset(repo)
849 revs.reverse()
849 revs.reverse()
850 return revs
850 return revs
851
851
852
852
853 def getrevs(repo, pats, opts):
853 def getrevs(repo, pats, opts):
854 # type: (Any, Any, Any) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]
854 # type: (Any, Any, Any) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]
855 """Return (revs, differ) where revs is a smartset
855 """Return (revs, differ) where revs is a smartset
856
856
857 differ is a changesetdiffer with pre-configured file matcher.
857 differ is a changesetdiffer with pre-configured file matcher.
858 """
858 """
859 follow = opts.get(b'follow') or opts.get(b'follow_first')
859 follow = opts.get(b'follow') or opts.get(b'follow_first')
860 followfirst = opts.get(b'follow_first')
860 followfirst = opts.get(b'follow_first')
861 limit = getlimit(opts)
861 limit = getlimit(opts)
862 revs = _initialrevs(repo, opts)
862 revs = _initialrevs(repo, opts)
863 if not revs:
863 if not revs:
864 return smartset.baseset(), None
864 return smartset.baseset(), None
865 match, pats, slowpath = _makematcher(repo, revs, pats, opts)
865 match, pats, slowpath = _makematcher(repo, revs, pats, opts)
866 filematcher = None
866 filematcher = None
867 if follow:
867 if follow:
868 if slowpath or match.always():
868 if slowpath or match.always():
869 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
869 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
870 else:
870 else:
871 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
871 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
872 revs.reverse()
872 revs.reverse()
873 if filematcher is None:
873 if filematcher is None:
874 filematcher = _makenofollowfilematcher(repo, pats, opts)
874 filematcher = _makenofollowfilematcher(repo, pats, opts)
875 if filematcher is None:
875 if filematcher is None:
876
876
877 def filematcher(ctx):
877 def filematcher(ctx):
878 return match
878 return match
879
879
880 expr = _makerevset(repo, match, pats, slowpath, opts)
880 expr = _makerevset(repo, match, pats, slowpath, opts)
881 if opts.get(b'graph'):
881 if opts.get(b'graph'):
882 # User-specified revs might be unsorted, but don't sort before
882 # User-specified revs might be unsorted, but don't sort before
883 # _makerevset because it might depend on the order of revs
883 # _makerevset because it might depend on the order of revs
884 if repo.ui.configbool(b'experimental', b'log.topo'):
884 if repo.ui.configbool(b'experimental', b'log.topo'):
885 if not revs.istopo():
885 if not revs.istopo():
886 revs = dagop.toposort(revs, repo.changelog.parentrevs)
886 revs = dagop.toposort(revs, repo.changelog.parentrevs)
887 # TODO: try to iterate the set lazily
887 # TODO: try to iterate the set lazily
888 revs = revset.baseset(list(revs), istopo=True)
888 revs = revset.baseset(list(revs), istopo=True)
889 elif not (revs.isdescending() or revs.istopo()):
889 elif not (revs.isdescending() or revs.istopo()):
890 revs.sort(reverse=True)
890 revs.sort(reverse=True)
891 if expr:
891 if expr:
892 matcher = revset.match(None, expr)
892 matcher = revset.match(None, expr)
893 revs = matcher(repo, revs)
893 revs = matcher(repo, revs)
894 if limit is not None:
894 if limit is not None:
895 revs = revs.slice(0, limit)
895 revs = revs.slice(0, limit)
896
896
897 differ = changesetdiffer()
897 differ = changesetdiffer()
898 differ._makefilematcher = filematcher
898 differ._makefilematcher = filematcher
899 return revs, differ
899 return revs, differ
900
900
901
901
902 def _parselinerangeopt(repo, opts):
902 def _parselinerangeopt(repo, opts):
903 """Parse --line-range log option and return a list of tuples (filename,
903 """Parse --line-range log option and return a list of tuples (filename,
904 (fromline, toline)).
904 (fromline, toline)).
905 """
905 """
906 linerangebyfname = []
906 linerangebyfname = []
907 for pat in opts.get(b'line_range', []):
907 for pat in opts.get(b'line_range', []):
908 try:
908 try:
909 pat, linerange = pat.rsplit(b',', 1)
909 pat, linerange = pat.rsplit(b',', 1)
910 except ValueError:
910 except ValueError:
911 raise error.Abort(_(b'malformatted line-range pattern %s') % pat)
911 raise error.Abort(_(b'malformatted line-range pattern %s') % pat)
912 try:
912 try:
913 fromline, toline = map(int, linerange.split(b':'))
913 fromline, toline = map(int, linerange.split(b':'))
914 except ValueError:
914 except ValueError:
915 raise error.Abort(_(b"invalid line range for %s") % pat)
915 raise error.Abort(_(b"invalid line range for %s") % pat)
916 msg = _(b"line range pattern '%s' must match exactly one file") % pat
916 msg = _(b"line range pattern '%s' must match exactly one file") % pat
917 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
917 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
918 linerangebyfname.append(
918 linerangebyfname.append(
919 (fname, util.processlinerange(fromline, toline))
919 (fname, util.processlinerange(fromline, toline))
920 )
920 )
921 return linerangebyfname
921 return linerangebyfname
922
922
923
923
924 def getlinerangerevs(repo, userrevs, opts):
924 def getlinerangerevs(repo, userrevs, opts):
925 """Return (revs, differ).
925 """Return (revs, differ).
926
926
927 "revs" are revisions obtained by processing "line-range" log options and
927 "revs" are revisions obtained by processing "line-range" log options and
928 walking block ancestors of each specified file/line-range.
928 walking block ancestors of each specified file/line-range.
929
929
930 "differ" is a changesetdiffer with pre-configured file matcher and hunks
930 "differ" is a changesetdiffer with pre-configured file matcher and hunks
931 filter.
931 filter.
932 """
932 """
933 wctx = repo[None]
933 wctx = repo[None]
934
934
935 # Two-levels map of "rev -> file ctx -> [line range]".
935 # Two-levels map of "rev -> file ctx -> [line range]".
936 linerangesbyrev = {}
936 linerangesbyrev = {}
937 for fname, (fromline, toline) in _parselinerangeopt(repo, opts):
937 for fname, (fromline, toline) in _parselinerangeopt(repo, opts):
938 if fname not in wctx:
938 if fname not in wctx:
939 raise error.Abort(
939 raise error.Abort(
940 _(b'cannot follow file not in parent revision: "%s"') % fname
940 _(b'cannot follow file not in parent revision: "%s"') % fname
941 )
941 )
942 fctx = wctx.filectx(fname)
942 fctx = wctx.filectx(fname)
943 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
943 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
944 rev = fctx.introrev()
944 rev = fctx.introrev()
945 if rev is None:
945 if rev is None:
946 rev = wdirrev
946 rev = wdirrev
947 if rev not in userrevs:
947 if rev not in userrevs:
948 continue
948 continue
949 linerangesbyrev.setdefault(rev, {}).setdefault(
949 linerangesbyrev.setdefault(rev, {}).setdefault(
950 fctx.path(), []
950 fctx.path(), []
951 ).append(linerange)
951 ).append(linerange)
952
952
953 def nofilterhunksfn(fctx, hunks):
953 def nofilterhunksfn(fctx, hunks):
954 return hunks
954 return hunks
955
955
956 def hunksfilter(ctx):
956 def hunksfilter(ctx):
957 fctxlineranges = linerangesbyrev.get(scmutil.intrev(ctx))
957 fctxlineranges = linerangesbyrev.get(scmutil.intrev(ctx))
958 if fctxlineranges is None:
958 if fctxlineranges is None:
959 return nofilterhunksfn
959 return nofilterhunksfn
960
960
961 def filterfn(fctx, hunks):
961 def filterfn(fctx, hunks):
962 lineranges = fctxlineranges.get(fctx.path())
962 lineranges = fctxlineranges.get(fctx.path())
963 if lineranges is not None:
963 if lineranges is not None:
964 for hr, lines in hunks:
964 for hr, lines in hunks:
965 if hr is None: # binary
965 if hr is None: # binary
966 yield hr, lines
966 yield hr, lines
967 continue
967 continue
968 if any(mdiff.hunkinrange(hr[2:], lr) for lr in lineranges):
968 if any(mdiff.hunkinrange(hr[2:], lr) for lr in lineranges):
969 yield hr, lines
969 yield hr, lines
970 else:
970 else:
971 for hunk in hunks:
971 for hunk in hunks:
972 yield hunk
972 yield hunk
973
973
974 return filterfn
974 return filterfn
975
975
976 def filematcher(ctx):
976 def filematcher(ctx):
977 files = list(linerangesbyrev.get(scmutil.intrev(ctx), []))
977 files = list(linerangesbyrev.get(scmutil.intrev(ctx), []))
978 return scmutil.matchfiles(repo, files)
978 return scmutil.matchfiles(repo, files)
979
979
980 revs = sorted(linerangesbyrev, reverse=True)
980 revs = sorted(linerangesbyrev, reverse=True)
981
981
982 differ = changesetdiffer()
982 differ = changesetdiffer()
983 differ._makefilematcher = filematcher
983 differ._makefilematcher = filematcher
984 differ._makehunksfilter = hunksfilter
984 differ._makehunksfilter = hunksfilter
985 return smartset.baseset(revs), differ
985 return smartset.baseset(revs), differ
986
986
987
987
988 def _graphnodeformatter(ui, displayer):
988 def _graphnodeformatter(ui, displayer):
989 spec = ui.config(b'ui', b'graphnodetemplate')
989 spec = ui.config(b'ui', b'graphnodetemplate')
990 if not spec:
990 if not spec:
991 return templatekw.getgraphnode # fast path for "{graphnode}"
991 return templatekw.getgraphnode # fast path for "{graphnode}"
992
992
993 spec = templater.unquotestring(spec)
993 spec = templater.unquotestring(spec)
994 if isinstance(displayer, changesettemplater):
994 if isinstance(displayer, changesettemplater):
995 # reuse cache of slow templates
995 # reuse cache of slow templates
996 tres = displayer._tresources
996 tres = displayer._tresources
997 else:
997 else:
998 tres = formatter.templateresources(ui)
998 tres = formatter.templateresources(ui)
999 templ = formatter.maketemplater(
999 templ = formatter.maketemplater(
1000 ui, spec, defaults=templatekw.keywords, resources=tres
1000 ui, spec, defaults=templatekw.keywords, resources=tres
1001 )
1001 )
1002
1002
1003 def formatnode(repo, ctx, cache):
1003 def formatnode(repo, ctx, cache):
1004 props = {b'ctx': ctx, b'repo': repo}
1004 props = {b'ctx': ctx, b'repo': repo}
1005 return templ.renderdefault(props)
1005 return templ.renderdefault(props)
1006
1006
1007 return formatnode
1007 return formatnode
1008
1008
1009
1009
1010 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None):
1010 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None):
1011 props = props or {}
1011 props = props or {}
1012 formatnode = _graphnodeformatter(ui, displayer)
1012 formatnode = _graphnodeformatter(ui, displayer)
1013 state = graphmod.asciistate()
1013 state = graphmod.asciistate()
1014 styles = state.styles
1014 styles = state.styles
1015
1015
1016 # only set graph styling if HGPLAIN is not set.
1016 # only set graph styling if HGPLAIN is not set.
1017 if ui.plain(b'graph'):
1017 if ui.plain(b'graph'):
1018 # set all edge styles to |, the default pre-3.8 behaviour
1018 # set all edge styles to |, the default pre-3.8 behaviour
1019 styles.update(dict.fromkeys(styles, b'|'))
1019 styles.update(dict.fromkeys(styles, b'|'))
1020 else:
1020 else:
1021 edgetypes = {
1021 edgetypes = {
1022 b'parent': graphmod.PARENT,
1022 b'parent': graphmod.PARENT,
1023 b'grandparent': graphmod.GRANDPARENT,
1023 b'grandparent': graphmod.GRANDPARENT,
1024 b'missing': graphmod.MISSINGPARENT,
1024 b'missing': graphmod.MISSINGPARENT,
1025 }
1025 }
1026 for name, key in edgetypes.items():
1026 for name, key in edgetypes.items():
1027 # experimental config: experimental.graphstyle.*
1027 # experimental config: experimental.graphstyle.*
1028 styles[key] = ui.config(
1028 styles[key] = ui.config(
1029 b'experimental', b'graphstyle.%s' % name, styles[key]
1029 b'experimental', b'graphstyle.%s' % name, styles[key]
1030 )
1030 )
1031 if not styles[key]:
1031 if not styles[key]:
1032 styles[key] = None
1032 styles[key] = None
1033
1033
1034 # experimental config: experimental.graphshorten
1034 # experimental config: experimental.graphshorten
1035 state.graphshorten = ui.configbool(b'experimental', b'graphshorten')
1035 state.graphshorten = ui.configbool(b'experimental', b'graphshorten')
1036
1036
1037 formatnode_cache = {}
1037 formatnode_cache = {}
1038 for rev, type, ctx, parents in dag:
1038 for rev, type, ctx, parents in dag:
1039 char = formatnode(repo, ctx, formatnode_cache)
1039 char = formatnode(repo, ctx, formatnode_cache)
1040 copies = getcopies(ctx) if getcopies else None
1040 copies = getcopies(ctx) if getcopies else None
1041 edges = edgefn(type, char, state, rev, parents)
1041 edges = edgefn(type, char, state, rev, parents)
1042 firstedge = next(edges)
1042 firstedge = next(edges)
1043 width = firstedge[2]
1043 width = firstedge[2]
1044 displayer.show(
1044 displayer.show(
1045 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props)
1045 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props)
1046 )
1046 )
1047 lines = displayer.hunk.pop(rev).split(b'\n')
1047 lines = displayer.hunk.pop(rev).split(b'\n')
1048 if not lines[-1]:
1048 if not lines[-1]:
1049 del lines[-1]
1049 del lines[-1]
1050 displayer.flush(ctx)
1050 displayer.flush(ctx)
1051 for type, char, width, coldata in itertools.chain([firstedge], edges):
1051 for type, char, width, coldata in itertools.chain([firstedge], edges):
1052 graphmod.ascii(ui, state, type, char, lines, coldata)
1052 graphmod.ascii(ui, state, type, char, lines, coldata)
1053 lines = []
1053 lines = []
1054 displayer.close()
1054 displayer.close()
1055
1055
1056
1056
1057 def displaygraphrevs(ui, repo, revs, displayer, getrenamed):
1057 def displaygraphrevs(ui, repo, revs, displayer, getrenamed):
1058 revdag = graphmod.dagwalker(repo, revs)
1058 revdag = graphmod.dagwalker(repo, revs)
1059 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed)
1059 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed)
1060
1060
1061
1061
1062 def displayrevs(ui, repo, revs, displayer, getcopies):
1062 def displayrevs(ui, repo, revs, displayer, getcopies):
1063 for rev in revs:
1063 for rev in revs:
1064 ctx = repo[rev]
1064 ctx = repo[rev]
1065 copies = getcopies(ctx) if getcopies else None
1065 copies = getcopies(ctx) if getcopies else None
1066 displayer.show(ctx, copies=copies)
1066 displayer.show(ctx, copies=copies)
1067 displayer.flush(ctx)
1067 displayer.flush(ctx)
1068 displayer.close()
1068 displayer.close()
1069
1069
1070
1070
1071 def checkunsupportedgraphflags(pats, opts):
1071 def checkunsupportedgraphflags(pats, opts):
1072 for op in [b"newest_first"]:
1072 for op in [b"newest_first"]:
1073 if op in opts and opts[op]:
1073 if op in opts and opts[op]:
1074 raise error.Abort(
1074 raise error.Abort(
1075 _(b"-G/--graph option is incompatible with --%s")
1075 _(b"-G/--graph option is incompatible with --%s")
1076 % op.replace(b"_", b"-")
1076 % op.replace(b"_", b"-")
1077 )
1077 )
1078
1078
1079
1079
1080 def graphrevs(repo, nodes, opts):
1080 def graphrevs(repo, nodes, opts):
1081 limit = getlimit(opts)
1081 limit = getlimit(opts)
1082 nodes.reverse()
1082 nodes.reverse()
1083 if limit is not None:
1083 if limit is not None:
1084 nodes = nodes[:limit]
1084 nodes = nodes[:limit]
1085 return graphmod.nodes(repo, nodes)
1085 return graphmod.nodes(repo, nodes)
@@ -1,469 +1,480 b''
1 # repoview.py - Filtered view of a localrepo object
1 # repoview.py - Filtered view of a localrepo object
2 #
2 #
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
4 # Logilab SA <contact@logilab.fr>
4 # Logilab SA <contact@logilab.fr>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import copy
11 import copy
12 import weakref
12 import weakref
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 hex,
16 hex,
17 nullrev,
17 nullrev,
18 )
18 )
19 from .pycompat import (
19 from .pycompat import (
20 delattr,
20 delattr,
21 getattr,
21 getattr,
22 setattr,
22 setattr,
23 )
23 )
24 from . import (
24 from . import (
25 error,
25 error,
26 obsolete,
26 obsolete,
27 phases,
27 phases,
28 pycompat,
28 pycompat,
29 tags as tagsmod,
29 tags as tagsmod,
30 util,
30 util,
31 )
31 )
32 from .utils import repoviewutil
32 from .utils import repoviewutil
33
33
34
34
35 def hideablerevs(repo):
35 def hideablerevs(repo):
36 """Revision candidates to be hidden
36 """Revision candidates to be hidden
37
37
38 This is a standalone function to allow extensions to wrap it.
38 This is a standalone function to allow extensions to wrap it.
39
39
40 Because we use the set of immutable changesets as a fallback subset in
40 Because we use the set of immutable changesets as a fallback subset in
41 branchmap (see mercurial.utils.repoviewutils.subsettable), you cannot set
41 branchmap (see mercurial.utils.repoviewutils.subsettable), you cannot set
42 "public" changesets as "hideable". Doing so would break multiple code
42 "public" changesets as "hideable". Doing so would break multiple code
43 assertions and lead to crashes."""
43 assertions and lead to crashes."""
44 obsoletes = obsolete.getrevs(repo, b'obsolete')
44 obsoletes = obsolete.getrevs(repo, b'obsolete')
45 internals = repo._phasecache.getrevset(repo, phases.localhiddenphases)
45 internals = repo._phasecache.getrevset(repo, phases.localhiddenphases)
46 internals = frozenset(internals)
46 internals = frozenset(internals)
47 return obsoletes | internals
47 return obsoletes | internals
48
48
49
49
50 def pinnedrevs(repo):
50 def pinnedrevs(repo):
51 """revisions blocking hidden changesets from being filtered
51 """revisions blocking hidden changesets from being filtered
52 """
52 """
53
53
54 cl = repo.changelog
54 cl = repo.changelog
55 pinned = set()
55 pinned = set()
56 pinned.update([par.rev() for par in repo[None].parents()])
56 pinned.update([par.rev() for par in repo[None].parents()])
57 pinned.update([cl.rev(bm) for bm in repo._bookmarks.values()])
57 pinned.update([cl.rev(bm) for bm in repo._bookmarks.values()])
58
58
59 tags = {}
59 tags = {}
60 tagsmod.readlocaltags(repo.ui, repo, tags, {})
60 tagsmod.readlocaltags(repo.ui, repo, tags, {})
61 if tags:
61 if tags:
62 rev = cl.index.get_rev
62 rev = cl.index.get_rev
63 pinned.update(rev(t[0]) for t in tags.values())
63 pinned.update(rev(t[0]) for t in tags.values())
64 pinned.discard(None)
64 pinned.discard(None)
65
66 # Avoid cycle: mercurial.filemerge -> mercurial.templater ->
67 # mercurial.templatefuncs -> mercurial.revset -> mercurial.repoview ->
68 # mercurial.mergestate -> mercurial.filemerge
69 from . import mergestate
70
71 ms = mergestate.mergestate.read(repo)
72 if ms.active():
73 pinned.add(ms.localctx.rev())
74 pinned.add(ms.otherctx.rev())
75
65 return pinned
76 return pinned
66
77
67
78
68 def _revealancestors(pfunc, hidden, revs):
79 def _revealancestors(pfunc, hidden, revs):
69 """reveals contiguous chains of hidden ancestors of 'revs' by removing them
80 """reveals contiguous chains of hidden ancestors of 'revs' by removing them
70 from 'hidden'
81 from 'hidden'
71
82
72 - pfunc(r): a funtion returning parent of 'r',
83 - pfunc(r): a funtion returning parent of 'r',
73 - hidden: the (preliminary) hidden revisions, to be updated
84 - hidden: the (preliminary) hidden revisions, to be updated
74 - revs: iterable of revnum,
85 - revs: iterable of revnum,
75
86
76 (Ancestors are revealed exclusively, i.e. the elements in 'revs' are
87 (Ancestors are revealed exclusively, i.e. the elements in 'revs' are
77 *not* revealed)
88 *not* revealed)
78 """
89 """
79 stack = list(revs)
90 stack = list(revs)
80 while stack:
91 while stack:
81 for p in pfunc(stack.pop()):
92 for p in pfunc(stack.pop()):
82 if p != nullrev and p in hidden:
93 if p != nullrev and p in hidden:
83 hidden.remove(p)
94 hidden.remove(p)
84 stack.append(p)
95 stack.append(p)
85
96
86
97
87 def computehidden(repo, visibilityexceptions=None):
98 def computehidden(repo, visibilityexceptions=None):
88 """compute the set of hidden revision to filter
99 """compute the set of hidden revision to filter
89
100
90 During most operation hidden should be filtered."""
101 During most operation hidden should be filtered."""
91 assert not repo.changelog.filteredrevs
102 assert not repo.changelog.filteredrevs
92
103
93 hidden = hideablerevs(repo)
104 hidden = hideablerevs(repo)
94 if hidden:
105 if hidden:
95 hidden = set(hidden - pinnedrevs(repo))
106 hidden = set(hidden - pinnedrevs(repo))
96 if visibilityexceptions:
107 if visibilityexceptions:
97 hidden -= visibilityexceptions
108 hidden -= visibilityexceptions
98 pfunc = repo.changelog.parentrevs
109 pfunc = repo.changelog.parentrevs
99 mutable = repo._phasecache.getrevset(repo, phases.mutablephases)
110 mutable = repo._phasecache.getrevset(repo, phases.mutablephases)
100
111
101 visible = mutable - hidden
112 visible = mutable - hidden
102 _revealancestors(pfunc, hidden, visible)
113 _revealancestors(pfunc, hidden, visible)
103 return frozenset(hidden)
114 return frozenset(hidden)
104
115
105
116
106 def computesecret(repo, visibilityexceptions=None):
117 def computesecret(repo, visibilityexceptions=None):
107 """compute the set of revision that can never be exposed through hgweb
118 """compute the set of revision that can never be exposed through hgweb
108
119
109 Changeset in the secret phase (or above) should stay unaccessible."""
120 Changeset in the secret phase (or above) should stay unaccessible."""
110 assert not repo.changelog.filteredrevs
121 assert not repo.changelog.filteredrevs
111 secrets = repo._phasecache.getrevset(repo, phases.remotehiddenphases)
122 secrets = repo._phasecache.getrevset(repo, phases.remotehiddenphases)
112 return frozenset(secrets)
123 return frozenset(secrets)
113
124
114
125
115 def computeunserved(repo, visibilityexceptions=None):
126 def computeunserved(repo, visibilityexceptions=None):
116 """compute the set of revision that should be filtered when used a server
127 """compute the set of revision that should be filtered when used a server
117
128
118 Secret and hidden changeset should not pretend to be here."""
129 Secret and hidden changeset should not pretend to be here."""
119 assert not repo.changelog.filteredrevs
130 assert not repo.changelog.filteredrevs
120 # fast path in simple case to avoid impact of non optimised code
131 # fast path in simple case to avoid impact of non optimised code
121 hiddens = filterrevs(repo, b'visible')
132 hiddens = filterrevs(repo, b'visible')
122 secrets = filterrevs(repo, b'served.hidden')
133 secrets = filterrevs(repo, b'served.hidden')
123 if secrets:
134 if secrets:
124 return frozenset(hiddens | secrets)
135 return frozenset(hiddens | secrets)
125 else:
136 else:
126 return hiddens
137 return hiddens
127
138
128
139
129 def computemutable(repo, visibilityexceptions=None):
140 def computemutable(repo, visibilityexceptions=None):
130 assert not repo.changelog.filteredrevs
141 assert not repo.changelog.filteredrevs
131 # fast check to avoid revset call on huge repo
142 # fast check to avoid revset call on huge repo
132 if repo._phasecache.hasnonpublicphases(repo):
143 if repo._phasecache.hasnonpublicphases(repo):
133 return frozenset(repo._phasecache.getrevset(repo, phases.mutablephases))
144 return frozenset(repo._phasecache.getrevset(repo, phases.mutablephases))
134 return frozenset()
145 return frozenset()
135
146
136
147
137 def computeimpactable(repo, visibilityexceptions=None):
148 def computeimpactable(repo, visibilityexceptions=None):
138 """Everything impactable by mutable revision
149 """Everything impactable by mutable revision
139
150
140 The immutable filter still have some chance to get invalidated. This will
151 The immutable filter still have some chance to get invalidated. This will
141 happen when:
152 happen when:
142
153
143 - you garbage collect hidden changeset,
154 - you garbage collect hidden changeset,
144 - public phase is moved backward,
155 - public phase is moved backward,
145 - something is changed in the filtering (this could be fixed)
156 - something is changed in the filtering (this could be fixed)
146
157
147 This filter out any mutable changeset and any public changeset that may be
158 This filter out any mutable changeset and any public changeset that may be
148 impacted by something happening to a mutable revision.
159 impacted by something happening to a mutable revision.
149
160
150 This is achieved by filtered everything with a revision number egal or
161 This is achieved by filtered everything with a revision number egal or
151 higher than the first mutable changeset is filtered."""
162 higher than the first mutable changeset is filtered."""
152 assert not repo.changelog.filteredrevs
163 assert not repo.changelog.filteredrevs
153 cl = repo.changelog
164 cl = repo.changelog
154 firstmutable = len(cl)
165 firstmutable = len(cl)
155 roots = repo._phasecache.nonpublicphaseroots(repo)
166 roots = repo._phasecache.nonpublicphaseroots(repo)
156 if roots:
167 if roots:
157 firstmutable = min(firstmutable, min(cl.rev(r) for r in roots))
168 firstmutable = min(firstmutable, min(cl.rev(r) for r in roots))
158 # protect from nullrev root
169 # protect from nullrev root
159 firstmutable = max(0, firstmutable)
170 firstmutable = max(0, firstmutable)
160 return frozenset(pycompat.xrange(firstmutable, len(cl)))
171 return frozenset(pycompat.xrange(firstmutable, len(cl)))
161
172
162
173
163 # function to compute filtered set
174 # function to compute filtered set
164 #
175 #
165 # When adding a new filter you MUST update the table at:
176 # When adding a new filter you MUST update the table at:
166 # mercurial.utils.repoviewutil.subsettable
177 # mercurial.utils.repoviewutil.subsettable
167 # Otherwise your filter will have to recompute all its branches cache
178 # Otherwise your filter will have to recompute all its branches cache
168 # from scratch (very slow).
179 # from scratch (very slow).
169 filtertable = {
180 filtertable = {
170 b'visible': computehidden,
181 b'visible': computehidden,
171 b'visible-hidden': computehidden,
182 b'visible-hidden': computehidden,
172 b'served.hidden': computesecret,
183 b'served.hidden': computesecret,
173 b'served': computeunserved,
184 b'served': computeunserved,
174 b'immutable': computemutable,
185 b'immutable': computemutable,
175 b'base': computeimpactable,
186 b'base': computeimpactable,
176 }
187 }
177
188
178 # set of filter level that will include the working copy parent no matter what.
189 # set of filter level that will include the working copy parent no matter what.
179 filter_has_wc = {b'visible', b'visible-hidden'}
190 filter_has_wc = {b'visible', b'visible-hidden'}
180
191
181 _basefiltername = list(filtertable)
192 _basefiltername = list(filtertable)
182
193
183
194
184 def extrafilter(ui):
195 def extrafilter(ui):
185 """initialize extra filter and return its id
196 """initialize extra filter and return its id
186
197
187 If extra filtering is configured, we make sure the associated filtered view
198 If extra filtering is configured, we make sure the associated filtered view
188 are declared and return the associated id.
199 are declared and return the associated id.
189 """
200 """
190 frevs = ui.config(b'experimental', b'extra-filter-revs')
201 frevs = ui.config(b'experimental', b'extra-filter-revs')
191 if frevs is None:
202 if frevs is None:
192 return None
203 return None
193
204
194 fid = pycompat.sysbytes(util.DIGESTS[b'sha1'](frevs).hexdigest())[:12]
205 fid = pycompat.sysbytes(util.DIGESTS[b'sha1'](frevs).hexdigest())[:12]
195
206
196 combine = lambda fname: fname + b'%' + fid
207 combine = lambda fname: fname + b'%' + fid
197
208
198 subsettable = repoviewutil.subsettable
209 subsettable = repoviewutil.subsettable
199
210
200 if combine(b'base') not in filtertable:
211 if combine(b'base') not in filtertable:
201 for name in _basefiltername:
212 for name in _basefiltername:
202
213
203 def extrafilteredrevs(repo, *args, **kwargs):
214 def extrafilteredrevs(repo, *args, **kwargs):
204 baserevs = filtertable[name](repo, *args, **kwargs)
215 baserevs = filtertable[name](repo, *args, **kwargs)
205 extrarevs = frozenset(repo.revs(frevs))
216 extrarevs = frozenset(repo.revs(frevs))
206 return baserevs | extrarevs
217 return baserevs | extrarevs
207
218
208 filtertable[combine(name)] = extrafilteredrevs
219 filtertable[combine(name)] = extrafilteredrevs
209 if name in subsettable:
220 if name in subsettable:
210 subsettable[combine(name)] = combine(subsettable[name])
221 subsettable[combine(name)] = combine(subsettable[name])
211 return fid
222 return fid
212
223
213
224
214 def filterrevs(repo, filtername, visibilityexceptions=None):
225 def filterrevs(repo, filtername, visibilityexceptions=None):
215 """returns set of filtered revision for this filter name
226 """returns set of filtered revision for this filter name
216
227
217 visibilityexceptions is a set of revs which must are exceptions for
228 visibilityexceptions is a set of revs which must are exceptions for
218 hidden-state and must be visible. They are dynamic and hence we should not
229 hidden-state and must be visible. They are dynamic and hence we should not
219 cache it's result"""
230 cache it's result"""
220 if filtername not in repo.filteredrevcache:
231 if filtername not in repo.filteredrevcache:
221 if repo.ui.configbool(b'devel', b'debug.repo-filters'):
232 if repo.ui.configbool(b'devel', b'debug.repo-filters'):
222 msg = b'computing revision filter for "%s"'
233 msg = b'computing revision filter for "%s"'
223 msg %= filtername
234 msg %= filtername
224 if repo.ui.tracebackflag and repo.ui.debugflag:
235 if repo.ui.tracebackflag and repo.ui.debugflag:
225 # XXX use ui.write_err
236 # XXX use ui.write_err
226 util.debugstacktrace(
237 util.debugstacktrace(
227 msg,
238 msg,
228 f=repo.ui._fout,
239 f=repo.ui._fout,
229 otherf=repo.ui._ferr,
240 otherf=repo.ui._ferr,
230 prefix=b'debug.filters: ',
241 prefix=b'debug.filters: ',
231 )
242 )
232 else:
243 else:
233 repo.ui.debug(b'debug.filters: %s\n' % msg)
244 repo.ui.debug(b'debug.filters: %s\n' % msg)
234 func = filtertable[filtername]
245 func = filtertable[filtername]
235 if visibilityexceptions:
246 if visibilityexceptions:
236 return func(repo.unfiltered, visibilityexceptions)
247 return func(repo.unfiltered, visibilityexceptions)
237 repo.filteredrevcache[filtername] = func(repo.unfiltered())
248 repo.filteredrevcache[filtername] = func(repo.unfiltered())
238 return repo.filteredrevcache[filtername]
249 return repo.filteredrevcache[filtername]
239
250
240
251
241 def wrapchangelog(unfichangelog, filteredrevs):
252 def wrapchangelog(unfichangelog, filteredrevs):
242 cl = copy.copy(unfichangelog)
253 cl = copy.copy(unfichangelog)
243 cl.filteredrevs = filteredrevs
254 cl.filteredrevs = filteredrevs
244
255
245 class filteredchangelog(filteredchangelogmixin, cl.__class__):
256 class filteredchangelog(filteredchangelogmixin, cl.__class__):
246 pass
257 pass
247
258
248 cl.__class__ = filteredchangelog
259 cl.__class__ = filteredchangelog
249
260
250 return cl
261 return cl
251
262
252
263
253 class filteredchangelogmixin(object):
264 class filteredchangelogmixin(object):
254 def tiprev(self):
265 def tiprev(self):
255 """filtered version of revlog.tiprev"""
266 """filtered version of revlog.tiprev"""
256 for i in pycompat.xrange(len(self) - 1, -2, -1):
267 for i in pycompat.xrange(len(self) - 1, -2, -1):
257 if i not in self.filteredrevs:
268 if i not in self.filteredrevs:
258 return i
269 return i
259
270
260 def __contains__(self, rev):
271 def __contains__(self, rev):
261 """filtered version of revlog.__contains__"""
272 """filtered version of revlog.__contains__"""
262 return 0 <= rev < len(self) and rev not in self.filteredrevs
273 return 0 <= rev < len(self) and rev not in self.filteredrevs
263
274
264 def __iter__(self):
275 def __iter__(self):
265 """filtered version of revlog.__iter__"""
276 """filtered version of revlog.__iter__"""
266
277
267 def filterediter():
278 def filterediter():
268 for i in pycompat.xrange(len(self)):
279 for i in pycompat.xrange(len(self)):
269 if i not in self.filteredrevs:
280 if i not in self.filteredrevs:
270 yield i
281 yield i
271
282
272 return filterediter()
283 return filterediter()
273
284
274 def revs(self, start=0, stop=None):
285 def revs(self, start=0, stop=None):
275 """filtered version of revlog.revs"""
286 """filtered version of revlog.revs"""
276 for i in super(filteredchangelogmixin, self).revs(start, stop):
287 for i in super(filteredchangelogmixin, self).revs(start, stop):
277 if i not in self.filteredrevs:
288 if i not in self.filteredrevs:
278 yield i
289 yield i
279
290
280 def _checknofilteredinrevs(self, revs):
291 def _checknofilteredinrevs(self, revs):
281 """raise the appropriate error if 'revs' contains a filtered revision
292 """raise the appropriate error if 'revs' contains a filtered revision
282
293
283 This returns a version of 'revs' to be used thereafter by the caller.
294 This returns a version of 'revs' to be used thereafter by the caller.
284 In particular, if revs is an iterator, it is converted into a set.
295 In particular, if revs is an iterator, it is converted into a set.
285 """
296 """
286 safehasattr = util.safehasattr
297 safehasattr = util.safehasattr
287 if safehasattr(revs, '__next__'):
298 if safehasattr(revs, '__next__'):
288 # Note that inspect.isgenerator() is not true for iterators,
299 # Note that inspect.isgenerator() is not true for iterators,
289 revs = set(revs)
300 revs = set(revs)
290
301
291 filteredrevs = self.filteredrevs
302 filteredrevs = self.filteredrevs
292 if safehasattr(revs, 'first'): # smartset
303 if safehasattr(revs, 'first'): # smartset
293 offenders = revs & filteredrevs
304 offenders = revs & filteredrevs
294 else:
305 else:
295 offenders = filteredrevs.intersection(revs)
306 offenders = filteredrevs.intersection(revs)
296
307
297 for rev in offenders:
308 for rev in offenders:
298 raise error.FilteredIndexError(rev)
309 raise error.FilteredIndexError(rev)
299 return revs
310 return revs
300
311
301 def headrevs(self, revs=None):
312 def headrevs(self, revs=None):
302 if revs is None:
313 if revs is None:
303 try:
314 try:
304 return self.index.headrevsfiltered(self.filteredrevs)
315 return self.index.headrevsfiltered(self.filteredrevs)
305 # AttributeError covers non-c-extension environments and
316 # AttributeError covers non-c-extension environments and
306 # old c extensions without filter handling.
317 # old c extensions without filter handling.
307 except AttributeError:
318 except AttributeError:
308 return self._headrevs()
319 return self._headrevs()
309
320
310 revs = self._checknofilteredinrevs(revs)
321 revs = self._checknofilteredinrevs(revs)
311 return super(filteredchangelogmixin, self).headrevs(revs)
322 return super(filteredchangelogmixin, self).headrevs(revs)
312
323
313 def strip(self, *args, **kwargs):
324 def strip(self, *args, **kwargs):
314 # XXX make something better than assert
325 # XXX make something better than assert
315 # We can't expect proper strip behavior if we are filtered.
326 # We can't expect proper strip behavior if we are filtered.
316 assert not self.filteredrevs
327 assert not self.filteredrevs
317 super(filteredchangelogmixin, self).strip(*args, **kwargs)
328 super(filteredchangelogmixin, self).strip(*args, **kwargs)
318
329
319 def rev(self, node):
330 def rev(self, node):
320 """filtered version of revlog.rev"""
331 """filtered version of revlog.rev"""
321 r = super(filteredchangelogmixin, self).rev(node)
332 r = super(filteredchangelogmixin, self).rev(node)
322 if r in self.filteredrevs:
333 if r in self.filteredrevs:
323 raise error.FilteredLookupError(
334 raise error.FilteredLookupError(
324 hex(node), self.indexfile, _(b'filtered node')
335 hex(node), self.indexfile, _(b'filtered node')
325 )
336 )
326 return r
337 return r
327
338
328 def node(self, rev):
339 def node(self, rev):
329 """filtered version of revlog.node"""
340 """filtered version of revlog.node"""
330 if rev in self.filteredrevs:
341 if rev in self.filteredrevs:
331 raise error.FilteredIndexError(rev)
342 raise error.FilteredIndexError(rev)
332 return super(filteredchangelogmixin, self).node(rev)
343 return super(filteredchangelogmixin, self).node(rev)
333
344
334 def linkrev(self, rev):
345 def linkrev(self, rev):
335 """filtered version of revlog.linkrev"""
346 """filtered version of revlog.linkrev"""
336 if rev in self.filteredrevs:
347 if rev in self.filteredrevs:
337 raise error.FilteredIndexError(rev)
348 raise error.FilteredIndexError(rev)
338 return super(filteredchangelogmixin, self).linkrev(rev)
349 return super(filteredchangelogmixin, self).linkrev(rev)
339
350
340 def parentrevs(self, rev):
351 def parentrevs(self, rev):
341 """filtered version of revlog.parentrevs"""
352 """filtered version of revlog.parentrevs"""
342 if rev in self.filteredrevs:
353 if rev in self.filteredrevs:
343 raise error.FilteredIndexError(rev)
354 raise error.FilteredIndexError(rev)
344 return super(filteredchangelogmixin, self).parentrevs(rev)
355 return super(filteredchangelogmixin, self).parentrevs(rev)
345
356
346 def flags(self, rev):
357 def flags(self, rev):
347 """filtered version of revlog.flags"""
358 """filtered version of revlog.flags"""
348 if rev in self.filteredrevs:
359 if rev in self.filteredrevs:
349 raise error.FilteredIndexError(rev)
360 raise error.FilteredIndexError(rev)
350 return super(filteredchangelogmixin, self).flags(rev)
361 return super(filteredchangelogmixin, self).flags(rev)
351
362
352
363
353 class repoview(object):
364 class repoview(object):
354 """Provide a read/write view of a repo through a filtered changelog
365 """Provide a read/write view of a repo through a filtered changelog
355
366
356 This object is used to access a filtered version of a repository without
367 This object is used to access a filtered version of a repository without
357 altering the original repository object itself. We can not alter the
368 altering the original repository object itself. We can not alter the
358 original object for two main reasons:
369 original object for two main reasons:
359 - It prevents the use of a repo with multiple filters at the same time. In
370 - It prevents the use of a repo with multiple filters at the same time. In
360 particular when multiple threads are involved.
371 particular when multiple threads are involved.
361 - It makes scope of the filtering harder to control.
372 - It makes scope of the filtering harder to control.
362
373
363 This object behaves very closely to the original repository. All attribute
374 This object behaves very closely to the original repository. All attribute
364 operations are done on the original repository:
375 operations are done on the original repository:
365 - An access to `repoview.someattr` actually returns `repo.someattr`,
376 - An access to `repoview.someattr` actually returns `repo.someattr`,
366 - A write to `repoview.someattr` actually sets value of `repo.someattr`,
377 - A write to `repoview.someattr` actually sets value of `repo.someattr`,
367 - A deletion of `repoview.someattr` actually drops `someattr`
378 - A deletion of `repoview.someattr` actually drops `someattr`
368 from `repo.__dict__`.
379 from `repo.__dict__`.
369
380
370 The only exception is the `changelog` property. It is overridden to return
381 The only exception is the `changelog` property. It is overridden to return
371 a (surface) copy of `repo.changelog` with some revisions filtered. The
382 a (surface) copy of `repo.changelog` with some revisions filtered. The
372 `filtername` attribute of the view control the revisions that need to be
383 `filtername` attribute of the view control the revisions that need to be
373 filtered. (the fact the changelog is copied is an implementation detail).
384 filtered. (the fact the changelog is copied is an implementation detail).
374
385
375 Unlike attributes, this object intercepts all method calls. This means that
386 Unlike attributes, this object intercepts all method calls. This means that
376 all methods are run on the `repoview` object with the filtered `changelog`
387 all methods are run on the `repoview` object with the filtered `changelog`
377 property. For this purpose the simple `repoview` class must be mixed with
388 property. For this purpose the simple `repoview` class must be mixed with
378 the actual class of the repository. This ensures that the resulting
389 the actual class of the repository. This ensures that the resulting
379 `repoview` object have the very same methods than the repo object. This
390 `repoview` object have the very same methods than the repo object. This
380 leads to the property below.
391 leads to the property below.
381
392
382 repoview.method() --> repo.__class__.method(repoview)
393 repoview.method() --> repo.__class__.method(repoview)
383
394
384 The inheritance has to be done dynamically because `repo` can be of any
395 The inheritance has to be done dynamically because `repo` can be of any
385 subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
396 subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
386 """
397 """
387
398
388 def __init__(self, repo, filtername, visibilityexceptions=None):
399 def __init__(self, repo, filtername, visibilityexceptions=None):
389 object.__setattr__(self, '_unfilteredrepo', repo)
400 object.__setattr__(self, '_unfilteredrepo', repo)
390 object.__setattr__(self, 'filtername', filtername)
401 object.__setattr__(self, 'filtername', filtername)
391 object.__setattr__(self, '_clcachekey', None)
402 object.__setattr__(self, '_clcachekey', None)
392 object.__setattr__(self, '_clcache', None)
403 object.__setattr__(self, '_clcache', None)
393 # revs which are exceptions and must not be hidden
404 # revs which are exceptions and must not be hidden
394 object.__setattr__(self, '_visibilityexceptions', visibilityexceptions)
405 object.__setattr__(self, '_visibilityexceptions', visibilityexceptions)
395
406
396 # not a propertycache on purpose we shall implement a proper cache later
407 # not a propertycache on purpose we shall implement a proper cache later
397 @property
408 @property
398 def changelog(self):
409 def changelog(self):
399 """return a filtered version of the changeset
410 """return a filtered version of the changeset
400
411
401 this changelog must not be used for writing"""
412 this changelog must not be used for writing"""
402 # some cache may be implemented later
413 # some cache may be implemented later
403 unfi = self._unfilteredrepo
414 unfi = self._unfilteredrepo
404 unfichangelog = unfi.changelog
415 unfichangelog = unfi.changelog
405 # bypass call to changelog.method
416 # bypass call to changelog.method
406 unfiindex = unfichangelog.index
417 unfiindex = unfichangelog.index
407 unfilen = len(unfiindex)
418 unfilen = len(unfiindex)
408 unfinode = unfiindex[unfilen - 1][7]
419 unfinode = unfiindex[unfilen - 1][7]
409 with util.timedcm('repo filter for %s', self.filtername):
420 with util.timedcm('repo filter for %s', self.filtername):
410 revs = filterrevs(unfi, self.filtername, self._visibilityexceptions)
421 revs = filterrevs(unfi, self.filtername, self._visibilityexceptions)
411 cl = self._clcache
422 cl = self._clcache
412 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed)
423 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed)
413 # if cl.index is not unfiindex, unfi.changelog would be
424 # if cl.index is not unfiindex, unfi.changelog would be
414 # recreated, and our clcache refers to garbage object
425 # recreated, and our clcache refers to garbage object
415 if cl is not None and (
426 if cl is not None and (
416 cl.index is not unfiindex or newkey != self._clcachekey
427 cl.index is not unfiindex or newkey != self._clcachekey
417 ):
428 ):
418 cl = None
429 cl = None
419 # could have been made None by the previous if
430 # could have been made None by the previous if
420 if cl is None:
431 if cl is None:
421 # Only filter if there's something to filter
432 # Only filter if there's something to filter
422 cl = wrapchangelog(unfichangelog, revs) if revs else unfichangelog
433 cl = wrapchangelog(unfichangelog, revs) if revs else unfichangelog
423 object.__setattr__(self, '_clcache', cl)
434 object.__setattr__(self, '_clcache', cl)
424 object.__setattr__(self, '_clcachekey', newkey)
435 object.__setattr__(self, '_clcachekey', newkey)
425 return cl
436 return cl
426
437
427 def unfiltered(self):
438 def unfiltered(self):
428 """Return an unfiltered version of a repo"""
439 """Return an unfiltered version of a repo"""
429 return self._unfilteredrepo
440 return self._unfilteredrepo
430
441
431 def filtered(self, name, visibilityexceptions=None):
442 def filtered(self, name, visibilityexceptions=None):
432 """Return a filtered version of a repository"""
443 """Return a filtered version of a repository"""
433 if name == self.filtername and not visibilityexceptions:
444 if name == self.filtername and not visibilityexceptions:
434 return self
445 return self
435 return self.unfiltered().filtered(name, visibilityexceptions)
446 return self.unfiltered().filtered(name, visibilityexceptions)
436
447
437 def __repr__(self):
448 def __repr__(self):
438 return '<%s:%s %r>' % (
449 return '<%s:%s %r>' % (
439 self.__class__.__name__,
450 self.__class__.__name__,
440 pycompat.sysstr(self.filtername),
451 pycompat.sysstr(self.filtername),
441 self.unfiltered(),
452 self.unfiltered(),
442 )
453 )
443
454
444 # everything access are forwarded to the proxied repo
455 # everything access are forwarded to the proxied repo
445 def __getattr__(self, attr):
456 def __getattr__(self, attr):
446 return getattr(self._unfilteredrepo, attr)
457 return getattr(self._unfilteredrepo, attr)
447
458
448 def __setattr__(self, attr, value):
459 def __setattr__(self, attr, value):
449 return setattr(self._unfilteredrepo, attr, value)
460 return setattr(self._unfilteredrepo, attr, value)
450
461
451 def __delattr__(self, attr):
462 def __delattr__(self, attr):
452 return delattr(self._unfilteredrepo, attr)
463 return delattr(self._unfilteredrepo, attr)
453
464
454
465
455 # Python <3.4 easily leaks types via __mro__. See
466 # Python <3.4 easily leaks types via __mro__. See
456 # https://bugs.python.org/issue17950. We cache dynamically created types
467 # https://bugs.python.org/issue17950. We cache dynamically created types
457 # so they won't be leaked on every invocation of repo.filtered().
468 # so they won't be leaked on every invocation of repo.filtered().
458 _filteredrepotypes = weakref.WeakKeyDictionary()
469 _filteredrepotypes = weakref.WeakKeyDictionary()
459
470
460
471
461 def newtype(base):
472 def newtype(base):
462 """Create a new type with the repoview mixin and the given base class"""
473 """Create a new type with the repoview mixin and the given base class"""
463 if base not in _filteredrepotypes:
474 if base not in _filteredrepotypes:
464
475
465 class filteredrepo(repoview, base):
476 class filteredrepo(repoview, base):
466 pass
477 pass
467
478
468 _filteredrepotypes[base] = filteredrepo
479 _filteredrepotypes[base] = filteredrepo
469 return _filteredrepotypes[base]
480 return _filteredrepotypes[base]
@@ -1,2790 +1,2835 b''
1 Log on empty repository: checking consistency
1 Log on empty repository: checking consistency
2
2
3 $ hg init empty
3 $ hg init empty
4 $ cd empty
4 $ cd empty
5 $ hg log
5 $ hg log
6 $ hg log -r 1
6 $ hg log -r 1
7 abort: unknown revision '1'!
7 abort: unknown revision '1'!
8 [255]
8 [255]
9 $ hg log -r -1:0
9 $ hg log -r -1:0
10 abort: unknown revision '-1'!
10 abort: unknown revision '-1'!
11 [255]
11 [255]
12 $ hg log -r 'branch(name)'
12 $ hg log -r 'branch(name)'
13 abort: unknown revision 'name'!
13 abort: unknown revision 'name'!
14 [255]
14 [255]
15 $ hg log -r null -q
15 $ hg log -r null -q
16 -1:000000000000
16 -1:000000000000
17
17
18 $ cd ..
18 $ cd ..
19
19
20 The g is crafted to have 2 filelog topological heads in a linear
20 The g is crafted to have 2 filelog topological heads in a linear
21 changeset graph
21 changeset graph
22
22
23 $ hg init a
23 $ hg init a
24 $ cd a
24 $ cd a
25 $ echo a > a
25 $ echo a > a
26 $ echo f > f
26 $ echo f > f
27 $ hg ci -Ama -d '1 0'
27 $ hg ci -Ama -d '1 0'
28 adding a
28 adding a
29 adding f
29 adding f
30
30
31 $ hg cp a b
31 $ hg cp a b
32 $ hg cp f g
32 $ hg cp f g
33 $ hg ci -mb -d '2 0'
33 $ hg ci -mb -d '2 0'
34
34
35 $ mkdir dir
35 $ mkdir dir
36 $ hg mv b dir
36 $ hg mv b dir
37 $ echo g >> g
37 $ echo g >> g
38 $ echo f >> f
38 $ echo f >> f
39 $ hg ci -mc -d '3 0'
39 $ hg ci -mc -d '3 0'
40
40
41 $ hg mv a b
41 $ hg mv a b
42 $ hg cp -f f g
42 $ hg cp -f f g
43 $ echo a > d
43 $ echo a > d
44 $ hg add d
44 $ hg add d
45 $ hg ci -md -d '4 0'
45 $ hg ci -md -d '4 0'
46
46
47 $ hg mv dir/b e
47 $ hg mv dir/b e
48 $ hg ci -me -d '5 0'
48 $ hg ci -me -d '5 0'
49
49
50 Make sure largefiles doesn't interfere with logging a regular file
50 Make sure largefiles doesn't interfere with logging a regular file
51 $ hg --debug log a -T '{rev}: {desc}\n' --config extensions.largefiles=
51 $ hg --debug log a -T '{rev}: {desc}\n' --config extensions.largefiles=
52 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
52 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
53 updated patterns: .hglf/a, a
53 updated patterns: .hglf/a, a
54 0: a
54 0: a
55 $ hg log a
55 $ hg log a
56 changeset: 0:9161b9aeaf16
56 changeset: 0:9161b9aeaf16
57 user: test
57 user: test
58 date: Thu Jan 01 00:00:01 1970 +0000
58 date: Thu Jan 01 00:00:01 1970 +0000
59 summary: a
59 summary: a
60
60
61 $ hg log glob:a*
61 $ hg log glob:a*
62 changeset: 3:2ca5ba701980
62 changeset: 3:2ca5ba701980
63 user: test
63 user: test
64 date: Thu Jan 01 00:00:04 1970 +0000
64 date: Thu Jan 01 00:00:04 1970 +0000
65 summary: d
65 summary: d
66
66
67 changeset: 0:9161b9aeaf16
67 changeset: 0:9161b9aeaf16
68 user: test
68 user: test
69 date: Thu Jan 01 00:00:01 1970 +0000
69 date: Thu Jan 01 00:00:01 1970 +0000
70 summary: a
70 summary: a
71
71
72 $ hg --debug log glob:a* -T '{rev}: {desc}\n' --config extensions.largefiles=
72 $ hg --debug log glob:a* -T '{rev}: {desc}\n' --config extensions.largefiles=
73 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
73 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
74 updated patterns: glob:.hglf/a*, glob:a*
74 updated patterns: glob:.hglf/a*, glob:a*
75 3: d
75 3: d
76 0: a
76 0: a
77
77
78 log on directory
78 log on directory
79
79
80 $ hg log dir
80 $ hg log dir
81 changeset: 4:7e4639b4691b
81 changeset: 4:7e4639b4691b
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:05 1970 +0000
84 date: Thu Jan 01 00:00:05 1970 +0000
85 summary: e
85 summary: e
86
86
87 changeset: 2:f8954cd4dc1f
87 changeset: 2:f8954cd4dc1f
88 user: test
88 user: test
89 date: Thu Jan 01 00:00:03 1970 +0000
89 date: Thu Jan 01 00:00:03 1970 +0000
90 summary: c
90 summary: c
91
91
92 $ hg log somethingthatdoesntexist dir
92 $ hg log somethingthatdoesntexist dir
93 changeset: 4:7e4639b4691b
93 changeset: 4:7e4639b4691b
94 tag: tip
94 tag: tip
95 user: test
95 user: test
96 date: Thu Jan 01 00:00:05 1970 +0000
96 date: Thu Jan 01 00:00:05 1970 +0000
97 summary: e
97 summary: e
98
98
99 changeset: 2:f8954cd4dc1f
99 changeset: 2:f8954cd4dc1f
100 user: test
100 user: test
101 date: Thu Jan 01 00:00:03 1970 +0000
101 date: Thu Jan 01 00:00:03 1970 +0000
102 summary: c
102 summary: c
103
103
104
104
105 -X, with explicit path
105 -X, with explicit path
106
106
107 $ hg log a -X a
107 $ hg log a -X a
108
108
109 -f, non-existent directory
109 -f, non-existent directory
110
110
111 $ hg log -f dir
111 $ hg log -f dir
112 abort: cannot follow file not in parent revision: "dir"
112 abort: cannot follow file not in parent revision: "dir"
113 [255]
113 [255]
114
114
115 -f, directory
115 -f, directory
116
116
117 $ hg up -q 3
117 $ hg up -q 3
118 $ hg log -f dir
118 $ hg log -f dir
119 changeset: 2:f8954cd4dc1f
119 changeset: 2:f8954cd4dc1f
120 user: test
120 user: test
121 date: Thu Jan 01 00:00:03 1970 +0000
121 date: Thu Jan 01 00:00:03 1970 +0000
122 summary: c
122 summary: c
123
123
124 -f, directory with --patch
124 -f, directory with --patch
125
125
126 $ hg log -f dir -p
126 $ hg log -f dir -p
127 changeset: 2:f8954cd4dc1f
127 changeset: 2:f8954cd4dc1f
128 user: test
128 user: test
129 date: Thu Jan 01 00:00:03 1970 +0000
129 date: Thu Jan 01 00:00:03 1970 +0000
130 summary: c
130 summary: c
131
131
132 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
132 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
133 --- /dev/null* (glob)
133 --- /dev/null* (glob)
134 +++ b/dir/b* (glob)
134 +++ b/dir/b* (glob)
135 @@ -0,0 +1,1 @@
135 @@ -0,0 +1,1 @@
136 +a
136 +a
137
137
138
138
139 -f, pattern
139 -f, pattern
140
140
141 $ hg log -f -I 'dir**' -p
141 $ hg log -f -I 'dir**' -p
142 changeset: 2:f8954cd4dc1f
142 changeset: 2:f8954cd4dc1f
143 user: test
143 user: test
144 date: Thu Jan 01 00:00:03 1970 +0000
144 date: Thu Jan 01 00:00:03 1970 +0000
145 summary: c
145 summary: c
146
146
147 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
147 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
148 --- /dev/null* (glob)
148 --- /dev/null* (glob)
149 +++ b/dir/b* (glob)
149 +++ b/dir/b* (glob)
150 @@ -0,0 +1,1 @@
150 @@ -0,0 +1,1 @@
151 +a
151 +a
152
152
153 $ hg up -q 4
153 $ hg up -q 4
154
154
155 -f, a wrong style
155 -f, a wrong style
156
156
157 $ hg log -f -l1 --style something
157 $ hg log -f -l1 --style something
158 abort: style 'something' not found
158 abort: style 'something' not found
159 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
159 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
160 [255]
160 [255]
161
161
162 -f, phases style
162 -f, phases style
163
163
164
164
165 $ hg log -f -l1 --style phases
165 $ hg log -f -l1 --style phases
166 changeset: 4:7e4639b4691b
166 changeset: 4:7e4639b4691b
167 tag: tip
167 tag: tip
168 phase: draft
168 phase: draft
169 user: test
169 user: test
170 date: Thu Jan 01 00:00:05 1970 +0000
170 date: Thu Jan 01 00:00:05 1970 +0000
171 summary: e
171 summary: e
172
172
173
173
174 $ hg log -f -l1 --style phases -q
174 $ hg log -f -l1 --style phases -q
175 4:7e4639b4691b
175 4:7e4639b4691b
176
176
177 -f, but no args
177 -f, but no args
178
178
179 $ hg log -f
179 $ hg log -f
180 changeset: 4:7e4639b4691b
180 changeset: 4:7e4639b4691b
181 tag: tip
181 tag: tip
182 user: test
182 user: test
183 date: Thu Jan 01 00:00:05 1970 +0000
183 date: Thu Jan 01 00:00:05 1970 +0000
184 summary: e
184 summary: e
185
185
186 changeset: 3:2ca5ba701980
186 changeset: 3:2ca5ba701980
187 user: test
187 user: test
188 date: Thu Jan 01 00:00:04 1970 +0000
188 date: Thu Jan 01 00:00:04 1970 +0000
189 summary: d
189 summary: d
190
190
191 changeset: 2:f8954cd4dc1f
191 changeset: 2:f8954cd4dc1f
192 user: test
192 user: test
193 date: Thu Jan 01 00:00:03 1970 +0000
193 date: Thu Jan 01 00:00:03 1970 +0000
194 summary: c
194 summary: c
195
195
196 changeset: 1:d89b0a12d229
196 changeset: 1:d89b0a12d229
197 user: test
197 user: test
198 date: Thu Jan 01 00:00:02 1970 +0000
198 date: Thu Jan 01 00:00:02 1970 +0000
199 summary: b
199 summary: b
200
200
201 changeset: 0:9161b9aeaf16
201 changeset: 0:9161b9aeaf16
202 user: test
202 user: test
203 date: Thu Jan 01 00:00:01 1970 +0000
203 date: Thu Jan 01 00:00:01 1970 +0000
204 summary: a
204 summary: a
205
205
206
206
207 one rename
207 one rename
208
208
209 $ hg up -q 2
209 $ hg up -q 2
210 $ hg log -vf a
210 $ hg log -vf a
211 changeset: 0:9161b9aeaf16
211 changeset: 0:9161b9aeaf16
212 user: test
212 user: test
213 date: Thu Jan 01 00:00:01 1970 +0000
213 date: Thu Jan 01 00:00:01 1970 +0000
214 files: a f
214 files: a f
215 description:
215 description:
216 a
216 a
217
217
218
218
219
219
220 many renames
220 many renames
221
221
222 $ hg up -q tip
222 $ hg up -q tip
223 $ hg log -vf e
223 $ hg log -vf e
224 changeset: 4:7e4639b4691b
224 changeset: 4:7e4639b4691b
225 tag: tip
225 tag: tip
226 user: test
226 user: test
227 date: Thu Jan 01 00:00:05 1970 +0000
227 date: Thu Jan 01 00:00:05 1970 +0000
228 files: dir/b e
228 files: dir/b e
229 description:
229 description:
230 e
230 e
231
231
232
232
233 changeset: 2:f8954cd4dc1f
233 changeset: 2:f8954cd4dc1f
234 user: test
234 user: test
235 date: Thu Jan 01 00:00:03 1970 +0000
235 date: Thu Jan 01 00:00:03 1970 +0000
236 files: b dir/b f g
236 files: b dir/b f g
237 description:
237 description:
238 c
238 c
239
239
240
240
241 changeset: 1:d89b0a12d229
241 changeset: 1:d89b0a12d229
242 user: test
242 user: test
243 date: Thu Jan 01 00:00:02 1970 +0000
243 date: Thu Jan 01 00:00:02 1970 +0000
244 files: b g
244 files: b g
245 description:
245 description:
246 b
246 b
247
247
248
248
249 changeset: 0:9161b9aeaf16
249 changeset: 0:9161b9aeaf16
250 user: test
250 user: test
251 date: Thu Jan 01 00:00:01 1970 +0000
251 date: Thu Jan 01 00:00:01 1970 +0000
252 files: a f
252 files: a f
253 description:
253 description:
254 a
254 a
255
255
256
256
257
257
258
258
259 log -pf dir/b
259 log -pf dir/b
260
260
261 $ hg up -q 3
261 $ hg up -q 3
262 $ hg log -pf dir/b
262 $ hg log -pf dir/b
263 changeset: 2:f8954cd4dc1f
263 changeset: 2:f8954cd4dc1f
264 user: test
264 user: test
265 date: Thu Jan 01 00:00:03 1970 +0000
265 date: Thu Jan 01 00:00:03 1970 +0000
266 summary: c
266 summary: c
267
267
268 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
268 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
270 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
271 @@ -0,0 +1,1 @@
271 @@ -0,0 +1,1 @@
272 +a
272 +a
273
273
274 changeset: 1:d89b0a12d229
274 changeset: 1:d89b0a12d229
275 user: test
275 user: test
276 date: Thu Jan 01 00:00:02 1970 +0000
276 date: Thu Jan 01 00:00:02 1970 +0000
277 summary: b
277 summary: b
278
278
279 diff -r 9161b9aeaf16 -r d89b0a12d229 b
279 diff -r 9161b9aeaf16 -r d89b0a12d229 b
280 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
280 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
281 +++ b/b Thu Jan 01 00:00:02 1970 +0000
281 +++ b/b Thu Jan 01 00:00:02 1970 +0000
282 @@ -0,0 +1,1 @@
282 @@ -0,0 +1,1 @@
283 +a
283 +a
284
284
285 changeset: 0:9161b9aeaf16
285 changeset: 0:9161b9aeaf16
286 user: test
286 user: test
287 date: Thu Jan 01 00:00:01 1970 +0000
287 date: Thu Jan 01 00:00:01 1970 +0000
288 summary: a
288 summary: a
289
289
290 diff -r 000000000000 -r 9161b9aeaf16 a
290 diff -r 000000000000 -r 9161b9aeaf16 a
291 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
291 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
292 +++ b/a Thu Jan 01 00:00:01 1970 +0000
292 +++ b/a Thu Jan 01 00:00:01 1970 +0000
293 @@ -0,0 +1,1 @@
293 @@ -0,0 +1,1 @@
294 +a
294 +a
295
295
296
296
297 log -pf b inside dir
297 log -pf b inside dir
298
298
299 $ hg --cwd=dir log -pf b
299 $ hg --cwd=dir log -pf b
300 changeset: 2:f8954cd4dc1f
300 changeset: 2:f8954cd4dc1f
301 user: test
301 user: test
302 date: Thu Jan 01 00:00:03 1970 +0000
302 date: Thu Jan 01 00:00:03 1970 +0000
303 summary: c
303 summary: c
304
304
305 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
305 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
306 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
306 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
307 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
307 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
308 @@ -0,0 +1,1 @@
308 @@ -0,0 +1,1 @@
309 +a
309 +a
310
310
311 changeset: 1:d89b0a12d229
311 changeset: 1:d89b0a12d229
312 user: test
312 user: test
313 date: Thu Jan 01 00:00:02 1970 +0000
313 date: Thu Jan 01 00:00:02 1970 +0000
314 summary: b
314 summary: b
315
315
316 diff -r 9161b9aeaf16 -r d89b0a12d229 b
316 diff -r 9161b9aeaf16 -r d89b0a12d229 b
317 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
317 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
318 +++ b/b Thu Jan 01 00:00:02 1970 +0000
318 +++ b/b Thu Jan 01 00:00:02 1970 +0000
319 @@ -0,0 +1,1 @@
319 @@ -0,0 +1,1 @@
320 +a
320 +a
321
321
322 changeset: 0:9161b9aeaf16
322 changeset: 0:9161b9aeaf16
323 user: test
323 user: test
324 date: Thu Jan 01 00:00:01 1970 +0000
324 date: Thu Jan 01 00:00:01 1970 +0000
325 summary: a
325 summary: a
326
326
327 diff -r 000000000000 -r 9161b9aeaf16 a
327 diff -r 000000000000 -r 9161b9aeaf16 a
328 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
328 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
329 +++ b/a Thu Jan 01 00:00:01 1970 +0000
329 +++ b/a Thu Jan 01 00:00:01 1970 +0000
330 @@ -0,0 +1,1 @@
330 @@ -0,0 +1,1 @@
331 +a
331 +a
332
332
333
333
334 log -pf, but no args
334 log -pf, but no args
335
335
336 $ hg log -pf
336 $ hg log -pf
337 changeset: 3:2ca5ba701980
337 changeset: 3:2ca5ba701980
338 user: test
338 user: test
339 date: Thu Jan 01 00:00:04 1970 +0000
339 date: Thu Jan 01 00:00:04 1970 +0000
340 summary: d
340 summary: d
341
341
342 diff -r f8954cd4dc1f -r 2ca5ba701980 a
342 diff -r f8954cd4dc1f -r 2ca5ba701980 a
343 --- a/a Thu Jan 01 00:00:03 1970 +0000
343 --- a/a Thu Jan 01 00:00:03 1970 +0000
344 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
344 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
345 @@ -1,1 +0,0 @@
345 @@ -1,1 +0,0 @@
346 -a
346 -a
347 diff -r f8954cd4dc1f -r 2ca5ba701980 b
347 diff -r f8954cd4dc1f -r 2ca5ba701980 b
348 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
348 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
349 +++ b/b Thu Jan 01 00:00:04 1970 +0000
349 +++ b/b Thu Jan 01 00:00:04 1970 +0000
350 @@ -0,0 +1,1 @@
350 @@ -0,0 +1,1 @@
351 +a
351 +a
352 diff -r f8954cd4dc1f -r 2ca5ba701980 d
352 diff -r f8954cd4dc1f -r 2ca5ba701980 d
353 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
353 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
354 +++ b/d Thu Jan 01 00:00:04 1970 +0000
354 +++ b/d Thu Jan 01 00:00:04 1970 +0000
355 @@ -0,0 +1,1 @@
355 @@ -0,0 +1,1 @@
356 +a
356 +a
357 diff -r f8954cd4dc1f -r 2ca5ba701980 g
357 diff -r f8954cd4dc1f -r 2ca5ba701980 g
358 --- a/g Thu Jan 01 00:00:03 1970 +0000
358 --- a/g Thu Jan 01 00:00:03 1970 +0000
359 +++ b/g Thu Jan 01 00:00:04 1970 +0000
359 +++ b/g Thu Jan 01 00:00:04 1970 +0000
360 @@ -1,2 +1,2 @@
360 @@ -1,2 +1,2 @@
361 f
361 f
362 -g
362 -g
363 +f
363 +f
364
364
365 changeset: 2:f8954cd4dc1f
365 changeset: 2:f8954cd4dc1f
366 user: test
366 user: test
367 date: Thu Jan 01 00:00:03 1970 +0000
367 date: Thu Jan 01 00:00:03 1970 +0000
368 summary: c
368 summary: c
369
369
370 diff -r d89b0a12d229 -r f8954cd4dc1f b
370 diff -r d89b0a12d229 -r f8954cd4dc1f b
371 --- a/b Thu Jan 01 00:00:02 1970 +0000
371 --- a/b Thu Jan 01 00:00:02 1970 +0000
372 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
372 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
373 @@ -1,1 +0,0 @@
373 @@ -1,1 +0,0 @@
374 -a
374 -a
375 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
375 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
376 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
376 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
377 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
377 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
378 @@ -0,0 +1,1 @@
378 @@ -0,0 +1,1 @@
379 +a
379 +a
380 diff -r d89b0a12d229 -r f8954cd4dc1f f
380 diff -r d89b0a12d229 -r f8954cd4dc1f f
381 --- a/f Thu Jan 01 00:00:02 1970 +0000
381 --- a/f Thu Jan 01 00:00:02 1970 +0000
382 +++ b/f Thu Jan 01 00:00:03 1970 +0000
382 +++ b/f Thu Jan 01 00:00:03 1970 +0000
383 @@ -1,1 +1,2 @@
383 @@ -1,1 +1,2 @@
384 f
384 f
385 +f
385 +f
386 diff -r d89b0a12d229 -r f8954cd4dc1f g
386 diff -r d89b0a12d229 -r f8954cd4dc1f g
387 --- a/g Thu Jan 01 00:00:02 1970 +0000
387 --- a/g Thu Jan 01 00:00:02 1970 +0000
388 +++ b/g Thu Jan 01 00:00:03 1970 +0000
388 +++ b/g Thu Jan 01 00:00:03 1970 +0000
389 @@ -1,1 +1,2 @@
389 @@ -1,1 +1,2 @@
390 f
390 f
391 +g
391 +g
392
392
393 changeset: 1:d89b0a12d229
393 changeset: 1:d89b0a12d229
394 user: test
394 user: test
395 date: Thu Jan 01 00:00:02 1970 +0000
395 date: Thu Jan 01 00:00:02 1970 +0000
396 summary: b
396 summary: b
397
397
398 diff -r 9161b9aeaf16 -r d89b0a12d229 b
398 diff -r 9161b9aeaf16 -r d89b0a12d229 b
399 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
400 +++ b/b Thu Jan 01 00:00:02 1970 +0000
400 +++ b/b Thu Jan 01 00:00:02 1970 +0000
401 @@ -0,0 +1,1 @@
401 @@ -0,0 +1,1 @@
402 +a
402 +a
403 diff -r 9161b9aeaf16 -r d89b0a12d229 g
403 diff -r 9161b9aeaf16 -r d89b0a12d229 g
404 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
404 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
405 +++ b/g Thu Jan 01 00:00:02 1970 +0000
405 +++ b/g Thu Jan 01 00:00:02 1970 +0000
406 @@ -0,0 +1,1 @@
406 @@ -0,0 +1,1 @@
407 +f
407 +f
408
408
409 changeset: 0:9161b9aeaf16
409 changeset: 0:9161b9aeaf16
410 user: test
410 user: test
411 date: Thu Jan 01 00:00:01 1970 +0000
411 date: Thu Jan 01 00:00:01 1970 +0000
412 summary: a
412 summary: a
413
413
414 diff -r 000000000000 -r 9161b9aeaf16 a
414 diff -r 000000000000 -r 9161b9aeaf16 a
415 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
415 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
416 +++ b/a Thu Jan 01 00:00:01 1970 +0000
416 +++ b/a Thu Jan 01 00:00:01 1970 +0000
417 @@ -0,0 +1,1 @@
417 @@ -0,0 +1,1 @@
418 +a
418 +a
419 diff -r 000000000000 -r 9161b9aeaf16 f
419 diff -r 000000000000 -r 9161b9aeaf16 f
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
421 +++ b/f Thu Jan 01 00:00:01 1970 +0000
421 +++ b/f Thu Jan 01 00:00:01 1970 +0000
422 @@ -0,0 +1,1 @@
422 @@ -0,0 +1,1 @@
423 +f
423 +f
424
424
425
425
426 log -vf dir/b
426 log -vf dir/b
427
427
428 $ hg log -vf dir/b
428 $ hg log -vf dir/b
429 changeset: 2:f8954cd4dc1f
429 changeset: 2:f8954cd4dc1f
430 user: test
430 user: test
431 date: Thu Jan 01 00:00:03 1970 +0000
431 date: Thu Jan 01 00:00:03 1970 +0000
432 files: b dir/b f g
432 files: b dir/b f g
433 description:
433 description:
434 c
434 c
435
435
436
436
437 changeset: 1:d89b0a12d229
437 changeset: 1:d89b0a12d229
438 user: test
438 user: test
439 date: Thu Jan 01 00:00:02 1970 +0000
439 date: Thu Jan 01 00:00:02 1970 +0000
440 files: b g
440 files: b g
441 description:
441 description:
442 b
442 b
443
443
444
444
445 changeset: 0:9161b9aeaf16
445 changeset: 0:9161b9aeaf16
446 user: test
446 user: test
447 date: Thu Jan 01 00:00:01 1970 +0000
447 date: Thu Jan 01 00:00:01 1970 +0000
448 files: a f
448 files: a f
449 description:
449 description:
450 a
450 a
451
451
452
452
453
453
454
454
455 -f and multiple filelog heads
455 -f and multiple filelog heads
456
456
457 $ hg up -q 2
457 $ hg up -q 2
458 $ hg log -f g --template '{rev}\n'
458 $ hg log -f g --template '{rev}\n'
459 2
459 2
460 1
460 1
461 0
461 0
462 $ hg up -q tip
462 $ hg up -q tip
463 $ hg log -f g --template '{rev}\n'
463 $ hg log -f g --template '{rev}\n'
464 3
464 3
465 2
465 2
466 0
466 0
467
467
468 follow files from the specified revisions (issue4959)
468 follow files from the specified revisions (issue4959)
469
469
470 $ hg log -G -T '{rev} {files},{file_copies % " {source}->{name}"}\n'
470 $ hg log -G -T '{rev} {files},{file_copies % " {source}->{name}"}\n'
471 @ 4 dir/b e, dir/b->e
471 @ 4 dir/b e, dir/b->e
472 |
472 |
473 o 3 a b d g, a->b f->g
473 o 3 a b d g, a->b f->g
474 |
474 |
475 o 2 b dir/b f g, b->dir/b
475 o 2 b dir/b f g, b->dir/b
476 |
476 |
477 o 1 b g, a->b f->g
477 o 1 b g, a->b f->g
478 |
478 |
479 o 0 a f,
479 o 0 a f,
480
480
481
481
482 $ hg log -T '{rev}\n' -fr 4 e
482 $ hg log -T '{rev}\n' -fr 4 e
483 4
483 4
484 2
484 2
485 1
485 1
486 0
486 0
487 $ hg log -T '{rev}\n' -fr 2 g
487 $ hg log -T '{rev}\n' -fr 2 g
488 2
488 2
489 1
489 1
490 0
490 0
491 $ hg log -T '{rev}\n' -fr '2+3' g
491 $ hg log -T '{rev}\n' -fr '2+3' g
492 3
492 3
493 2
493 2
494 1
494 1
495 0
495 0
496
496
497 follow files from the specified revisions with glob patterns (issue5053)
497 follow files from the specified revisions with glob patterns (issue5053)
498 (BROKEN: should follow copies from e@4)
498 (BROKEN: should follow copies from e@4)
499
499
500 $ hg log -T '{rev}\n' -fr4 e -X '[abcdfg]'
500 $ hg log -T '{rev}\n' -fr4 e -X '[abcdfg]'
501 4
501 4
502 2 (false !)
502 2 (false !)
503 1 (false !)
503 1 (false !)
504 0 (false !)
504 0 (false !)
505
505
506 follow files from the specified revisions with missing patterns
506 follow files from the specified revisions with missing patterns
507 (BROKEN: should follow copies from e@4)
507 (BROKEN: should follow copies from e@4)
508
508
509 $ hg log -T '{rev}\n' -fr4 e x
509 $ hg log -T '{rev}\n' -fr4 e x
510 4
510 4
511 2 (false !)
511 2 (false !)
512 1 (false !)
512 1 (false !)
513 0 (false !)
513 0 (false !)
514
514
515 follow files from the specified revisions across copies with -p/--patch
515 follow files from the specified revisions across copies with -p/--patch
516
516
517 $ hg log -T '== rev: {rev},{file_copies % " {source}->{name}"} ==\n' -fpr 4 e g
517 $ hg log -T '== rev: {rev},{file_copies % " {source}->{name}"} ==\n' -fpr 4 e g
518 == rev: 4, dir/b->e ==
518 == rev: 4, dir/b->e ==
519 diff -r 2ca5ba701980 -r 7e4639b4691b e
519 diff -r 2ca5ba701980 -r 7e4639b4691b e
520 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
520 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
521 +++ b/e Thu Jan 01 00:00:05 1970 +0000
521 +++ b/e Thu Jan 01 00:00:05 1970 +0000
522 @@ -0,0 +1,1 @@
522 @@ -0,0 +1,1 @@
523 +a
523 +a
524
524
525 == rev: 3, a->b f->g ==
525 == rev: 3, a->b f->g ==
526 diff -r f8954cd4dc1f -r 2ca5ba701980 g
526 diff -r f8954cd4dc1f -r 2ca5ba701980 g
527 --- a/g Thu Jan 01 00:00:03 1970 +0000
527 --- a/g Thu Jan 01 00:00:03 1970 +0000
528 +++ b/g Thu Jan 01 00:00:04 1970 +0000
528 +++ b/g Thu Jan 01 00:00:04 1970 +0000
529 @@ -1,2 +1,2 @@
529 @@ -1,2 +1,2 @@
530 f
530 f
531 -g
531 -g
532 +f
532 +f
533
533
534 == rev: 2, b->dir/b ==
534 == rev: 2, b->dir/b ==
535 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
535 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
536 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
536 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
537 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
537 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
538 @@ -0,0 +1,1 @@
538 @@ -0,0 +1,1 @@
539 +a
539 +a
540 diff -r d89b0a12d229 -r f8954cd4dc1f f
540 diff -r d89b0a12d229 -r f8954cd4dc1f f
541 --- a/f Thu Jan 01 00:00:02 1970 +0000
541 --- a/f Thu Jan 01 00:00:02 1970 +0000
542 +++ b/f Thu Jan 01 00:00:03 1970 +0000
542 +++ b/f Thu Jan 01 00:00:03 1970 +0000
543 @@ -1,1 +1,2 @@
543 @@ -1,1 +1,2 @@
544 f
544 f
545 +f
545 +f
546
546
547 == rev: 1, a->b f->g ==
547 == rev: 1, a->b f->g ==
548 diff -r 9161b9aeaf16 -r d89b0a12d229 b
548 diff -r 9161b9aeaf16 -r d89b0a12d229 b
549 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
549 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
550 +++ b/b Thu Jan 01 00:00:02 1970 +0000
550 +++ b/b Thu Jan 01 00:00:02 1970 +0000
551 @@ -0,0 +1,1 @@
551 @@ -0,0 +1,1 @@
552 +a
552 +a
553
553
554 == rev: 0, ==
554 == rev: 0, ==
555 diff -r 000000000000 -r 9161b9aeaf16 a
555 diff -r 000000000000 -r 9161b9aeaf16 a
556 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
556 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
557 +++ b/a Thu Jan 01 00:00:01 1970 +0000
557 +++ b/a Thu Jan 01 00:00:01 1970 +0000
558 @@ -0,0 +1,1 @@
558 @@ -0,0 +1,1 @@
559 +a
559 +a
560 diff -r 000000000000 -r 9161b9aeaf16 f
560 diff -r 000000000000 -r 9161b9aeaf16 f
561 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
561 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
562 +++ b/f Thu Jan 01 00:00:01 1970 +0000
562 +++ b/f Thu Jan 01 00:00:01 1970 +0000
563 @@ -0,0 +1,1 @@
563 @@ -0,0 +1,1 @@
564 +f
564 +f
565
565
566
566
567 log copies with --copies
567 log copies with --copies
568
568
569 $ hg log -vC --template '{rev} {file_copies}\n'
569 $ hg log -vC --template '{rev} {file_copies}\n'
570 4 e (dir/b)
570 4 e (dir/b)
571 3 b (a)g (f)
571 3 b (a)g (f)
572 2 dir/b (b)
572 2 dir/b (b)
573 1 b (a)g (f)
573 1 b (a)g (f)
574 0
574 0
575
575
576 log copies switch without --copies, with old filecopy template
576 log copies switch without --copies, with old filecopy template
577
577
578 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
578 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
579 4
579 4
580 3
580 3
581 2
581 2
582 1
582 1
583 0
583 0
584
584
585 log copies switch with --copies
585 log copies switch with --copies
586
586
587 $ hg log -vC --template '{rev} {file_copies_switch}\n'
587 $ hg log -vC --template '{rev} {file_copies_switch}\n'
588 4 e (dir/b)
588 4 e (dir/b)
589 3 b (a)g (f)
589 3 b (a)g (f)
590 2 dir/b (b)
590 2 dir/b (b)
591 1 b (a)g (f)
591 1 b (a)g (f)
592 0
592 0
593
593
594
594
595 log copies with hardcoded style and with --style=default
595 log copies with hardcoded style and with --style=default
596
596
597 $ hg log -vC -r4
597 $ hg log -vC -r4
598 changeset: 4:7e4639b4691b
598 changeset: 4:7e4639b4691b
599 tag: tip
599 tag: tip
600 user: test
600 user: test
601 date: Thu Jan 01 00:00:05 1970 +0000
601 date: Thu Jan 01 00:00:05 1970 +0000
602 files: dir/b e
602 files: dir/b e
603 copies: e (dir/b)
603 copies: e (dir/b)
604 description:
604 description:
605 e
605 e
606
606
607
607
608 $ hg log -vC -r4 --style=default
608 $ hg log -vC -r4 --style=default
609 changeset: 4:7e4639b4691b
609 changeset: 4:7e4639b4691b
610 tag: tip
610 tag: tip
611 user: test
611 user: test
612 date: Thu Jan 01 00:00:05 1970 +0000
612 date: Thu Jan 01 00:00:05 1970 +0000
613 files: dir/b e
613 files: dir/b e
614 copies: e (dir/b)
614 copies: e (dir/b)
615 description:
615 description:
616 e
616 e
617
617
618
618
619 $ hg log -vC -r4 -Tjson
619 $ hg log -vC -r4 -Tjson
620 [
620 [
621 {
621 {
622 "bookmarks": [],
622 "bookmarks": [],
623 "branch": "default",
623 "branch": "default",
624 "copies": {"e": "dir/b"},
624 "copies": {"e": "dir/b"},
625 "date": [5, 0],
625 "date": [5, 0],
626 "desc": "e",
626 "desc": "e",
627 "files": ["dir/b", "e"],
627 "files": ["dir/b", "e"],
628 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
628 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
629 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
629 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
630 "phase": "draft",
630 "phase": "draft",
631 "rev": 4,
631 "rev": 4,
632 "tags": ["tip"],
632 "tags": ["tip"],
633 "user": "test"
633 "user": "test"
634 }
634 }
635 ]
635 ]
636
636
637 log copies, non-linear manifest
637 log copies, non-linear manifest
638
638
639 $ hg up -C 3
639 $ hg up -C 3
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
641 $ hg mv dir/b e
641 $ hg mv dir/b e
642 $ echo foo > foo
642 $ echo foo > foo
643 $ hg ci -Ame2 -d '6 0'
643 $ hg ci -Ame2 -d '6 0'
644 adding foo
644 adding foo
645 created new head
645 created new head
646 $ hg log -v --template '{rev} {file_copies}\n' -r 5
646 $ hg log -v --template '{rev} {file_copies}\n' -r 5
647 5 e (dir/b)
647 5 e (dir/b)
648
648
649
649
650 log copies, execute bit set
650 log copies, execute bit set
651
651
652 #if execbit
652 #if execbit
653 $ chmod +x e
653 $ chmod +x e
654 $ hg ci -me3 -d '7 0'
654 $ hg ci -me3 -d '7 0'
655 $ hg log -v --template '{rev} {file_copies}\n' -r 6
655 $ hg log -v --template '{rev} {file_copies}\n' -r 6
656 6
656 6
657 #endif
657 #endif
658
658
659 log copies, empty set
659 log copies, empty set
660
660
661 $ hg log --copies -r '0 and not 0'
661 $ hg log --copies -r '0 and not 0'
662
662
663 log -p d
663 log -p d
664
664
665 $ hg log -pv d
665 $ hg log -pv d
666 changeset: 3:2ca5ba701980
666 changeset: 3:2ca5ba701980
667 user: test
667 user: test
668 date: Thu Jan 01 00:00:04 1970 +0000
668 date: Thu Jan 01 00:00:04 1970 +0000
669 files: a b d g
669 files: a b d g
670 description:
670 description:
671 d
671 d
672
672
673
673
674 diff -r f8954cd4dc1f -r 2ca5ba701980 d
674 diff -r f8954cd4dc1f -r 2ca5ba701980 d
675 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
675 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
676 +++ b/d Thu Jan 01 00:00:04 1970 +0000
676 +++ b/d Thu Jan 01 00:00:04 1970 +0000
677 @@ -0,0 +1,1 @@
677 @@ -0,0 +1,1 @@
678 +a
678 +a
679
679
680
680
681
681
682 log --removed file
682 log --removed file
683
683
684 $ hg log --removed -v a
684 $ hg log --removed -v a
685 changeset: 3:2ca5ba701980
685 changeset: 3:2ca5ba701980
686 user: test
686 user: test
687 date: Thu Jan 01 00:00:04 1970 +0000
687 date: Thu Jan 01 00:00:04 1970 +0000
688 files: a b d g
688 files: a b d g
689 description:
689 description:
690 d
690 d
691
691
692
692
693 changeset: 0:9161b9aeaf16
693 changeset: 0:9161b9aeaf16
694 user: test
694 user: test
695 date: Thu Jan 01 00:00:01 1970 +0000
695 date: Thu Jan 01 00:00:01 1970 +0000
696 files: a f
696 files: a f
697 description:
697 description:
698 a
698 a
699
699
700
700
701
701
702 log --removed revrange file
702 log --removed revrange file
703
703
704 $ hg log --removed -v -r0:2 a
704 $ hg log --removed -v -r0:2 a
705 changeset: 0:9161b9aeaf16
705 changeset: 0:9161b9aeaf16
706 user: test
706 user: test
707 date: Thu Jan 01 00:00:01 1970 +0000
707 date: Thu Jan 01 00:00:01 1970 +0000
708 files: a f
708 files: a f
709 description:
709 description:
710 a
710 a
711
711
712
712
713 $ cd ..
713 $ cd ..
714
714
715 log --follow tests
715 log --follow tests
716
716
717 $ hg init follow
717 $ hg init follow
718 $ cd follow
718 $ cd follow
719
719
720 $ echo base > base
720 $ echo base > base
721 $ hg ci -Ambase -d '1 0'
721 $ hg ci -Ambase -d '1 0'
722 adding base
722 adding base
723
723
724 $ echo r1 >> base
724 $ echo r1 >> base
725 $ hg ci -Amr1 -d '1 0'
725 $ hg ci -Amr1 -d '1 0'
726 $ echo r2 >> base
726 $ echo r2 >> base
727 $ hg ci -Amr2 -d '1 0'
727 $ hg ci -Amr2 -d '1 0'
728
728
729 $ hg up -C 1
729 $ hg up -C 1
730 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
730 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
731 $ echo b1 > b1
731 $ echo b1 > b1
732
732
733 log -r "follow('set:clean()')"
733 log -r "follow('set:clean()')"
734
734
735 $ hg log -r "follow('set:clean()')"
735 $ hg log -r "follow('set:clean()')"
736 changeset: 0:67e992f2c4f3
736 changeset: 0:67e992f2c4f3
737 user: test
737 user: test
738 date: Thu Jan 01 00:00:01 1970 +0000
738 date: Thu Jan 01 00:00:01 1970 +0000
739 summary: base
739 summary: base
740
740
741 changeset: 1:3d5bf5654eda
741 changeset: 1:3d5bf5654eda
742 user: test
742 user: test
743 date: Thu Jan 01 00:00:01 1970 +0000
743 date: Thu Jan 01 00:00:01 1970 +0000
744 summary: r1
744 summary: r1
745
745
746
746
747 $ hg ci -Amb1 -d '1 0'
747 $ hg ci -Amb1 -d '1 0'
748 adding b1
748 adding b1
749 created new head
749 created new head
750
750
751
751
752 log -f
752 log -f
753
753
754 $ hg log -f
754 $ hg log -f
755 changeset: 3:e62f78d544b4
755 changeset: 3:e62f78d544b4
756 tag: tip
756 tag: tip
757 parent: 1:3d5bf5654eda
757 parent: 1:3d5bf5654eda
758 user: test
758 user: test
759 date: Thu Jan 01 00:00:01 1970 +0000
759 date: Thu Jan 01 00:00:01 1970 +0000
760 summary: b1
760 summary: b1
761
761
762 changeset: 1:3d5bf5654eda
762 changeset: 1:3d5bf5654eda
763 user: test
763 user: test
764 date: Thu Jan 01 00:00:01 1970 +0000
764 date: Thu Jan 01 00:00:01 1970 +0000
765 summary: r1
765 summary: r1
766
766
767 changeset: 0:67e992f2c4f3
767 changeset: 0:67e992f2c4f3
768 user: test
768 user: test
769 date: Thu Jan 01 00:00:01 1970 +0000
769 date: Thu Jan 01 00:00:01 1970 +0000
770 summary: base
770 summary: base
771
771
772
772
773 log -r follow('glob:b*')
773 log -r follow('glob:b*')
774
774
775 $ hg log -r "follow('glob:b*')"
775 $ hg log -r "follow('glob:b*')"
776 changeset: 0:67e992f2c4f3
776 changeset: 0:67e992f2c4f3
777 user: test
777 user: test
778 date: Thu Jan 01 00:00:01 1970 +0000
778 date: Thu Jan 01 00:00:01 1970 +0000
779 summary: base
779 summary: base
780
780
781 changeset: 1:3d5bf5654eda
781 changeset: 1:3d5bf5654eda
782 user: test
782 user: test
783 date: Thu Jan 01 00:00:01 1970 +0000
783 date: Thu Jan 01 00:00:01 1970 +0000
784 summary: r1
784 summary: r1
785
785
786 changeset: 3:e62f78d544b4
786 changeset: 3:e62f78d544b4
787 tag: tip
787 tag: tip
788 parent: 1:3d5bf5654eda
788 parent: 1:3d5bf5654eda
789 user: test
789 user: test
790 date: Thu Jan 01 00:00:01 1970 +0000
790 date: Thu Jan 01 00:00:01 1970 +0000
791 summary: b1
791 summary: b1
792
792
793 log -f -r '1 + 4'
793 log -f -r '1 + 4'
794
794
795 $ hg up -C 0
795 $ hg up -C 0
796 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
797 $ echo b2 > b2
797 $ echo b2 > b2
798 $ hg ci -Amb2 -d '1 0'
798 $ hg ci -Amb2 -d '1 0'
799 adding b2
799 adding b2
800 created new head
800 created new head
801 $ hg log -f -r '1 + 4'
801 $ hg log -f -r '1 + 4'
802 changeset: 4:ddb82e70d1a1
802 changeset: 4:ddb82e70d1a1
803 tag: tip
803 tag: tip
804 parent: 0:67e992f2c4f3
804 parent: 0:67e992f2c4f3
805 user: test
805 user: test
806 date: Thu Jan 01 00:00:01 1970 +0000
806 date: Thu Jan 01 00:00:01 1970 +0000
807 summary: b2
807 summary: b2
808
808
809 changeset: 1:3d5bf5654eda
809 changeset: 1:3d5bf5654eda
810 user: test
810 user: test
811 date: Thu Jan 01 00:00:01 1970 +0000
811 date: Thu Jan 01 00:00:01 1970 +0000
812 summary: r1
812 summary: r1
813
813
814 changeset: 0:67e992f2c4f3
814 changeset: 0:67e992f2c4f3
815 user: test
815 user: test
816 date: Thu Jan 01 00:00:01 1970 +0000
816 date: Thu Jan 01 00:00:01 1970 +0000
817 summary: base
817 summary: base
818
818
819
819
820 log -fr with aliases: 'A' should be expanded, but 'reverse()' should have no
820 log -fr with aliases: 'A' should be expanded, but 'reverse()' should have no
821 effect
821 effect
822
822
823 $ hg log --config 'revsetalias.reverse(x)=x' --config 'revsetalias.A=1+4' -qfrA
823 $ hg log --config 'revsetalias.reverse(x)=x' --config 'revsetalias.A=1+4' -qfrA
824 4:ddb82e70d1a1
824 4:ddb82e70d1a1
825 1:3d5bf5654eda
825 1:3d5bf5654eda
826 0:67e992f2c4f3
826 0:67e992f2c4f3
827
827
828 log -r "follow('set:grep(b2)')"
828 log -r "follow('set:grep(b2)')"
829
829
830 $ hg log -r "follow('set:grep(b2)')"
830 $ hg log -r "follow('set:grep(b2)')"
831 changeset: 4:ddb82e70d1a1
831 changeset: 4:ddb82e70d1a1
832 tag: tip
832 tag: tip
833 parent: 0:67e992f2c4f3
833 parent: 0:67e992f2c4f3
834 user: test
834 user: test
835 date: Thu Jan 01 00:00:01 1970 +0000
835 date: Thu Jan 01 00:00:01 1970 +0000
836 summary: b2
836 summary: b2
837
837
838 log -r "follow('set:grep(b2)', 4)"
838 log -r "follow('set:grep(b2)', 4)"
839
839
840 $ hg up -qC 0
840 $ hg up -qC 0
841 $ hg log -r "follow('set:grep(b2)', 4)"
841 $ hg log -r "follow('set:grep(b2)', 4)"
842 changeset: 4:ddb82e70d1a1
842 changeset: 4:ddb82e70d1a1
843 tag: tip
843 tag: tip
844 parent: 0:67e992f2c4f3
844 parent: 0:67e992f2c4f3
845 user: test
845 user: test
846 date: Thu Jan 01 00:00:01 1970 +0000
846 date: Thu Jan 01 00:00:01 1970 +0000
847 summary: b2
847 summary: b2
848
848
849
849
850 follow files starting from multiple revisions:
850 follow files starting from multiple revisions:
851
851
852 $ hg log -T '{rev}: {files}\n' -r "follow('glob:b?', startrev=2+3+4)"
852 $ hg log -T '{rev}: {files}\n' -r "follow('glob:b?', startrev=2+3+4)"
853 3: b1
853 3: b1
854 4: b2
854 4: b2
855
855
856 follow files starting from empty revision:
856 follow files starting from empty revision:
857
857
858 $ hg log -T '{rev}: {files}\n' -r "follow('glob:*', startrev=.-.)"
858 $ hg log -T '{rev}: {files}\n' -r "follow('glob:*', startrev=.-.)"
859
859
860 follow starting from revisions:
860 follow starting from revisions:
861
861
862 $ hg log -Gq -r "follow(startrev=2+4)"
862 $ hg log -Gq -r "follow(startrev=2+4)"
863 o 4:ddb82e70d1a1
863 o 4:ddb82e70d1a1
864 |
864 |
865 | o 2:60c670bf5b30
865 | o 2:60c670bf5b30
866 | |
866 | |
867 | o 1:3d5bf5654eda
867 | o 1:3d5bf5654eda
868 |/
868 |/
869 @ 0:67e992f2c4f3
869 @ 0:67e992f2c4f3
870
870
871
871
872 follow the current revision:
872 follow the current revision:
873
873
874 $ hg log -Gq -r "follow()"
874 $ hg log -Gq -r "follow()"
875 @ 0:67e992f2c4f3
875 @ 0:67e992f2c4f3
876
876
877
877
878 $ hg up -qC 4
878 $ hg up -qC 4
879
879
880 log -f -r null
880 log -f -r null
881
881
882 $ hg log -f -r null
882 $ hg log -f -r null
883 changeset: -1:000000000000
883 changeset: -1:000000000000
884 user:
884 user:
885 date: Thu Jan 01 00:00:00 1970 +0000
885 date: Thu Jan 01 00:00:00 1970 +0000
886
886
887 $ hg log -f -r null -G
887 $ hg log -f -r null -G
888 o changeset: -1:000000000000
888 o changeset: -1:000000000000
889 user:
889 user:
890 date: Thu Jan 01 00:00:00 1970 +0000
890 date: Thu Jan 01 00:00:00 1970 +0000
891
891
892
892
893
893
894 log -f with null parent
894 log -f with null parent
895
895
896 $ hg up -C null
896 $ hg up -C null
897 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
897 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
898 $ hg log -f
898 $ hg log -f
899
899
900
900
901 log -r . with two parents
901 log -r . with two parents
902
902
903 $ hg up -C 3
903 $ hg up -C 3
904 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 $ hg merge tip
905 $ hg merge tip
906 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
906 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
907 (branch merge, don't forget to commit)
907 (branch merge, don't forget to commit)
908 $ hg log -r .
908 $ hg log -r .
909 changeset: 3:e62f78d544b4
909 changeset: 3:e62f78d544b4
910 parent: 1:3d5bf5654eda
910 parent: 1:3d5bf5654eda
911 user: test
911 user: test
912 date: Thu Jan 01 00:00:01 1970 +0000
912 date: Thu Jan 01 00:00:01 1970 +0000
913 summary: b1
913 summary: b1
914
914
915
915
916
916
917 log -r . with one parent
917 log -r . with one parent
918
918
919 $ hg ci -mm12 -d '1 0'
919 $ hg ci -mm12 -d '1 0'
920 $ hg log -r .
920 $ hg log -r .
921 changeset: 5:302e9dd6890d
921 changeset: 5:302e9dd6890d
922 tag: tip
922 tag: tip
923 parent: 3:e62f78d544b4
923 parent: 3:e62f78d544b4
924 parent: 4:ddb82e70d1a1
924 parent: 4:ddb82e70d1a1
925 user: test
925 user: test
926 date: Thu Jan 01 00:00:01 1970 +0000
926 date: Thu Jan 01 00:00:01 1970 +0000
927 summary: m12
927 summary: m12
928
928
929
929
930 $ echo postm >> b1
930 $ echo postm >> b1
931 $ hg ci -Amb1.1 -d'1 0'
931 $ hg ci -Amb1.1 -d'1 0'
932
932
933
933
934 log --follow-first
934 log --follow-first
935
935
936 $ hg log --follow-first
936 $ hg log --follow-first
937 changeset: 6:2404bbcab562
937 changeset: 6:2404bbcab562
938 tag: tip
938 tag: tip
939 user: test
939 user: test
940 date: Thu Jan 01 00:00:01 1970 +0000
940 date: Thu Jan 01 00:00:01 1970 +0000
941 summary: b1.1
941 summary: b1.1
942
942
943 changeset: 5:302e9dd6890d
943 changeset: 5:302e9dd6890d
944 parent: 3:e62f78d544b4
944 parent: 3:e62f78d544b4
945 parent: 4:ddb82e70d1a1
945 parent: 4:ddb82e70d1a1
946 user: test
946 user: test
947 date: Thu Jan 01 00:00:01 1970 +0000
947 date: Thu Jan 01 00:00:01 1970 +0000
948 summary: m12
948 summary: m12
949
949
950 changeset: 3:e62f78d544b4
950 changeset: 3:e62f78d544b4
951 parent: 1:3d5bf5654eda
951 parent: 1:3d5bf5654eda
952 user: test
952 user: test
953 date: Thu Jan 01 00:00:01 1970 +0000
953 date: Thu Jan 01 00:00:01 1970 +0000
954 summary: b1
954 summary: b1
955
955
956 changeset: 1:3d5bf5654eda
956 changeset: 1:3d5bf5654eda
957 user: test
957 user: test
958 date: Thu Jan 01 00:00:01 1970 +0000
958 date: Thu Jan 01 00:00:01 1970 +0000
959 summary: r1
959 summary: r1
960
960
961 changeset: 0:67e992f2c4f3
961 changeset: 0:67e992f2c4f3
962 user: test
962 user: test
963 date: Thu Jan 01 00:00:01 1970 +0000
963 date: Thu Jan 01 00:00:01 1970 +0000
964 summary: base
964 summary: base
965
965
966
966
967
967
968 log -P 2
968 log -P 2
969
969
970 $ hg log -P 2
970 $ hg log -P 2
971 changeset: 6:2404bbcab562
971 changeset: 6:2404bbcab562
972 tag: tip
972 tag: tip
973 user: test
973 user: test
974 date: Thu Jan 01 00:00:01 1970 +0000
974 date: Thu Jan 01 00:00:01 1970 +0000
975 summary: b1.1
975 summary: b1.1
976
976
977 changeset: 5:302e9dd6890d
977 changeset: 5:302e9dd6890d
978 parent: 3:e62f78d544b4
978 parent: 3:e62f78d544b4
979 parent: 4:ddb82e70d1a1
979 parent: 4:ddb82e70d1a1
980 user: test
980 user: test
981 date: Thu Jan 01 00:00:01 1970 +0000
981 date: Thu Jan 01 00:00:01 1970 +0000
982 summary: m12
982 summary: m12
983
983
984 changeset: 4:ddb82e70d1a1
984 changeset: 4:ddb82e70d1a1
985 parent: 0:67e992f2c4f3
985 parent: 0:67e992f2c4f3
986 user: test
986 user: test
987 date: Thu Jan 01 00:00:01 1970 +0000
987 date: Thu Jan 01 00:00:01 1970 +0000
988 summary: b2
988 summary: b2
989
989
990 changeset: 3:e62f78d544b4
990 changeset: 3:e62f78d544b4
991 parent: 1:3d5bf5654eda
991 parent: 1:3d5bf5654eda
992 user: test
992 user: test
993 date: Thu Jan 01 00:00:01 1970 +0000
993 date: Thu Jan 01 00:00:01 1970 +0000
994 summary: b1
994 summary: b1
995
995
996
996
997
997
998 log -r tip -p --git
998 log -r tip -p --git
999
999
1000 $ hg log -r tip -p --git
1000 $ hg log -r tip -p --git
1001 changeset: 6:2404bbcab562
1001 changeset: 6:2404bbcab562
1002 tag: tip
1002 tag: tip
1003 user: test
1003 user: test
1004 date: Thu Jan 01 00:00:01 1970 +0000
1004 date: Thu Jan 01 00:00:01 1970 +0000
1005 summary: b1.1
1005 summary: b1.1
1006
1006
1007 diff --git a/b1 b/b1
1007 diff --git a/b1 b/b1
1008 --- a/b1
1008 --- a/b1
1009 +++ b/b1
1009 +++ b/b1
1010 @@ -1,1 +1,2 @@
1010 @@ -1,1 +1,2 @@
1011 b1
1011 b1
1012 +postm
1012 +postm
1013
1013
1014
1014
1015
1015
1016 log -r ""
1016 log -r ""
1017
1017
1018 $ hg log -r ''
1018 $ hg log -r ''
1019 hg: parse error: empty query
1019 hg: parse error: empty query
1020 [255]
1020 [255]
1021
1021
1022 log -r <some unknown node id>
1022 log -r <some unknown node id>
1023
1023
1024 $ hg log -r 1000000000000000000000000000000000000000
1024 $ hg log -r 1000000000000000000000000000000000000000
1025 abort: unknown revision '1000000000000000000000000000000000000000'!
1025 abort: unknown revision '1000000000000000000000000000000000000000'!
1026 [255]
1026 [255]
1027
1027
1028 log -k r1
1028 log -k r1
1029
1029
1030 $ hg log -k r1
1030 $ hg log -k r1
1031 changeset: 1:3d5bf5654eda
1031 changeset: 1:3d5bf5654eda
1032 user: test
1032 user: test
1033 date: Thu Jan 01 00:00:01 1970 +0000
1033 date: Thu Jan 01 00:00:01 1970 +0000
1034 summary: r1
1034 summary: r1
1035
1035
1036 log -p -l2 --color=always
1036 log -p -l2 --color=always
1037
1037
1038 $ hg --config extensions.color= --config color.mode=ansi \
1038 $ hg --config extensions.color= --config color.mode=ansi \
1039 > log -p -l2 --color=always
1039 > log -p -l2 --color=always
1040 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
1040 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
1041 tag: tip
1041 tag: tip
1042 user: test
1042 user: test
1043 date: Thu Jan 01 00:00:01 1970 +0000
1043 date: Thu Jan 01 00:00:01 1970 +0000
1044 summary: b1.1
1044 summary: b1.1
1045
1045
1046 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
1046 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
1047 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1047 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1048 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1048 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1049 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
1049 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
1050 b1
1050 b1
1051 \x1b[0;32m+postm\x1b[0m (esc)
1051 \x1b[0;32m+postm\x1b[0m (esc)
1052
1052
1053 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
1053 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
1054 parent: 3:e62f78d544b4
1054 parent: 3:e62f78d544b4
1055 parent: 4:ddb82e70d1a1
1055 parent: 4:ddb82e70d1a1
1056 user: test
1056 user: test
1057 date: Thu Jan 01 00:00:01 1970 +0000
1057 date: Thu Jan 01 00:00:01 1970 +0000
1058 summary: m12
1058 summary: m12
1059
1059
1060 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
1060 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
1061 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
1061 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
1062 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1062 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1063 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
1063 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
1064 \x1b[0;32m+b2\x1b[0m (esc)
1064 \x1b[0;32m+b2\x1b[0m (esc)
1065
1065
1066
1066
1067
1067
1068 log -r tip --stat
1068 log -r tip --stat
1069
1069
1070 $ hg log -r tip --stat
1070 $ hg log -r tip --stat
1071 changeset: 6:2404bbcab562
1071 changeset: 6:2404bbcab562
1072 tag: tip
1072 tag: tip
1073 user: test
1073 user: test
1074 date: Thu Jan 01 00:00:01 1970 +0000
1074 date: Thu Jan 01 00:00:01 1970 +0000
1075 summary: b1.1
1075 summary: b1.1
1076
1076
1077 b1 | 1 +
1077 b1 | 1 +
1078 1 files changed, 1 insertions(+), 0 deletions(-)
1078 1 files changed, 1 insertions(+), 0 deletions(-)
1079
1079
1080
1080
1081 $ cd ..
1081 $ cd ..
1082
1082
1083 log --follow --patch FILE in repository where linkrev isn't trustworthy
1083 log --follow --patch FILE in repository where linkrev isn't trustworthy
1084 (issue5376, issue6124)
1084 (issue5376, issue6124)
1085
1085
1086 $ hg init follow-dup
1086 $ hg init follow-dup
1087 $ cd follow-dup
1087 $ cd follow-dup
1088 $ cat <<EOF >> .hg/hgrc
1088 $ cat <<EOF >> .hg/hgrc
1089 > [ui]
1089 > [ui]
1090 > logtemplate = '=== {rev}: {desc}\n'
1090 > logtemplate = '=== {rev}: {desc}\n'
1091 > [diff]
1091 > [diff]
1092 > nodates = True
1092 > nodates = True
1093 > EOF
1093 > EOF
1094 $ echo 0 >> a
1094 $ echo 0 >> a
1095 $ hg ci -qAm 'a0'
1095 $ hg ci -qAm 'a0'
1096 $ echo 1 >> a
1096 $ echo 1 >> a
1097 $ hg ci -m 'a1'
1097 $ hg ci -m 'a1'
1098 $ hg up -q 0
1098 $ hg up -q 0
1099 $ echo 1 >> a
1099 $ echo 1 >> a
1100 $ touch b
1100 $ touch b
1101 $ hg ci -qAm 'a1 with b'
1101 $ hg ci -qAm 'a1 with b'
1102 $ echo 3 >> a
1102 $ echo 3 >> a
1103 $ hg ci -m 'a3'
1103 $ hg ci -m 'a3'
1104
1104
1105 fctx.rev() == 2, but fctx.linkrev() == 1
1105 fctx.rev() == 2, but fctx.linkrev() == 1
1106
1106
1107 $ hg log -pf a
1107 $ hg log -pf a
1108 === 3: a3
1108 === 3: a3
1109 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1109 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1110 --- a/a
1110 --- a/a
1111 +++ b/a
1111 +++ b/a
1112 @@ -1,2 +1,3 @@
1112 @@ -1,2 +1,3 @@
1113 0
1113 0
1114 1
1114 1
1115 +3
1115 +3
1116
1116
1117 === 2: a1 with b
1117 === 2: a1 with b
1118 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1118 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1119 --- a/a
1119 --- a/a
1120 +++ b/a
1120 +++ b/a
1121 @@ -1,1 +1,2 @@
1121 @@ -1,1 +1,2 @@
1122 0
1122 0
1123 +1
1123 +1
1124
1124
1125 === 0: a0
1125 === 0: a0
1126 diff -r 000000000000 -r 49b5e81287e2 a
1126 diff -r 000000000000 -r 49b5e81287e2 a
1127 --- /dev/null
1127 --- /dev/null
1128 +++ b/a
1128 +++ b/a
1129 @@ -0,0 +1,1 @@
1129 @@ -0,0 +1,1 @@
1130 +0
1130 +0
1131
1131
1132 $ hg log -pr . a
1132 $ hg log -pr . a
1133 === 3: a3
1133 === 3: a3
1134 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1134 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1135 --- a/a
1135 --- a/a
1136 +++ b/a
1136 +++ b/a
1137 @@ -1,2 +1,3 @@
1137 @@ -1,2 +1,3 @@
1138 0
1138 0
1139 1
1139 1
1140 +3
1140 +3
1141
1141
1142
1142
1143 fctx.introrev() == 2, but fctx.linkrev() == 1
1143 fctx.introrev() == 2, but fctx.linkrev() == 1
1144
1144
1145 $ hg up -q 2
1145 $ hg up -q 2
1146 $ hg log -pf a
1146 $ hg log -pf a
1147 === 2: a1 with b
1147 === 2: a1 with b
1148 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1148 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1149 --- a/a
1149 --- a/a
1150 +++ b/a
1150 +++ b/a
1151 @@ -1,1 +1,2 @@
1151 @@ -1,1 +1,2 @@
1152 0
1152 0
1153 +1
1153 +1
1154
1154
1155 === 0: a0
1155 === 0: a0
1156 diff -r 000000000000 -r 49b5e81287e2 a
1156 diff -r 000000000000 -r 49b5e81287e2 a
1157 --- /dev/null
1157 --- /dev/null
1158 +++ b/a
1158 +++ b/a
1159 @@ -0,0 +1,1 @@
1159 @@ -0,0 +1,1 @@
1160 +0
1160 +0
1161
1161
1162
1162
1163 BROKEN: should show the same diff as for rev 2 above
1163 BROKEN: should show the same diff as for rev 2 above
1164 $ hg log -pr . a
1164 $ hg log -pr . a
1165
1165
1166 $ cd ..
1166 $ cd ..
1167
1167
1168 Multiple copy sources of a file:
1168 Multiple copy sources of a file:
1169
1169
1170 $ hg init follow-multi
1170 $ hg init follow-multi
1171 $ cd follow-multi
1171 $ cd follow-multi
1172 $ echo 0 >> a
1172 $ echo 0 >> a
1173 $ hg ci -qAm 'a'
1173 $ hg ci -qAm 'a'
1174 $ hg cp a b
1174 $ hg cp a b
1175 $ hg ci -m 'a->b'
1175 $ hg ci -m 'a->b'
1176 $ echo 2 >> a
1176 $ echo 2 >> a
1177 $ hg ci -m 'a'
1177 $ hg ci -m 'a'
1178 $ echo 3 >> b
1178 $ echo 3 >> b
1179 $ hg ci -m 'b'
1179 $ hg ci -m 'b'
1180 $ echo 4 >> a
1180 $ echo 4 >> a
1181 $ echo 4 >> b
1181 $ echo 4 >> b
1182 $ hg ci -m 'a,b'
1182 $ hg ci -m 'a,b'
1183 $ echo 5 >> a
1183 $ echo 5 >> a
1184 $ hg ci -m 'a0'
1184 $ hg ci -m 'a0'
1185 $ echo 6 >> b
1185 $ echo 6 >> b
1186 $ hg ci -m 'b0'
1186 $ hg ci -m 'b0'
1187 $ hg up -q 4
1187 $ hg up -q 4
1188 $ echo 7 >> b
1188 $ echo 7 >> b
1189 $ hg ci -m 'b1'
1189 $ hg ci -m 'b1'
1190 created new head
1190 created new head
1191 $ echo 8 >> a
1191 $ echo 8 >> a
1192 $ hg ci -m 'a1'
1192 $ hg ci -m 'a1'
1193 $ hg rm a
1193 $ hg rm a
1194 $ hg mv b a
1194 $ hg mv b a
1195 $ hg ci -m 'b1->a1'
1195 $ hg ci -m 'b1->a1'
1196 $ hg merge -qt :local
1196 $ hg merge -qt :local
1197 $ hg ci -m '(a0,b1->a1)->a'
1197 $ hg ci -m '(a0,b1->a1)->a'
1198
1198
1199 $ hg log -GT '{rev}: {desc}\n'
1199 $ hg log -GT '{rev}: {desc}\n'
1200 @ 10: (a0,b1->a1)->a
1200 @ 10: (a0,b1->a1)->a
1201 |\
1201 |\
1202 | o 9: b1->a1
1202 | o 9: b1->a1
1203 | |
1203 | |
1204 | o 8: a1
1204 | o 8: a1
1205 | |
1205 | |
1206 | o 7: b1
1206 | o 7: b1
1207 | |
1207 | |
1208 o | 6: b0
1208 o | 6: b0
1209 | |
1209 | |
1210 o | 5: a0
1210 o | 5: a0
1211 |/
1211 |/
1212 o 4: a,b
1212 o 4: a,b
1213 |
1213 |
1214 o 3: b
1214 o 3: b
1215 |
1215 |
1216 o 2: a
1216 o 2: a
1217 |
1217 |
1218 o 1: a->b
1218 o 1: a->b
1219 |
1219 |
1220 o 0: a
1220 o 0: a
1221
1221
1222
1222
1223 since file 'a' has multiple copy sources at the revision 4, ancestors can't
1223 since file 'a' has multiple copy sources at the revision 4, ancestors can't
1224 be indexed solely by fctx.linkrev().
1224 be indexed solely by fctx.linkrev().
1225
1225
1226 $ hg log -T '{rev}: {desc}\n' -f a
1226 $ hg log -T '{rev}: {desc}\n' -f a
1227 10: (a0,b1->a1)->a
1227 10: (a0,b1->a1)->a
1228 9: b1->a1
1228 9: b1->a1
1229 7: b1
1229 7: b1
1230 5: a0
1230 5: a0
1231 4: a,b
1231 4: a,b
1232 3: b
1232 3: b
1233 2: a
1233 2: a
1234 1: a->b
1234 1: a->b
1235 0: a
1235 0: a
1236
1236
1237 $ cd ..
1237 $ cd ..
1238
1238
1239 Test that log should respect the order of -rREV even if multiple OR conditions
1239 Test that log should respect the order of -rREV even if multiple OR conditions
1240 are specified (issue5100):
1240 are specified (issue5100):
1241
1241
1242 $ hg init revorder
1242 $ hg init revorder
1243 $ cd revorder
1243 $ cd revorder
1244
1244
1245 $ hg branch -q b0
1245 $ hg branch -q b0
1246 $ echo 0 >> f0
1246 $ echo 0 >> f0
1247 $ hg ci -qAm k0 -u u0
1247 $ hg ci -qAm k0 -u u0
1248 $ hg branch -q b1
1248 $ hg branch -q b1
1249 $ echo 1 >> f1
1249 $ echo 1 >> f1
1250 $ hg ci -qAm k1 -u u1
1250 $ hg ci -qAm k1 -u u1
1251 $ hg branch -q b2
1251 $ hg branch -q b2
1252 $ echo 2 >> f2
1252 $ echo 2 >> f2
1253 $ hg ci -qAm k2 -u u2
1253 $ hg ci -qAm k2 -u u2
1254
1254
1255 $ hg update -q b2
1255 $ hg update -q b2
1256 $ echo 3 >> f2
1256 $ echo 3 >> f2
1257 $ hg ci -qAm k2 -u u2
1257 $ hg ci -qAm k2 -u u2
1258 $ hg update -q b1
1258 $ hg update -q b1
1259 $ echo 4 >> f1
1259 $ echo 4 >> f1
1260 $ hg ci -qAm k1 -u u1
1260 $ hg ci -qAm k1 -u u1
1261 $ hg update -q b0
1261 $ hg update -q b0
1262 $ echo 5 >> f0
1262 $ echo 5 >> f0
1263 $ hg ci -qAm k0 -u u0
1263 $ hg ci -qAm k0 -u u0
1264
1264
1265 summary of revisions:
1265 summary of revisions:
1266
1266
1267 $ hg log -G -T '{rev} {branch} {author} {desc} {files}\n'
1267 $ hg log -G -T '{rev} {branch} {author} {desc} {files}\n'
1268 @ 5 b0 u0 k0 f0
1268 @ 5 b0 u0 k0 f0
1269 |
1269 |
1270 | o 4 b1 u1 k1 f1
1270 | o 4 b1 u1 k1 f1
1271 | |
1271 | |
1272 | | o 3 b2 u2 k2 f2
1272 | | o 3 b2 u2 k2 f2
1273 | | |
1273 | | |
1274 | | o 2 b2 u2 k2 f2
1274 | | o 2 b2 u2 k2 f2
1275 | |/
1275 | |/
1276 | o 1 b1 u1 k1 f1
1276 | o 1 b1 u1 k1 f1
1277 |/
1277 |/
1278 o 0 b0 u0 k0 f0
1278 o 0 b0 u0 k0 f0
1279
1279
1280
1280
1281 log -b BRANCH in ascending order:
1281 log -b BRANCH in ascending order:
1282
1282
1283 $ hg log -r0:tip -T '{rev} {branch}\n' -b b0 -b b1
1283 $ hg log -r0:tip -T '{rev} {branch}\n' -b b0 -b b1
1284 0 b0
1284 0 b0
1285 1 b1
1285 1 b1
1286 4 b1
1286 4 b1
1287 5 b0
1287 5 b0
1288 $ hg log -r0:tip -T '{rev} {branch}\n' -b b1 -b b0
1288 $ hg log -r0:tip -T '{rev} {branch}\n' -b b1 -b b0
1289 0 b0
1289 0 b0
1290 1 b1
1290 1 b1
1291 4 b1
1291 4 b1
1292 5 b0
1292 5 b0
1293
1293
1294 log --only-branch BRANCH in descending order:
1294 log --only-branch BRANCH in descending order:
1295
1295
1296 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b1 --only-branch b2
1296 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b1 --only-branch b2
1297 4 b1
1297 4 b1
1298 3 b2
1298 3 b2
1299 2 b2
1299 2 b2
1300 1 b1
1300 1 b1
1301 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b2 --only-branch b1
1301 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b2 --only-branch b1
1302 4 b1
1302 4 b1
1303 3 b2
1303 3 b2
1304 2 b2
1304 2 b2
1305 1 b1
1305 1 b1
1306
1306
1307 log -u USER in ascending order, against compound set:
1307 log -u USER in ascending order, against compound set:
1308
1308
1309 $ hg log -r'::head()' -T '{rev} {author}\n' -u u0 -u u2
1309 $ hg log -r'::head()' -T '{rev} {author}\n' -u u0 -u u2
1310 0 u0
1310 0 u0
1311 2 u2
1311 2 u2
1312 3 u2
1312 3 u2
1313 5 u0
1313 5 u0
1314 $ hg log -r'::head()' -T '{rev} {author}\n' -u u2 -u u0
1314 $ hg log -r'::head()' -T '{rev} {author}\n' -u u2 -u u0
1315 0 u0
1315 0 u0
1316 2 u2
1316 2 u2
1317 3 u2
1317 3 u2
1318 5 u0
1318 5 u0
1319
1319
1320 log -k TEXT in descending order, against compound set:
1320 log -k TEXT in descending order, against compound set:
1321
1321
1322 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k0 -k k1 -k k2
1322 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k0 -k k1 -k k2
1323 5 k0
1323 5 k0
1324 3 k2
1324 3 k2
1325 2 k2
1325 2 k2
1326 1 k1
1326 1 k1
1327 0 k0
1327 0 k0
1328 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k2 -k k1 -k k0
1328 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k2 -k k1 -k k0
1329 5 k0
1329 5 k0
1330 3 k2
1330 3 k2
1331 2 k2
1331 2 k2
1332 1 k1
1332 1 k1
1333 0 k0
1333 0 k0
1334
1334
1335 log FILE in ascending order, against dagrange:
1335 log FILE in ascending order, against dagrange:
1336
1336
1337 $ hg log -r1:: -T '{rev} {files}\n' f1 f2
1337 $ hg log -r1:: -T '{rev} {files}\n' f1 f2
1338 1 f1
1338 1 f1
1339 2 f2
1339 2 f2
1340 3 f2
1340 3 f2
1341 4 f1
1341 4 f1
1342 $ hg log -r1:: -T '{rev} {files}\n' f2 f1
1342 $ hg log -r1:: -T '{rev} {files}\n' f2 f1
1343 1 f1
1343 1 f1
1344 2 f2
1344 2 f2
1345 3 f2
1345 3 f2
1346 4 f1
1346 4 f1
1347
1347
1348 $ cd ..
1348 $ cd ..
1349
1349
1350 User
1350 User
1351
1351
1352 $ hg init usertest
1352 $ hg init usertest
1353 $ cd usertest
1353 $ cd usertest
1354
1354
1355 $ echo a > a
1355 $ echo a > a
1356 $ hg ci -A -m "a" -u "User One <user1@example.org>"
1356 $ hg ci -A -m "a" -u "User One <user1@example.org>"
1357 adding a
1357 adding a
1358 $ echo b > b
1358 $ echo b > b
1359 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
1359 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
1360 adding b
1360 adding b
1361
1361
1362 $ hg log -u "User One <user1@example.org>"
1362 $ hg log -u "User One <user1@example.org>"
1363 changeset: 0:29a4c94f1924
1363 changeset: 0:29a4c94f1924
1364 user: User One <user1@example.org>
1364 user: User One <user1@example.org>
1365 date: Thu Jan 01 00:00:00 1970 +0000
1365 date: Thu Jan 01 00:00:00 1970 +0000
1366 summary: a
1366 summary: a
1367
1367
1368 $ hg log -u "user1" -u "user2"
1368 $ hg log -u "user1" -u "user2"
1369 changeset: 1:e834b5e69c0e
1369 changeset: 1:e834b5e69c0e
1370 tag: tip
1370 tag: tip
1371 user: User Two <user2@example.org>
1371 user: User Two <user2@example.org>
1372 date: Thu Jan 01 00:00:00 1970 +0000
1372 date: Thu Jan 01 00:00:00 1970 +0000
1373 summary: b
1373 summary: b
1374
1374
1375 changeset: 0:29a4c94f1924
1375 changeset: 0:29a4c94f1924
1376 user: User One <user1@example.org>
1376 user: User One <user1@example.org>
1377 date: Thu Jan 01 00:00:00 1970 +0000
1377 date: Thu Jan 01 00:00:00 1970 +0000
1378 summary: a
1378 summary: a
1379
1379
1380 $ hg log -u "user3"
1380 $ hg log -u "user3"
1381
1381
1382 "-u USER" shouldn't be overridden by "user(USER)" alias
1382 "-u USER" shouldn't be overridden by "user(USER)" alias
1383
1383
1384 $ hg log --config 'revsetalias.user(x)=branch(x)' -u default
1384 $ hg log --config 'revsetalias.user(x)=branch(x)' -u default
1385 $ hg log --config 'revsetalias.user(x)=branch(x)' -u user1
1385 $ hg log --config 'revsetalias.user(x)=branch(x)' -u user1
1386 changeset: 0:29a4c94f1924
1386 changeset: 0:29a4c94f1924
1387 user: User One <user1@example.org>
1387 user: User One <user1@example.org>
1388 date: Thu Jan 01 00:00:00 1970 +0000
1388 date: Thu Jan 01 00:00:00 1970 +0000
1389 summary: a
1389 summary: a
1390
1390
1391
1391
1392 $ cd ..
1392 $ cd ..
1393
1393
1394 $ hg init branches
1394 $ hg init branches
1395 $ cd branches
1395 $ cd branches
1396
1396
1397 $ echo a > a
1397 $ echo a > a
1398 $ hg ci -A -m "commit on default"
1398 $ hg ci -A -m "commit on default"
1399 adding a
1399 adding a
1400 $ hg branch test
1400 $ hg branch test
1401 marked working directory as branch test
1401 marked working directory as branch test
1402 (branches are permanent and global, did you want a bookmark?)
1402 (branches are permanent and global, did you want a bookmark?)
1403 $ echo b > b
1403 $ echo b > b
1404 $ hg ci -A -m "commit on test"
1404 $ hg ci -A -m "commit on test"
1405 adding b
1405 adding b
1406
1406
1407 $ hg up default
1407 $ hg up default
1408 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1408 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1409 $ echo c > c
1409 $ echo c > c
1410 $ hg ci -A -m "commit on default"
1410 $ hg ci -A -m "commit on default"
1411 adding c
1411 adding c
1412 $ hg up test
1412 $ hg up test
1413 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1413 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1414 $ echo c > c
1414 $ echo c > c
1415 $ hg ci -A -m "commit on test"
1415 $ hg ci -A -m "commit on test"
1416 adding c
1416 adding c
1417
1417
1418
1418
1419 log -b default
1419 log -b default
1420
1420
1421 $ hg log -b default
1421 $ hg log -b default
1422 changeset: 2:c3a4f03cc9a7
1422 changeset: 2:c3a4f03cc9a7
1423 parent: 0:24427303d56f
1423 parent: 0:24427303d56f
1424 user: test
1424 user: test
1425 date: Thu Jan 01 00:00:00 1970 +0000
1425 date: Thu Jan 01 00:00:00 1970 +0000
1426 summary: commit on default
1426 summary: commit on default
1427
1427
1428 changeset: 0:24427303d56f
1428 changeset: 0:24427303d56f
1429 user: test
1429 user: test
1430 date: Thu Jan 01 00:00:00 1970 +0000
1430 date: Thu Jan 01 00:00:00 1970 +0000
1431 summary: commit on default
1431 summary: commit on default
1432
1432
1433
1433
1434
1434
1435 log -b test
1435 log -b test
1436
1436
1437 $ hg log -b test
1437 $ hg log -b test
1438 changeset: 3:f5d8de11c2e2
1438 changeset: 3:f5d8de11c2e2
1439 branch: test
1439 branch: test
1440 tag: tip
1440 tag: tip
1441 parent: 1:d32277701ccb
1441 parent: 1:d32277701ccb
1442 user: test
1442 user: test
1443 date: Thu Jan 01 00:00:00 1970 +0000
1443 date: Thu Jan 01 00:00:00 1970 +0000
1444 summary: commit on test
1444 summary: commit on test
1445
1445
1446 changeset: 1:d32277701ccb
1446 changeset: 1:d32277701ccb
1447 branch: test
1447 branch: test
1448 user: test
1448 user: test
1449 date: Thu Jan 01 00:00:00 1970 +0000
1449 date: Thu Jan 01 00:00:00 1970 +0000
1450 summary: commit on test
1450 summary: commit on test
1451
1451
1452
1452
1453
1453
1454 log -b dummy
1454 log -b dummy
1455
1455
1456 $ hg log -b dummy
1456 $ hg log -b dummy
1457 abort: unknown revision 'dummy'!
1457 abort: unknown revision 'dummy'!
1458 [255]
1458 [255]
1459
1459
1460
1460
1461 log -b .
1461 log -b .
1462
1462
1463 $ hg log -b .
1463 $ hg log -b .
1464 changeset: 3:f5d8de11c2e2
1464 changeset: 3:f5d8de11c2e2
1465 branch: test
1465 branch: test
1466 tag: tip
1466 tag: tip
1467 parent: 1:d32277701ccb
1467 parent: 1:d32277701ccb
1468 user: test
1468 user: test
1469 date: Thu Jan 01 00:00:00 1970 +0000
1469 date: Thu Jan 01 00:00:00 1970 +0000
1470 summary: commit on test
1470 summary: commit on test
1471
1471
1472 changeset: 1:d32277701ccb
1472 changeset: 1:d32277701ccb
1473 branch: test
1473 branch: test
1474 user: test
1474 user: test
1475 date: Thu Jan 01 00:00:00 1970 +0000
1475 date: Thu Jan 01 00:00:00 1970 +0000
1476 summary: commit on test
1476 summary: commit on test
1477
1477
1478
1478
1479
1479
1480 log -b default -b test
1480 log -b default -b test
1481
1481
1482 $ hg log -b default -b test
1482 $ hg log -b default -b test
1483 changeset: 3:f5d8de11c2e2
1483 changeset: 3:f5d8de11c2e2
1484 branch: test
1484 branch: test
1485 tag: tip
1485 tag: tip
1486 parent: 1:d32277701ccb
1486 parent: 1:d32277701ccb
1487 user: test
1487 user: test
1488 date: Thu Jan 01 00:00:00 1970 +0000
1488 date: Thu Jan 01 00:00:00 1970 +0000
1489 summary: commit on test
1489 summary: commit on test
1490
1490
1491 changeset: 2:c3a4f03cc9a7
1491 changeset: 2:c3a4f03cc9a7
1492 parent: 0:24427303d56f
1492 parent: 0:24427303d56f
1493 user: test
1493 user: test
1494 date: Thu Jan 01 00:00:00 1970 +0000
1494 date: Thu Jan 01 00:00:00 1970 +0000
1495 summary: commit on default
1495 summary: commit on default
1496
1496
1497 changeset: 1:d32277701ccb
1497 changeset: 1:d32277701ccb
1498 branch: test
1498 branch: test
1499 user: test
1499 user: test
1500 date: Thu Jan 01 00:00:00 1970 +0000
1500 date: Thu Jan 01 00:00:00 1970 +0000
1501 summary: commit on test
1501 summary: commit on test
1502
1502
1503 changeset: 0:24427303d56f
1503 changeset: 0:24427303d56f
1504 user: test
1504 user: test
1505 date: Thu Jan 01 00:00:00 1970 +0000
1505 date: Thu Jan 01 00:00:00 1970 +0000
1506 summary: commit on default
1506 summary: commit on default
1507
1507
1508
1508
1509
1509
1510 log -b default -b .
1510 log -b default -b .
1511
1511
1512 $ hg log -b default -b .
1512 $ hg log -b default -b .
1513 changeset: 3:f5d8de11c2e2
1513 changeset: 3:f5d8de11c2e2
1514 branch: test
1514 branch: test
1515 tag: tip
1515 tag: tip
1516 parent: 1:d32277701ccb
1516 parent: 1:d32277701ccb
1517 user: test
1517 user: test
1518 date: Thu Jan 01 00:00:00 1970 +0000
1518 date: Thu Jan 01 00:00:00 1970 +0000
1519 summary: commit on test
1519 summary: commit on test
1520
1520
1521 changeset: 2:c3a4f03cc9a7
1521 changeset: 2:c3a4f03cc9a7
1522 parent: 0:24427303d56f
1522 parent: 0:24427303d56f
1523 user: test
1523 user: test
1524 date: Thu Jan 01 00:00:00 1970 +0000
1524 date: Thu Jan 01 00:00:00 1970 +0000
1525 summary: commit on default
1525 summary: commit on default
1526
1526
1527 changeset: 1:d32277701ccb
1527 changeset: 1:d32277701ccb
1528 branch: test
1528 branch: test
1529 user: test
1529 user: test
1530 date: Thu Jan 01 00:00:00 1970 +0000
1530 date: Thu Jan 01 00:00:00 1970 +0000
1531 summary: commit on test
1531 summary: commit on test
1532
1532
1533 changeset: 0:24427303d56f
1533 changeset: 0:24427303d56f
1534 user: test
1534 user: test
1535 date: Thu Jan 01 00:00:00 1970 +0000
1535 date: Thu Jan 01 00:00:00 1970 +0000
1536 summary: commit on default
1536 summary: commit on default
1537
1537
1538
1538
1539
1539
1540 log -b . -b test
1540 log -b . -b test
1541
1541
1542 $ hg log -b . -b test
1542 $ hg log -b . -b test
1543 changeset: 3:f5d8de11c2e2
1543 changeset: 3:f5d8de11c2e2
1544 branch: test
1544 branch: test
1545 tag: tip
1545 tag: tip
1546 parent: 1:d32277701ccb
1546 parent: 1:d32277701ccb
1547 user: test
1547 user: test
1548 date: Thu Jan 01 00:00:00 1970 +0000
1548 date: Thu Jan 01 00:00:00 1970 +0000
1549 summary: commit on test
1549 summary: commit on test
1550
1550
1551 changeset: 1:d32277701ccb
1551 changeset: 1:d32277701ccb
1552 branch: test
1552 branch: test
1553 user: test
1553 user: test
1554 date: Thu Jan 01 00:00:00 1970 +0000
1554 date: Thu Jan 01 00:00:00 1970 +0000
1555 summary: commit on test
1555 summary: commit on test
1556
1556
1557
1557
1558
1558
1559 log -b 2
1559 log -b 2
1560
1560
1561 $ hg log -b 2
1561 $ hg log -b 2
1562 changeset: 2:c3a4f03cc9a7
1562 changeset: 2:c3a4f03cc9a7
1563 parent: 0:24427303d56f
1563 parent: 0:24427303d56f
1564 user: test
1564 user: test
1565 date: Thu Jan 01 00:00:00 1970 +0000
1565 date: Thu Jan 01 00:00:00 1970 +0000
1566 summary: commit on default
1566 summary: commit on default
1567
1567
1568 changeset: 0:24427303d56f
1568 changeset: 0:24427303d56f
1569 user: test
1569 user: test
1570 date: Thu Jan 01 00:00:00 1970 +0000
1570 date: Thu Jan 01 00:00:00 1970 +0000
1571 summary: commit on default
1571 summary: commit on default
1572
1572
1573 #if gettext
1573 #if gettext
1574
1574
1575 Test that all log names are translated (e.g. branches, bookmarks, tags):
1575 Test that all log names are translated (e.g. branches, bookmarks, tags):
1576
1576
1577 $ hg bookmark babar -r tip
1577 $ hg bookmark babar -r tip
1578
1578
1579 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1579 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1580 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1580 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1581 Zweig: test
1581 Zweig: test
1582 Lesezeichen: babar
1582 Lesezeichen: babar
1583 Marke: tip
1583 Marke: tip
1584 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1584 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1585 Nutzer: test
1585 Nutzer: test
1586 Datum: Thu Jan 01 00:00:00 1970 +0000
1586 Datum: Thu Jan 01 00:00:00 1970 +0000
1587 Zusammenfassung: commit on test
1587 Zusammenfassung: commit on test
1588
1588
1589 $ hg bookmark -d babar
1589 $ hg bookmark -d babar
1590
1590
1591 #endif
1591 #endif
1592
1592
1593 log -p --cwd dir (in subdir)
1593 log -p --cwd dir (in subdir)
1594
1594
1595 $ mkdir dir
1595 $ mkdir dir
1596 $ hg log -p --cwd dir
1596 $ hg log -p --cwd dir
1597 changeset: 3:f5d8de11c2e2
1597 changeset: 3:f5d8de11c2e2
1598 branch: test
1598 branch: test
1599 tag: tip
1599 tag: tip
1600 parent: 1:d32277701ccb
1600 parent: 1:d32277701ccb
1601 user: test
1601 user: test
1602 date: Thu Jan 01 00:00:00 1970 +0000
1602 date: Thu Jan 01 00:00:00 1970 +0000
1603 summary: commit on test
1603 summary: commit on test
1604
1604
1605 diff -r d32277701ccb -r f5d8de11c2e2 c
1605 diff -r d32277701ccb -r f5d8de11c2e2 c
1606 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1606 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1607 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1607 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1608 @@ -0,0 +1,1 @@
1608 @@ -0,0 +1,1 @@
1609 +c
1609 +c
1610
1610
1611 changeset: 2:c3a4f03cc9a7
1611 changeset: 2:c3a4f03cc9a7
1612 parent: 0:24427303d56f
1612 parent: 0:24427303d56f
1613 user: test
1613 user: test
1614 date: Thu Jan 01 00:00:00 1970 +0000
1614 date: Thu Jan 01 00:00:00 1970 +0000
1615 summary: commit on default
1615 summary: commit on default
1616
1616
1617 diff -r 24427303d56f -r c3a4f03cc9a7 c
1617 diff -r 24427303d56f -r c3a4f03cc9a7 c
1618 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1618 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1619 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1619 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1620 @@ -0,0 +1,1 @@
1620 @@ -0,0 +1,1 @@
1621 +c
1621 +c
1622
1622
1623 changeset: 1:d32277701ccb
1623 changeset: 1:d32277701ccb
1624 branch: test
1624 branch: test
1625 user: test
1625 user: test
1626 date: Thu Jan 01 00:00:00 1970 +0000
1626 date: Thu Jan 01 00:00:00 1970 +0000
1627 summary: commit on test
1627 summary: commit on test
1628
1628
1629 diff -r 24427303d56f -r d32277701ccb b
1629 diff -r 24427303d56f -r d32277701ccb b
1630 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1630 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1631 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1631 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1632 @@ -0,0 +1,1 @@
1632 @@ -0,0 +1,1 @@
1633 +b
1633 +b
1634
1634
1635 changeset: 0:24427303d56f
1635 changeset: 0:24427303d56f
1636 user: test
1636 user: test
1637 date: Thu Jan 01 00:00:00 1970 +0000
1637 date: Thu Jan 01 00:00:00 1970 +0000
1638 summary: commit on default
1638 summary: commit on default
1639
1639
1640 diff -r 000000000000 -r 24427303d56f a
1640 diff -r 000000000000 -r 24427303d56f a
1641 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1641 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1642 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1642 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1643 @@ -0,0 +1,1 @@
1643 @@ -0,0 +1,1 @@
1644 +a
1644 +a
1645
1645
1646
1646
1647
1647
1648 log -p -R repo
1648 log -p -R repo
1649
1649
1650 $ cd dir
1650 $ cd dir
1651 $ hg log -p -R .. ../a
1651 $ hg log -p -R .. ../a
1652 changeset: 0:24427303d56f
1652 changeset: 0:24427303d56f
1653 user: test
1653 user: test
1654 date: Thu Jan 01 00:00:00 1970 +0000
1654 date: Thu Jan 01 00:00:00 1970 +0000
1655 summary: commit on default
1655 summary: commit on default
1656
1656
1657 diff -r 000000000000 -r 24427303d56f a
1657 diff -r 000000000000 -r 24427303d56f a
1658 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1658 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1659 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1659 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1660 @@ -0,0 +1,1 @@
1660 @@ -0,0 +1,1 @@
1661 +a
1661 +a
1662
1662
1663
1663
1664 $ cd ../..
1664 $ cd ../..
1665
1665
1666 $ hg init follow2
1666 $ hg init follow2
1667 $ cd follow2
1667 $ cd follow2
1668
1668
1669 # Build the following history:
1669 # Build the following history:
1670 # tip - o - x - o - x - x
1670 # tip - o - x - o - x - x
1671 # \ /
1671 # \ /
1672 # o - o - o - x
1672 # o - o - o - x
1673 # \ /
1673 # \ /
1674 # o
1674 # o
1675 #
1675 #
1676 # Where "o" is a revision containing "foo" and
1676 # Where "o" is a revision containing "foo" and
1677 # "x" is a revision without "foo"
1677 # "x" is a revision without "foo"
1678
1678
1679 $ touch init
1679 $ touch init
1680 $ hg ci -A -m "init, unrelated"
1680 $ hg ci -A -m "init, unrelated"
1681 adding init
1681 adding init
1682 $ echo 'foo' > init
1682 $ echo 'foo' > init
1683 $ hg ci -m "change, unrelated"
1683 $ hg ci -m "change, unrelated"
1684 $ echo 'foo' > foo
1684 $ echo 'foo' > foo
1685 $ hg ci -A -m "add unrelated old foo"
1685 $ hg ci -A -m "add unrelated old foo"
1686 adding foo
1686 adding foo
1687 $ hg rm foo
1687 $ hg rm foo
1688 $ hg ci -m "delete foo, unrelated"
1688 $ hg ci -m "delete foo, unrelated"
1689 $ echo 'related' > foo
1689 $ echo 'related' > foo
1690 $ hg ci -A -m "add foo, related"
1690 $ hg ci -A -m "add foo, related"
1691 adding foo
1691 adding foo
1692
1692
1693 $ hg up 0
1693 $ hg up 0
1694 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1694 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1695 $ touch branch
1695 $ touch branch
1696 $ hg ci -A -m "first branch, unrelated"
1696 $ hg ci -A -m "first branch, unrelated"
1697 adding branch
1697 adding branch
1698 created new head
1698 created new head
1699 $ touch foo
1699 $ touch foo
1700 $ hg ci -A -m "create foo, related"
1700 $ hg ci -A -m "create foo, related"
1701 adding foo
1701 adding foo
1702 $ echo 'change' > foo
1702 $ echo 'change' > foo
1703 $ hg ci -m "change foo, related"
1703 $ hg ci -m "change foo, related"
1704
1704
1705 $ hg up 6
1705 $ hg up 6
1706 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1706 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1707 $ echo 'change foo in branch' > foo
1707 $ echo 'change foo in branch' > foo
1708 $ hg ci -m "change foo in branch, related"
1708 $ hg ci -m "change foo in branch, related"
1709 created new head
1709 created new head
1710 $ hg merge 7
1710 $ hg merge 7
1711 merging foo
1711 merging foo
1712 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1712 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1713 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1713 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1714 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1714 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1715 [1]
1715 [1]
1716 $ echo 'merge 1' > foo
1716 $ echo 'merge 1' > foo
1717 $ hg resolve -m foo
1717 $ hg resolve -m foo
1718 (no more unresolved files)
1718 (no more unresolved files)
1719 $ hg ci -m "First merge, related"
1719 $ hg ci -m "First merge, related"
1720
1720
1721 $ hg merge 4
1721 $ hg merge 4
1722 merging foo
1722 merging foo
1723 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1723 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1724 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1724 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1725 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1725 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1726 [1]
1726 [1]
1727 $ echo 'merge 2' > foo
1727 $ echo 'merge 2' > foo
1728 $ hg resolve -m foo
1728 $ hg resolve -m foo
1729 (no more unresolved files)
1729 (no more unresolved files)
1730 $ hg ci -m "Last merge, related"
1730 $ hg ci -m "Last merge, related"
1731
1731
1732 $ hg log --graph
1732 $ hg log --graph
1733 @ changeset: 10:4dae8563d2c5
1733 @ changeset: 10:4dae8563d2c5
1734 |\ tag: tip
1734 |\ tag: tip
1735 | | parent: 9:7b35701b003e
1735 | | parent: 9:7b35701b003e
1736 | | parent: 4:88176d361b69
1736 | | parent: 4:88176d361b69
1737 | | user: test
1737 | | user: test
1738 | | date: Thu Jan 01 00:00:00 1970 +0000
1738 | | date: Thu Jan 01 00:00:00 1970 +0000
1739 | | summary: Last merge, related
1739 | | summary: Last merge, related
1740 | |
1740 | |
1741 | o changeset: 9:7b35701b003e
1741 | o changeset: 9:7b35701b003e
1742 | |\ parent: 8:e5416ad8a855
1742 | |\ parent: 8:e5416ad8a855
1743 | | | parent: 7:87fe3144dcfa
1743 | | | parent: 7:87fe3144dcfa
1744 | | | user: test
1744 | | | user: test
1745 | | | date: Thu Jan 01 00:00:00 1970 +0000
1745 | | | date: Thu Jan 01 00:00:00 1970 +0000
1746 | | | summary: First merge, related
1746 | | | summary: First merge, related
1747 | | |
1747 | | |
1748 | | o changeset: 8:e5416ad8a855
1748 | | o changeset: 8:e5416ad8a855
1749 | | | parent: 6:dc6c325fe5ee
1749 | | | parent: 6:dc6c325fe5ee
1750 | | | user: test
1750 | | | user: test
1751 | | | date: Thu Jan 01 00:00:00 1970 +0000
1751 | | | date: Thu Jan 01 00:00:00 1970 +0000
1752 | | | summary: change foo in branch, related
1752 | | | summary: change foo in branch, related
1753 | | |
1753 | | |
1754 | o | changeset: 7:87fe3144dcfa
1754 | o | changeset: 7:87fe3144dcfa
1755 | |/ user: test
1755 | |/ user: test
1756 | | date: Thu Jan 01 00:00:00 1970 +0000
1756 | | date: Thu Jan 01 00:00:00 1970 +0000
1757 | | summary: change foo, related
1757 | | summary: change foo, related
1758 | |
1758 | |
1759 | o changeset: 6:dc6c325fe5ee
1759 | o changeset: 6:dc6c325fe5ee
1760 | | user: test
1760 | | user: test
1761 | | date: Thu Jan 01 00:00:00 1970 +0000
1761 | | date: Thu Jan 01 00:00:00 1970 +0000
1762 | | summary: create foo, related
1762 | | summary: create foo, related
1763 | |
1763 | |
1764 | o changeset: 5:73db34516eb9
1764 | o changeset: 5:73db34516eb9
1765 | | parent: 0:e87515fd044a
1765 | | parent: 0:e87515fd044a
1766 | | user: test
1766 | | user: test
1767 | | date: Thu Jan 01 00:00:00 1970 +0000
1767 | | date: Thu Jan 01 00:00:00 1970 +0000
1768 | | summary: first branch, unrelated
1768 | | summary: first branch, unrelated
1769 | |
1769 | |
1770 o | changeset: 4:88176d361b69
1770 o | changeset: 4:88176d361b69
1771 | | user: test
1771 | | user: test
1772 | | date: Thu Jan 01 00:00:00 1970 +0000
1772 | | date: Thu Jan 01 00:00:00 1970 +0000
1773 | | summary: add foo, related
1773 | | summary: add foo, related
1774 | |
1774 | |
1775 o | changeset: 3:dd78ae4afb56
1775 o | changeset: 3:dd78ae4afb56
1776 | | user: test
1776 | | user: test
1777 | | date: Thu Jan 01 00:00:00 1970 +0000
1777 | | date: Thu Jan 01 00:00:00 1970 +0000
1778 | | summary: delete foo, unrelated
1778 | | summary: delete foo, unrelated
1779 | |
1779 | |
1780 o | changeset: 2:c4c64aedf0f7
1780 o | changeset: 2:c4c64aedf0f7
1781 | | user: test
1781 | | user: test
1782 | | date: Thu Jan 01 00:00:00 1970 +0000
1782 | | date: Thu Jan 01 00:00:00 1970 +0000
1783 | | summary: add unrelated old foo
1783 | | summary: add unrelated old foo
1784 | |
1784 | |
1785 o | changeset: 1:e5faa7440653
1785 o | changeset: 1:e5faa7440653
1786 |/ user: test
1786 |/ user: test
1787 | date: Thu Jan 01 00:00:00 1970 +0000
1787 | date: Thu Jan 01 00:00:00 1970 +0000
1788 | summary: change, unrelated
1788 | summary: change, unrelated
1789 |
1789 |
1790 o changeset: 0:e87515fd044a
1790 o changeset: 0:e87515fd044a
1791 user: test
1791 user: test
1792 date: Thu Jan 01 00:00:00 1970 +0000
1792 date: Thu Jan 01 00:00:00 1970 +0000
1793 summary: init, unrelated
1793 summary: init, unrelated
1794
1794
1795
1795
1796 $ hg --traceback log -f foo
1796 $ hg --traceback log -f foo
1797 changeset: 10:4dae8563d2c5
1797 changeset: 10:4dae8563d2c5
1798 tag: tip
1798 tag: tip
1799 parent: 9:7b35701b003e
1799 parent: 9:7b35701b003e
1800 parent: 4:88176d361b69
1800 parent: 4:88176d361b69
1801 user: test
1801 user: test
1802 date: Thu Jan 01 00:00:00 1970 +0000
1802 date: Thu Jan 01 00:00:00 1970 +0000
1803 summary: Last merge, related
1803 summary: Last merge, related
1804
1804
1805 changeset: 9:7b35701b003e
1805 changeset: 9:7b35701b003e
1806 parent: 8:e5416ad8a855
1806 parent: 8:e5416ad8a855
1807 parent: 7:87fe3144dcfa
1807 parent: 7:87fe3144dcfa
1808 user: test
1808 user: test
1809 date: Thu Jan 01 00:00:00 1970 +0000
1809 date: Thu Jan 01 00:00:00 1970 +0000
1810 summary: First merge, related
1810 summary: First merge, related
1811
1811
1812 changeset: 8:e5416ad8a855
1812 changeset: 8:e5416ad8a855
1813 parent: 6:dc6c325fe5ee
1813 parent: 6:dc6c325fe5ee
1814 user: test
1814 user: test
1815 date: Thu Jan 01 00:00:00 1970 +0000
1815 date: Thu Jan 01 00:00:00 1970 +0000
1816 summary: change foo in branch, related
1816 summary: change foo in branch, related
1817
1817
1818 changeset: 7:87fe3144dcfa
1818 changeset: 7:87fe3144dcfa
1819 user: test
1819 user: test
1820 date: Thu Jan 01 00:00:00 1970 +0000
1820 date: Thu Jan 01 00:00:00 1970 +0000
1821 summary: change foo, related
1821 summary: change foo, related
1822
1822
1823 changeset: 6:dc6c325fe5ee
1823 changeset: 6:dc6c325fe5ee
1824 user: test
1824 user: test
1825 date: Thu Jan 01 00:00:00 1970 +0000
1825 date: Thu Jan 01 00:00:00 1970 +0000
1826 summary: create foo, related
1826 summary: create foo, related
1827
1827
1828 changeset: 4:88176d361b69
1828 changeset: 4:88176d361b69
1829 user: test
1829 user: test
1830 date: Thu Jan 01 00:00:00 1970 +0000
1830 date: Thu Jan 01 00:00:00 1970 +0000
1831 summary: add foo, related
1831 summary: add foo, related
1832
1832
1833
1833
1834 Also check when maxrev < lastrevfilelog
1834 Also check when maxrev < lastrevfilelog
1835
1835
1836 $ hg --traceback log -f -r4 foo
1836 $ hg --traceback log -f -r4 foo
1837 changeset: 4:88176d361b69
1837 changeset: 4:88176d361b69
1838 user: test
1838 user: test
1839 date: Thu Jan 01 00:00:00 1970 +0000
1839 date: Thu Jan 01 00:00:00 1970 +0000
1840 summary: add foo, related
1840 summary: add foo, related
1841
1841
1842 $ cd ..
1842 $ cd ..
1843
1843
1844 Issue2383: hg log showing _less_ differences than hg diff
1844 Issue2383: hg log showing _less_ differences than hg diff
1845
1845
1846 $ hg init issue2383
1846 $ hg init issue2383
1847 $ cd issue2383
1847 $ cd issue2383
1848
1848
1849 Create a test repo:
1849 Create a test repo:
1850
1850
1851 $ echo a > a
1851 $ echo a > a
1852 $ hg ci -Am0
1852 $ hg ci -Am0
1853 adding a
1853 adding a
1854 $ echo b > b
1854 $ echo b > b
1855 $ hg ci -Am1
1855 $ hg ci -Am1
1856 adding b
1856 adding b
1857 $ hg co 0
1857 $ hg co 0
1858 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1858 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1859 $ echo b > a
1859 $ echo b > a
1860 $ hg ci -m2
1860 $ hg ci -m2
1861 created new head
1861 created new head
1862
1862
1863 Merge:
1863 Merge:
1864
1864
1865 $ hg merge
1865 $ hg merge
1866 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1866 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1867 (branch merge, don't forget to commit)
1867 (branch merge, don't forget to commit)
1868
1868
1869 Make sure there's a file listed in the merge to trigger the bug:
1869 Make sure there's a file listed in the merge to trigger the bug:
1870
1870
1871 $ echo c > a
1871 $ echo c > a
1872 $ hg ci -m3
1872 $ hg ci -m3
1873
1873
1874 Two files shown here in diff:
1874 Two files shown here in diff:
1875
1875
1876 $ hg diff --rev 2:3
1876 $ hg diff --rev 2:3
1877 diff -r b09be438c43a -r 8e07aafe1edc a
1877 diff -r b09be438c43a -r 8e07aafe1edc a
1878 --- a/a Thu Jan 01 00:00:00 1970 +0000
1878 --- a/a Thu Jan 01 00:00:00 1970 +0000
1879 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1879 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1880 @@ -1,1 +1,1 @@
1880 @@ -1,1 +1,1 @@
1881 -b
1881 -b
1882 +c
1882 +c
1883 diff -r b09be438c43a -r 8e07aafe1edc b
1883 diff -r b09be438c43a -r 8e07aafe1edc b
1884 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1884 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1885 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1885 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1886 @@ -0,0 +1,1 @@
1886 @@ -0,0 +1,1 @@
1887 +b
1887 +b
1888
1888
1889 Diff here should be the same:
1889 Diff here should be the same:
1890
1890
1891 $ hg log -vpr 3
1891 $ hg log -vpr 3
1892 changeset: 3:8e07aafe1edc
1892 changeset: 3:8e07aafe1edc
1893 tag: tip
1893 tag: tip
1894 parent: 2:b09be438c43a
1894 parent: 2:b09be438c43a
1895 parent: 1:925d80f479bb
1895 parent: 1:925d80f479bb
1896 user: test
1896 user: test
1897 date: Thu Jan 01 00:00:00 1970 +0000
1897 date: Thu Jan 01 00:00:00 1970 +0000
1898 files: a
1898 files: a
1899 description:
1899 description:
1900 3
1900 3
1901
1901
1902
1902
1903 diff -r b09be438c43a -r 8e07aafe1edc a
1903 diff -r b09be438c43a -r 8e07aafe1edc a
1904 --- a/a Thu Jan 01 00:00:00 1970 +0000
1904 --- a/a Thu Jan 01 00:00:00 1970 +0000
1905 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1905 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1906 @@ -1,1 +1,1 @@
1906 @@ -1,1 +1,1 @@
1907 -b
1907 -b
1908 +c
1908 +c
1909 diff -r b09be438c43a -r 8e07aafe1edc b
1909 diff -r b09be438c43a -r 8e07aafe1edc b
1910 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1910 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1911 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1911 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1912 @@ -0,0 +1,1 @@
1912 @@ -0,0 +1,1 @@
1913 +b
1913 +b
1914
1914
1915 $ cd ..
1915 $ cd ..
1916
1916
1917 'hg log -r rev fn' when last(filelog(fn)) != rev
1917 'hg log -r rev fn' when last(filelog(fn)) != rev
1918
1918
1919 $ hg init simplelog
1919 $ hg init simplelog
1920 $ cd simplelog
1920 $ cd simplelog
1921 $ echo f > a
1921 $ echo f > a
1922 $ hg ci -Am'a' -d '0 0'
1922 $ hg ci -Am'a' -d '0 0'
1923 adding a
1923 adding a
1924 $ echo f >> a
1924 $ echo f >> a
1925 $ hg ci -Am'a bis' -d '1 0'
1925 $ hg ci -Am'a bis' -d '1 0'
1926
1926
1927 $ hg log -r0 a
1927 $ hg log -r0 a
1928 changeset: 0:9f758d63dcde
1928 changeset: 0:9f758d63dcde
1929 user: test
1929 user: test
1930 date: Thu Jan 01 00:00:00 1970 +0000
1930 date: Thu Jan 01 00:00:00 1970 +0000
1931 summary: a
1931 summary: a
1932
1932
1933 enable obsolete to test hidden feature
1933 enable obsolete to test hidden feature
1934
1934
1935 $ cat >> $HGRCPATH << EOF
1935 $ cat >> $HGRCPATH << EOF
1936 > [experimental]
1936 > [experimental]
1937 > evolution.createmarkers=True
1937 > evolution.createmarkers=True
1938 > EOF
1938 > EOF
1939
1939
1940 $ hg log --template='{rev}:{node}\n'
1940 $ hg log --template='{rev}:{node}\n'
1941 1:a765632148dc55d38c35c4f247c618701886cb2f
1941 1:a765632148dc55d38c35c4f247c618701886cb2f
1942 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1942 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1943 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1943 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1944 1 new obsolescence markers
1944 1 new obsolescence markers
1945 obsoleted 1 changesets
1945 obsoleted 1 changesets
1946 $ hg up null -q
1946 $ hg up null -q
1947 $ hg log --template='{rev}:{node}\n'
1947 $ hg log --template='{rev}:{node}\n'
1948 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1948 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1949 $ hg log --template='{rev}:{node}\n' --hidden
1949 $ hg log --template='{rev}:{node}\n' --hidden
1950 1:a765632148dc55d38c35c4f247c618701886cb2f
1950 1:a765632148dc55d38c35c4f247c618701886cb2f
1951 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1951 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1952 $ hg log -r a
1952 $ hg log -r a
1953 abort: hidden revision 'a' is pruned!
1953 abort: hidden revision 'a' is pruned!
1954 (use --hidden to access hidden revisions)
1954 (use --hidden to access hidden revisions)
1955 [255]
1955 [255]
1956
1956
1957 test that parent prevent a changeset to be hidden
1957 test that parent prevent a changeset to be hidden
1958
1958
1959 $ hg up 1 -q --hidden
1959 $ hg up 1 -q --hidden
1960 updated to hidden changeset a765632148dc
1960 updated to hidden changeset a765632148dc
1961 (hidden revision 'a765632148dc' is pruned)
1961 (hidden revision 'a765632148dc' is pruned)
1962 $ hg log --template='{rev}:{node}\n'
1962 $ hg log --template='{rev}:{node}\n'
1963 1:a765632148dc55d38c35c4f247c618701886cb2f
1963 1:a765632148dc55d38c35c4f247c618701886cb2f
1964 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1964 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1965
1965
1966 test that second parent prevent a changeset to be hidden too
1966 test that second parent prevent a changeset to be hidden too
1967
1967
1968 $ hg debugsetparents 0 1 # nothing suitable to merge here
1968 $ hg debugsetparents 0 1 # nothing suitable to merge here
1969 $ hg log --template='{rev}:{node}\n'
1969 $ hg log --template='{rev}:{node}\n'
1970 1:a765632148dc55d38c35c4f247c618701886cb2f
1970 1:a765632148dc55d38c35c4f247c618701886cb2f
1971 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1971 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1972 $ hg debugsetparents 1
1972 $ hg debugsetparents 1
1973 $ hg up -q null
1973 $ hg up -q null
1974
1974
1975 bookmarks prevent a changeset being hidden
1975 bookmarks prevent a changeset being hidden
1976
1976
1977 $ hg bookmark --hidden -r 1 X
1977 $ hg bookmark --hidden -r 1 X
1978 bookmarking hidden changeset a765632148dc
1978 bookmarking hidden changeset a765632148dc
1979 (hidden revision 'a765632148dc' is pruned)
1979 (hidden revision 'a765632148dc' is pruned)
1980 $ hg log --template '{rev}:{node}\n'
1980 $ hg log --template '{rev}:{node}\n'
1981 1:a765632148dc55d38c35c4f247c618701886cb2f
1981 1:a765632148dc55d38c35c4f247c618701886cb2f
1982 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1982 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1983 $ hg bookmark -d X
1983 $ hg bookmark -d X
1984
1984
1985 divergent bookmarks are not hidden
1985 divergent bookmarks are not hidden
1986
1986
1987 $ hg bookmark --hidden -r 1 X@foo
1987 $ hg bookmark --hidden -r 1 X@foo
1988 bookmarking hidden changeset a765632148dc
1988 bookmarking hidden changeset a765632148dc
1989 (hidden revision 'a765632148dc' is pruned)
1989 (hidden revision 'a765632148dc' is pruned)
1990 $ hg log --template '{rev}:{node}\n'
1990 $ hg log --template '{rev}:{node}\n'
1991 1:a765632148dc55d38c35c4f247c618701886cb2f
1991 1:a765632148dc55d38c35c4f247c618701886cb2f
1992 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1992 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1993
1993
1994 test hidden revision 0 (issue5385)
1994 test hidden revision 0 (issue5385)
1995
1995
1996 $ hg bookmark -d X@foo
1996 $ hg bookmark -d X@foo
1997 $ hg up null -q
1997 $ hg up null -q
1998 $ hg debugobsolete 9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1998 $ hg debugobsolete 9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1999 1 new obsolescence markers
1999 1 new obsolescence markers
2000 obsoleted 1 changesets
2000 obsoleted 1 changesets
2001 $ echo f > b
2001 $ echo f > b
2002 $ hg ci -Am'b' -d '2 0'
2002 $ hg ci -Am'b' -d '2 0'
2003 adding b
2003 adding b
2004 $ echo f >> b
2004 $ echo f >> b
2005 $ hg ci -m'b bis' -d '3 0'
2005 $ hg ci -m'b bis' -d '3 0'
2006 $ hg log -T'{rev}:{node}\n'
2006 $ hg log -T'{rev}:{node}\n'
2007 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2007 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2008 2:94375ec45bddd2a824535fc04855bd058c926ec0
2008 2:94375ec45bddd2a824535fc04855bd058c926ec0
2009
2009
2010 $ hg log -T'{rev}:{node}\n' -r:
2010 $ hg log -T'{rev}:{node}\n' -r:
2011 2:94375ec45bddd2a824535fc04855bd058c926ec0
2011 2:94375ec45bddd2a824535fc04855bd058c926ec0
2012 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2012 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2013 $ hg log -T'{rev}:{node}\n' -r:tip
2013 $ hg log -T'{rev}:{node}\n' -r:tip
2014 2:94375ec45bddd2a824535fc04855bd058c926ec0
2014 2:94375ec45bddd2a824535fc04855bd058c926ec0
2015 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2015 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2016 $ hg log -T'{rev}:{node}\n' -r:0
2016 $ hg log -T'{rev}:{node}\n' -r:0
2017 abort: hidden revision '0' is pruned!
2017 abort: hidden revision '0' is pruned!
2018 (use --hidden to access hidden revisions)
2018 (use --hidden to access hidden revisions)
2019 [255]
2019 [255]
2020 $ hg log -T'{rev}:{node}\n' -f
2020 $ hg log -T'{rev}:{node}\n' -f
2021 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2021 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2022 2:94375ec45bddd2a824535fc04855bd058c926ec0
2022 2:94375ec45bddd2a824535fc04855bd058c926ec0
2023
2023
2024 clear extensions configuration
2024 clear extensions configuration
2025 $ echo '[extensions]' >> $HGRCPATH
2025 $ echo '[extensions]' >> $HGRCPATH
2026 $ echo "obs=!" >> $HGRCPATH
2026 $ echo "obs=!" >> $HGRCPATH
2027 $ cd ..
2027 $ cd ..
2028
2028
2029 test -u/-k for problematic encoding
2029 test -u/-k for problematic encoding
2030 # unicode: cp932:
2030 # unicode: cp932:
2031 # u30A2 0x83 0x41(= 'A')
2031 # u30A2 0x83 0x41(= 'A')
2032 # u30C2 0x83 0x61(= 'a')
2032 # u30C2 0x83 0x61(= 'a')
2033
2033
2034 $ hg init problematicencoding
2034 $ hg init problematicencoding
2035 $ cd problematicencoding
2035 $ cd problematicencoding
2036
2036
2037 >>> with open('setup.sh', 'wb') as f:
2037 >>> with open('setup.sh', 'wb') as f:
2038 ... f.write(u'''
2038 ... f.write(u'''
2039 ... echo a > text
2039 ... echo a > text
2040 ... hg add text
2040 ... hg add text
2041 ... hg --encoding utf-8 commit -u '\u30A2' -m none
2041 ... hg --encoding utf-8 commit -u '\u30A2' -m none
2042 ... echo b > text
2042 ... echo b > text
2043 ... hg --encoding utf-8 commit -u '\u30C2' -m none
2043 ... hg --encoding utf-8 commit -u '\u30C2' -m none
2044 ... echo c > text
2044 ... echo c > text
2045 ... hg --encoding utf-8 commit -u none -m '\u30A2'
2045 ... hg --encoding utf-8 commit -u none -m '\u30A2'
2046 ... echo d > text
2046 ... echo d > text
2047 ... hg --encoding utf-8 commit -u none -m '\u30C2'
2047 ... hg --encoding utf-8 commit -u none -m '\u30C2'
2048 ... '''.encode('utf-8')) and None
2048 ... '''.encode('utf-8')) and None
2049 $ sh < setup.sh
2049 $ sh < setup.sh
2050
2050
2051 test in problematic encoding
2051 test in problematic encoding
2052 >>> with open('test.sh', 'wb') as f:
2052 >>> with open('test.sh', 'wb') as f:
2053 ... f.write(u'''
2053 ... f.write(u'''
2054 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
2054 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
2055 ... echo ====
2055 ... echo ====
2056 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
2056 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
2057 ... echo ====
2057 ... echo ====
2058 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
2058 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
2059 ... echo ====
2059 ... echo ====
2060 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
2060 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
2061 ... '''.encode('cp932')) and None
2061 ... '''.encode('cp932')) and None
2062 $ sh < test.sh
2062 $ sh < test.sh
2063 0
2063 0
2064 ====
2064 ====
2065 1
2065 1
2066 ====
2066 ====
2067 2
2067 2
2068 0
2068 0
2069 ====
2069 ====
2070 3
2070 3
2071 1
2071 1
2072
2072
2073 $ cd ..
2073 $ cd ..
2074
2074
2075 test hg log on non-existent files and on directories
2075 test hg log on non-existent files and on directories
2076 $ hg init issue1340
2076 $ hg init issue1340
2077 $ cd issue1340
2077 $ cd issue1340
2078 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
2078 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
2079 $ echo 1 > d1/f1
2079 $ echo 1 > d1/f1
2080 $ echo 1 > D2/f1
2080 $ echo 1 > D2/f1
2081 $ echo 1 > D3.i/f1
2081 $ echo 1 > D3.i/f1
2082 $ echo 1 > d4.hg/f1
2082 $ echo 1 > d4.hg/f1
2083 $ echo 1 > d5.d/f1
2083 $ echo 1 > d5.d/f1
2084 $ echo 1 > .d6/f1
2084 $ echo 1 > .d6/f1
2085 $ hg -q add .
2085 $ hg -q add .
2086 $ hg commit -m "a bunch of weird directories"
2086 $ hg commit -m "a bunch of weird directories"
2087 $ hg log -l1 d1/f1 | grep changeset
2087 $ hg log -l1 d1/f1 | grep changeset
2088 changeset: 0:65624cd9070a
2088 changeset: 0:65624cd9070a
2089 $ hg log -l1 f1
2089 $ hg log -l1 f1
2090 $ hg log -l1 . | grep changeset
2090 $ hg log -l1 . | grep changeset
2091 changeset: 0:65624cd9070a
2091 changeset: 0:65624cd9070a
2092 $ hg log -l1 ./ | grep changeset
2092 $ hg log -l1 ./ | grep changeset
2093 changeset: 0:65624cd9070a
2093 changeset: 0:65624cd9070a
2094 $ hg log -l1 d1 | grep changeset
2094 $ hg log -l1 d1 | grep changeset
2095 changeset: 0:65624cd9070a
2095 changeset: 0:65624cd9070a
2096 $ hg log -l1 D2 | grep changeset
2096 $ hg log -l1 D2 | grep changeset
2097 changeset: 0:65624cd9070a
2097 changeset: 0:65624cd9070a
2098 $ hg log -l1 D2/f1 | grep changeset
2098 $ hg log -l1 D2/f1 | grep changeset
2099 changeset: 0:65624cd9070a
2099 changeset: 0:65624cd9070a
2100 $ hg log -l1 D3.i | grep changeset
2100 $ hg log -l1 D3.i | grep changeset
2101 changeset: 0:65624cd9070a
2101 changeset: 0:65624cd9070a
2102 $ hg log -l1 D3.i/f1 | grep changeset
2102 $ hg log -l1 D3.i/f1 | grep changeset
2103 changeset: 0:65624cd9070a
2103 changeset: 0:65624cd9070a
2104 $ hg log -l1 d4.hg | grep changeset
2104 $ hg log -l1 d4.hg | grep changeset
2105 changeset: 0:65624cd9070a
2105 changeset: 0:65624cd9070a
2106 $ hg log -l1 d4.hg/f1 | grep changeset
2106 $ hg log -l1 d4.hg/f1 | grep changeset
2107 changeset: 0:65624cd9070a
2107 changeset: 0:65624cd9070a
2108 $ hg log -l1 d5.d | grep changeset
2108 $ hg log -l1 d5.d | grep changeset
2109 changeset: 0:65624cd9070a
2109 changeset: 0:65624cd9070a
2110 $ hg log -l1 d5.d/f1 | grep changeset
2110 $ hg log -l1 d5.d/f1 | grep changeset
2111 changeset: 0:65624cd9070a
2111 changeset: 0:65624cd9070a
2112 $ hg log -l1 .d6 | grep changeset
2112 $ hg log -l1 .d6 | grep changeset
2113 changeset: 0:65624cd9070a
2113 changeset: 0:65624cd9070a
2114 $ hg log -l1 .d6/f1 | grep changeset
2114 $ hg log -l1 .d6/f1 | grep changeset
2115 changeset: 0:65624cd9070a
2115 changeset: 0:65624cd9070a
2116
2116
2117 issue3772: hg log -r :null showing revision 0 as well
2117 issue3772: hg log -r :null showing revision 0 as well
2118
2118
2119 $ hg log -r :null
2119 $ hg log -r :null
2120 changeset: 0:65624cd9070a
2120 changeset: 0:65624cd9070a
2121 tag: tip
2121 tag: tip
2122 user: test
2122 user: test
2123 date: Thu Jan 01 00:00:00 1970 +0000
2123 date: Thu Jan 01 00:00:00 1970 +0000
2124 summary: a bunch of weird directories
2124 summary: a bunch of weird directories
2125
2125
2126 changeset: -1:000000000000
2126 changeset: -1:000000000000
2127 user:
2127 user:
2128 date: Thu Jan 01 00:00:00 1970 +0000
2128 date: Thu Jan 01 00:00:00 1970 +0000
2129
2129
2130 $ hg log -r null:null
2130 $ hg log -r null:null
2131 changeset: -1:000000000000
2131 changeset: -1:000000000000
2132 user:
2132 user:
2133 date: Thu Jan 01 00:00:00 1970 +0000
2133 date: Thu Jan 01 00:00:00 1970 +0000
2134
2134
2135 working-directory revision requires special treatment
2135 working-directory revision requires special treatment
2136
2136
2137 clean:
2137 clean:
2138
2138
2139 $ hg log -r 'wdir()' --debug
2139 $ hg log -r 'wdir()' --debug
2140 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2140 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2141 phase: draft
2141 phase: draft
2142 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2142 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2143 parent: -1:0000000000000000000000000000000000000000
2143 parent: -1:0000000000000000000000000000000000000000
2144 manifest: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2144 manifest: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2145 user: test
2145 user: test
2146 date: [A-Za-z0-9:+ ]+ (re)
2146 date: [A-Za-z0-9:+ ]+ (re)
2147 extra: branch=default
2147 extra: branch=default
2148
2148
2149 $ hg log -r 'wdir()' -p --stat
2149 $ hg log -r 'wdir()' -p --stat
2150 changeset: 2147483647:ffffffffffff
2150 changeset: 2147483647:ffffffffffff
2151 parent: 0:65624cd9070a
2151 parent: 0:65624cd9070a
2152 user: test
2152 user: test
2153 date: [A-Za-z0-9:+ ]+ (re)
2153 date: [A-Za-z0-9:+ ]+ (re)
2154
2154
2155
2155
2156
2156
2157
2157
2158 dirty:
2158 dirty:
2159
2159
2160 $ echo 2 >> d1/f1
2160 $ echo 2 >> d1/f1
2161 $ echo 2 > d1/f2
2161 $ echo 2 > d1/f2
2162 $ hg add d1/f2
2162 $ hg add d1/f2
2163 $ hg remove .d6/f1
2163 $ hg remove .d6/f1
2164 $ hg status
2164 $ hg status
2165 M d1/f1
2165 M d1/f1
2166 A d1/f2
2166 A d1/f2
2167 R .d6/f1
2167 R .d6/f1
2168
2168
2169 $ hg log -r 'wdir()'
2169 $ hg log -r 'wdir()'
2170 changeset: 2147483647:ffffffffffff
2170 changeset: 2147483647:ffffffffffff
2171 parent: 0:65624cd9070a
2171 parent: 0:65624cd9070a
2172 user: test
2172 user: test
2173 date: [A-Za-z0-9:+ ]+ (re)
2173 date: [A-Za-z0-9:+ ]+ (re)
2174
2174
2175 $ hg log -r 'wdir()' -q
2175 $ hg log -r 'wdir()' -q
2176 2147483647:ffffffffffff
2176 2147483647:ffffffffffff
2177
2177
2178 $ hg log -r 'wdir()' --debug
2178 $ hg log -r 'wdir()' --debug
2179 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2179 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2180 phase: draft
2180 phase: draft
2181 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2181 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2182 parent: -1:0000000000000000000000000000000000000000
2182 parent: -1:0000000000000000000000000000000000000000
2183 manifest: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2183 manifest: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2184 user: test
2184 user: test
2185 date: [A-Za-z0-9:+ ]+ (re)
2185 date: [A-Za-z0-9:+ ]+ (re)
2186 files: d1/f1
2186 files: d1/f1
2187 files+: d1/f2
2187 files+: d1/f2
2188 files-: .d6/f1
2188 files-: .d6/f1
2189 extra: branch=default
2189 extra: branch=default
2190
2190
2191 $ hg log -r 'wdir()' -p --stat --git
2191 $ hg log -r 'wdir()' -p --stat --git
2192 changeset: 2147483647:ffffffffffff
2192 changeset: 2147483647:ffffffffffff
2193 parent: 0:65624cd9070a
2193 parent: 0:65624cd9070a
2194 user: test
2194 user: test
2195 date: [A-Za-z0-9:+ ]+ (re)
2195 date: [A-Za-z0-9:+ ]+ (re)
2196
2196
2197 .d6/f1 | 1 -
2197 .d6/f1 | 1 -
2198 d1/f1 | 1 +
2198 d1/f1 | 1 +
2199 d1/f2 | 1 +
2199 d1/f2 | 1 +
2200 3 files changed, 2 insertions(+), 1 deletions(-)
2200 3 files changed, 2 insertions(+), 1 deletions(-)
2201
2201
2202 diff --git a/.d6/f1 b/.d6/f1
2202 diff --git a/.d6/f1 b/.d6/f1
2203 deleted file mode 100644
2203 deleted file mode 100644
2204 --- a/.d6/f1
2204 --- a/.d6/f1
2205 +++ /dev/null
2205 +++ /dev/null
2206 @@ -1,1 +0,0 @@
2206 @@ -1,1 +0,0 @@
2207 -1
2207 -1
2208 diff --git a/d1/f1 b/d1/f1
2208 diff --git a/d1/f1 b/d1/f1
2209 --- a/d1/f1
2209 --- a/d1/f1
2210 +++ b/d1/f1
2210 +++ b/d1/f1
2211 @@ -1,1 +1,2 @@
2211 @@ -1,1 +1,2 @@
2212 1
2212 1
2213 +2
2213 +2
2214 diff --git a/d1/f2 b/d1/f2
2214 diff --git a/d1/f2 b/d1/f2
2215 new file mode 100644
2215 new file mode 100644
2216 --- /dev/null
2216 --- /dev/null
2217 +++ b/d1/f2
2217 +++ b/d1/f2
2218 @@ -0,0 +1,1 @@
2218 @@ -0,0 +1,1 @@
2219 +2
2219 +2
2220
2220
2221 $ hg log -r 'wdir()' -Tjson
2221 $ hg log -r 'wdir()' -Tjson
2222 [
2222 [
2223 {
2223 {
2224 "bookmarks": [],
2224 "bookmarks": [],
2225 "branch": "default",
2225 "branch": "default",
2226 "date": [*, 0], (glob)
2226 "date": [*, 0], (glob)
2227 "desc": "",
2227 "desc": "",
2228 "node": "ffffffffffffffffffffffffffffffffffffffff",
2228 "node": "ffffffffffffffffffffffffffffffffffffffff",
2229 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2229 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2230 "phase": "draft",
2230 "phase": "draft",
2231 "rev": 2147483647,
2231 "rev": 2147483647,
2232 "tags": [],
2232 "tags": [],
2233 "user": "test"
2233 "user": "test"
2234 }
2234 }
2235 ]
2235 ]
2236
2236
2237 $ hg log -r 'wdir()' -Tjson -q
2237 $ hg log -r 'wdir()' -Tjson -q
2238 [
2238 [
2239 {
2239 {
2240 "node": "ffffffffffffffffffffffffffffffffffffffff",
2240 "node": "ffffffffffffffffffffffffffffffffffffffff",
2241 "rev": 2147483647
2241 "rev": 2147483647
2242 }
2242 }
2243 ]
2243 ]
2244
2244
2245 $ hg log -r 'wdir()' -Tjson --debug
2245 $ hg log -r 'wdir()' -Tjson --debug
2246 [
2246 [
2247 {
2247 {
2248 "added": ["d1/f2"],
2248 "added": ["d1/f2"],
2249 "bookmarks": [],
2249 "bookmarks": [],
2250 "branch": "default",
2250 "branch": "default",
2251 "date": [*, 0], (glob)
2251 "date": [*, 0], (glob)
2252 "desc": "",
2252 "desc": "",
2253 "extra": {"branch": "default"},
2253 "extra": {"branch": "default"},
2254 "manifest": "ffffffffffffffffffffffffffffffffffffffff",
2254 "manifest": "ffffffffffffffffffffffffffffffffffffffff",
2255 "modified": ["d1/f1"],
2255 "modified": ["d1/f1"],
2256 "node": "ffffffffffffffffffffffffffffffffffffffff",
2256 "node": "ffffffffffffffffffffffffffffffffffffffff",
2257 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2257 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2258 "phase": "draft",
2258 "phase": "draft",
2259 "removed": [".d6/f1"],
2259 "removed": [".d6/f1"],
2260 "rev": 2147483647,
2260 "rev": 2147483647,
2261 "tags": [],
2261 "tags": [],
2262 "user": "test"
2262 "user": "test"
2263 }
2263 }
2264 ]
2264 ]
2265
2265
2266 follow files from wdir
2267
2268 $ hg cp d1/f1 f1-copy
2269 $ hg stat --all
2270 M d1/f1
2271 A d1/f2
2272 A f1-copy
2273 d1/f1
2274 R .d6/f1
2275 C D2/f1
2276 C D3.i/f1
2277 C d4.hg/f1
2278 C d5.d/f1
2279
2280 $ hg log -T '== {rev} ==\n' -fr'wdir()' --git --stat d5.d/f1
2281 == 2147483647 ==
2282
2283 == 0 ==
2284 d5.d/f1 | 1 +
2285 1 files changed, 1 insertions(+), 0 deletions(-)
2286
2287
2288 $ hg log -T '== {rev} ==\n' -fr'wdir()' --git --stat d1/f1
2289 == 2147483647 ==
2290 d1/f1 | 1 +
2291 1 files changed, 1 insertions(+), 0 deletions(-)
2292
2293 == 0 ==
2294 d1/f1 | 1 +
2295 1 files changed, 1 insertions(+), 0 deletions(-)
2296
2297
2298 BROKEN: added file should exist in wdir
2299 $ hg log -T '== {rev} ==\n' -fr'wdir()' --git --stat d1/f2
2300 abort: cannot follow nonexistent file: "d1/f2"
2301 [255]
2302
2303 BROKEN: copied file should exist in wdir
2304 $ hg log -T '== {rev} ==\n' -fr'wdir()' --git --stat f1-copy
2305 abort: cannot follow nonexistent file: "f1-copy"
2306 [255]
2307
2308 $ hg log -T '== {rev} ==\n' -fr'wdir()' --git --stat notfound
2309 notfound: $ENOENT$
2310
2266 $ hg revert -aqC
2311 $ hg revert -aqC
2267
2312
2268 Check that adding an arbitrary name shows up in log automatically
2313 Check that adding an arbitrary name shows up in log automatically
2269
2314
2270 $ cat > ../names.py <<EOF
2315 $ cat > ../names.py <<EOF
2271 > """A small extension to test adding arbitrary names to a repo"""
2316 > """A small extension to test adding arbitrary names to a repo"""
2272 > from __future__ import absolute_import
2317 > from __future__ import absolute_import
2273 > from mercurial import namespaces
2318 > from mercurial import namespaces
2274 >
2319 >
2275 > def reposetup(ui, repo):
2320 > def reposetup(ui, repo):
2276 > if not repo.local():
2321 > if not repo.local():
2277 > return
2322 > return
2278 > foo = {b'foo': repo[0].node()}
2323 > foo = {b'foo': repo[0].node()}
2279 > names = lambda r: foo.keys()
2324 > names = lambda r: foo.keys()
2280 > namemap = lambda r, name: foo.get(name)
2325 > namemap = lambda r, name: foo.get(name)
2281 > nodemap = lambda r, node: [name for name, n in foo.items()
2326 > nodemap = lambda r, node: [name for name, n in foo.items()
2282 > if n == node]
2327 > if n == node]
2283 > ns = namespaces.namespace(
2328 > ns = namespaces.namespace(
2284 > b"bars", templatename=b"bar", logname=b"barlog",
2329 > b"bars", templatename=b"bar", logname=b"barlog",
2285 > colorname=b"barcolor", listnames=names, namemap=namemap,
2330 > colorname=b"barcolor", listnames=names, namemap=namemap,
2286 > nodemap=nodemap)
2331 > nodemap=nodemap)
2287 >
2332 >
2288 > repo.names.addnamespace(ns)
2333 > repo.names.addnamespace(ns)
2289 > EOF
2334 > EOF
2290
2335
2291 $ hg --config extensions.names=../names.py log -r 0
2336 $ hg --config extensions.names=../names.py log -r 0
2292 changeset: 0:65624cd9070a
2337 changeset: 0:65624cd9070a
2293 tag: tip
2338 tag: tip
2294 barlog: foo
2339 barlog: foo
2295 user: test
2340 user: test
2296 date: Thu Jan 01 00:00:00 1970 +0000
2341 date: Thu Jan 01 00:00:00 1970 +0000
2297 summary: a bunch of weird directories
2342 summary: a bunch of weird directories
2298
2343
2299 $ hg --config extensions.names=../names.py \
2344 $ hg --config extensions.names=../names.py \
2300 > --config extensions.color= --config color.log.barcolor=red \
2345 > --config extensions.color= --config color.log.barcolor=red \
2301 > --color=always log -r 0
2346 > --color=always log -r 0
2302 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
2347 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
2303 tag: tip
2348 tag: tip
2304 \x1b[0;31mbarlog: foo\x1b[0m (esc)
2349 \x1b[0;31mbarlog: foo\x1b[0m (esc)
2305 user: test
2350 user: test
2306 date: Thu Jan 01 00:00:00 1970 +0000
2351 date: Thu Jan 01 00:00:00 1970 +0000
2307 summary: a bunch of weird directories
2352 summary: a bunch of weird directories
2308
2353
2309 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
2354 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
2310 foo
2355 foo
2311
2356
2312 Templater parse errors:
2357 Templater parse errors:
2313
2358
2314 simple error
2359 simple error
2315 $ hg log -r . -T '{shortest(node}'
2360 $ hg log -r . -T '{shortest(node}'
2316 hg: parse error at 14: unexpected token: end
2361 hg: parse error at 14: unexpected token: end
2317 ({shortest(node}
2362 ({shortest(node}
2318 ^ here)
2363 ^ here)
2319 [255]
2364 [255]
2320
2365
2321 multi-line template with error
2366 multi-line template with error
2322 $ hg log -r . -T 'line 1
2367 $ hg log -r . -T 'line 1
2323 > line2
2368 > line2
2324 > {shortest(node}
2369 > {shortest(node}
2325 > line4\nline5'
2370 > line4\nline5'
2326 hg: parse error at 27: unexpected token: end
2371 hg: parse error at 27: unexpected token: end
2327 (line 1\nline2\n{shortest(node}\nline4\nline5
2372 (line 1\nline2\n{shortest(node}\nline4\nline5
2328 ^ here)
2373 ^ here)
2329 [255]
2374 [255]
2330
2375
2331 $ cd ..
2376 $ cd ..
2332
2377
2333 New namespace is registered per repo instance, but the template keyword
2378 New namespace is registered per repo instance, but the template keyword
2334 is global. So we shouldn't expect the namespace always exists. Using
2379 is global. So we shouldn't expect the namespace always exists. Using
2335 ssh:// makes sure a bundle repository is created from scratch. (issue6301)
2380 ssh:// makes sure a bundle repository is created from scratch. (issue6301)
2336
2381
2337 $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" \
2382 $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" \
2338 > -qr0 "ssh://user@dummy/`pwd`/a" a-clone
2383 > -qr0 "ssh://user@dummy/`pwd`/a" a-clone
2339 $ hg incoming --config extensions.names=names.py -R a-clone \
2384 $ hg incoming --config extensions.names=names.py -R a-clone \
2340 > -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" -T '{bars}\n' -l1
2385 > -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" -T '{bars}\n' -l1
2341 comparing with ssh://user@dummy/$TESTTMP/a
2386 comparing with ssh://user@dummy/$TESTTMP/a
2342 searching for changes
2387 searching for changes
2343
2388
2344
2389
2345 hg log -f dir across branches
2390 hg log -f dir across branches
2346
2391
2347 $ hg init acrossbranches
2392 $ hg init acrossbranches
2348 $ cd acrossbranches
2393 $ cd acrossbranches
2349 $ mkdir d
2394 $ mkdir d
2350 $ echo a > d/a && hg ci -Aqm a
2395 $ echo a > d/a && hg ci -Aqm a
2351 $ echo b > d/a && hg ci -Aqm b
2396 $ echo b > d/a && hg ci -Aqm b
2352 $ hg up -q 0
2397 $ hg up -q 0
2353 $ echo b > d/a && hg ci -Aqm c
2398 $ echo b > d/a && hg ci -Aqm c
2354 $ hg log -f d -T '{desc}' -G
2399 $ hg log -f d -T '{desc}' -G
2355 @ c
2400 @ c
2356 |
2401 |
2357 o a
2402 o a
2358
2403
2359 Ensure that largefiles doesn't interfere with following a normal file
2404 Ensure that largefiles doesn't interfere with following a normal file
2360 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
2405 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
2361 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
2406 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
2362 @ c
2407 @ c
2363 |
2408 |
2364 o a
2409 o a
2365
2410
2366 $ hg log -f d/a -T '{desc}' -G
2411 $ hg log -f d/a -T '{desc}' -G
2367 @ c
2412 @ c
2368 |
2413 |
2369 o a
2414 o a
2370
2415
2371 $ cd ..
2416 $ cd ..
2372
2417
2373 hg log -f with linkrev pointing to another branch
2418 hg log -f with linkrev pointing to another branch
2374 -------------------------------------------------
2419 -------------------------------------------------
2375
2420
2376 create history with a filerev whose linkrev points to another branch
2421 create history with a filerev whose linkrev points to another branch
2377
2422
2378 $ hg init branchedlinkrev
2423 $ hg init branchedlinkrev
2379 $ cd branchedlinkrev
2424 $ cd branchedlinkrev
2380 $ echo 1 > a
2425 $ echo 1 > a
2381 $ hg commit -Am 'content1'
2426 $ hg commit -Am 'content1'
2382 adding a
2427 adding a
2383 $ echo 2 > a
2428 $ echo 2 > a
2384 $ hg commit -m 'content2'
2429 $ hg commit -m 'content2'
2385 $ hg up --rev 'desc(content1)'
2430 $ hg up --rev 'desc(content1)'
2386 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2387 $ echo unrelated > unrelated
2432 $ echo unrelated > unrelated
2388 $ hg commit -Am 'unrelated'
2433 $ hg commit -Am 'unrelated'
2389 adding unrelated
2434 adding unrelated
2390 created new head
2435 created new head
2391 $ hg graft -r 'desc(content2)'
2436 $ hg graft -r 'desc(content2)'
2392 grafting 1:2294ae80ad84 "content2"
2437 grafting 1:2294ae80ad84 "content2"
2393 $ echo 3 > a
2438 $ echo 3 > a
2394 $ hg commit -m 'content3'
2439 $ hg commit -m 'content3'
2395 $ hg log -G
2440 $ hg log -G
2396 @ changeset: 4:50b9b36e9c5d
2441 @ changeset: 4:50b9b36e9c5d
2397 | tag: tip
2442 | tag: tip
2398 | user: test
2443 | user: test
2399 | date: Thu Jan 01 00:00:00 1970 +0000
2444 | date: Thu Jan 01 00:00:00 1970 +0000
2400 | summary: content3
2445 | summary: content3
2401 |
2446 |
2402 o changeset: 3:15b2327059e5
2447 o changeset: 3:15b2327059e5
2403 | user: test
2448 | user: test
2404 | date: Thu Jan 01 00:00:00 1970 +0000
2449 | date: Thu Jan 01 00:00:00 1970 +0000
2405 | summary: content2
2450 | summary: content2
2406 |
2451 |
2407 o changeset: 2:2029acd1168c
2452 o changeset: 2:2029acd1168c
2408 | parent: 0:ae0a3c9f9e95
2453 | parent: 0:ae0a3c9f9e95
2409 | user: test
2454 | user: test
2410 | date: Thu Jan 01 00:00:00 1970 +0000
2455 | date: Thu Jan 01 00:00:00 1970 +0000
2411 | summary: unrelated
2456 | summary: unrelated
2412 |
2457 |
2413 | o changeset: 1:2294ae80ad84
2458 | o changeset: 1:2294ae80ad84
2414 |/ user: test
2459 |/ user: test
2415 | date: Thu Jan 01 00:00:00 1970 +0000
2460 | date: Thu Jan 01 00:00:00 1970 +0000
2416 | summary: content2
2461 | summary: content2
2417 |
2462 |
2418 o changeset: 0:ae0a3c9f9e95
2463 o changeset: 0:ae0a3c9f9e95
2419 user: test
2464 user: test
2420 date: Thu Jan 01 00:00:00 1970 +0000
2465 date: Thu Jan 01 00:00:00 1970 +0000
2421 summary: content1
2466 summary: content1
2422
2467
2423
2468
2424 log -f on the file should list the graft result.
2469 log -f on the file should list the graft result.
2425
2470
2426 $ hg log -Gf a
2471 $ hg log -Gf a
2427 @ changeset: 4:50b9b36e9c5d
2472 @ changeset: 4:50b9b36e9c5d
2428 | tag: tip
2473 | tag: tip
2429 | user: test
2474 | user: test
2430 | date: Thu Jan 01 00:00:00 1970 +0000
2475 | date: Thu Jan 01 00:00:00 1970 +0000
2431 | summary: content3
2476 | summary: content3
2432 |
2477 |
2433 o changeset: 3:15b2327059e5
2478 o changeset: 3:15b2327059e5
2434 : user: test
2479 : user: test
2435 : date: Thu Jan 01 00:00:00 1970 +0000
2480 : date: Thu Jan 01 00:00:00 1970 +0000
2436 : summary: content2
2481 : summary: content2
2437 :
2482 :
2438 o changeset: 0:ae0a3c9f9e95
2483 o changeset: 0:ae0a3c9f9e95
2439 user: test
2484 user: test
2440 date: Thu Jan 01 00:00:00 1970 +0000
2485 date: Thu Jan 01 00:00:00 1970 +0000
2441 summary: content1
2486 summary: content1
2442
2487
2443
2488
2444 plain log lists the original version
2489 plain log lists the original version
2445 (XXX we should probably list both)
2490 (XXX we should probably list both)
2446
2491
2447 $ hg log -G a
2492 $ hg log -G a
2448 @ changeset: 4:50b9b36e9c5d
2493 @ changeset: 4:50b9b36e9c5d
2449 : tag: tip
2494 : tag: tip
2450 : user: test
2495 : user: test
2451 : date: Thu Jan 01 00:00:00 1970 +0000
2496 : date: Thu Jan 01 00:00:00 1970 +0000
2452 : summary: content3
2497 : summary: content3
2453 :
2498 :
2454 : o changeset: 1:2294ae80ad84
2499 : o changeset: 1:2294ae80ad84
2455 :/ user: test
2500 :/ user: test
2456 : date: Thu Jan 01 00:00:00 1970 +0000
2501 : date: Thu Jan 01 00:00:00 1970 +0000
2457 : summary: content2
2502 : summary: content2
2458 :
2503 :
2459 o changeset: 0:ae0a3c9f9e95
2504 o changeset: 0:ae0a3c9f9e95
2460 user: test
2505 user: test
2461 date: Thu Jan 01 00:00:00 1970 +0000
2506 date: Thu Jan 01 00:00:00 1970 +0000
2462 summary: content1
2507 summary: content1
2463
2508
2464
2509
2465 hg log -f from the grafted changeset
2510 hg log -f from the grafted changeset
2466 (The bootstrap should properly take the topology in account)
2511 (The bootstrap should properly take the topology in account)
2467
2512
2468 $ hg up 'desc(content3)^'
2513 $ hg up 'desc(content3)^'
2469 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2514 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2470 $ hg log -Gf a
2515 $ hg log -Gf a
2471 @ changeset: 3:15b2327059e5
2516 @ changeset: 3:15b2327059e5
2472 : user: test
2517 : user: test
2473 : date: Thu Jan 01 00:00:00 1970 +0000
2518 : date: Thu Jan 01 00:00:00 1970 +0000
2474 : summary: content2
2519 : summary: content2
2475 :
2520 :
2476 o changeset: 0:ae0a3c9f9e95
2521 o changeset: 0:ae0a3c9f9e95
2477 user: test
2522 user: test
2478 date: Thu Jan 01 00:00:00 1970 +0000
2523 date: Thu Jan 01 00:00:00 1970 +0000
2479 summary: content1
2524 summary: content1
2480
2525
2481
2526
2482 Test that we use the first non-hidden changeset in that case.
2527 Test that we use the first non-hidden changeset in that case.
2483
2528
2484 (hide the changeset)
2529 (hide the changeset)
2485
2530
2486 $ hg log -T '{node}\n' -r 1
2531 $ hg log -T '{node}\n' -r 1
2487 2294ae80ad8447bc78383182eeac50cb049df623
2532 2294ae80ad8447bc78383182eeac50cb049df623
2488 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
2533 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
2489 1 new obsolescence markers
2534 1 new obsolescence markers
2490 obsoleted 1 changesets
2535 obsoleted 1 changesets
2491 $ hg log -G
2536 $ hg log -G
2492 o changeset: 4:50b9b36e9c5d
2537 o changeset: 4:50b9b36e9c5d
2493 | tag: tip
2538 | tag: tip
2494 | user: test
2539 | user: test
2495 | date: Thu Jan 01 00:00:00 1970 +0000
2540 | date: Thu Jan 01 00:00:00 1970 +0000
2496 | summary: content3
2541 | summary: content3
2497 |
2542 |
2498 @ changeset: 3:15b2327059e5
2543 @ changeset: 3:15b2327059e5
2499 | user: test
2544 | user: test
2500 | date: Thu Jan 01 00:00:00 1970 +0000
2545 | date: Thu Jan 01 00:00:00 1970 +0000
2501 | summary: content2
2546 | summary: content2
2502 |
2547 |
2503 o changeset: 2:2029acd1168c
2548 o changeset: 2:2029acd1168c
2504 | parent: 0:ae0a3c9f9e95
2549 | parent: 0:ae0a3c9f9e95
2505 | user: test
2550 | user: test
2506 | date: Thu Jan 01 00:00:00 1970 +0000
2551 | date: Thu Jan 01 00:00:00 1970 +0000
2507 | summary: unrelated
2552 | summary: unrelated
2508 |
2553 |
2509 o changeset: 0:ae0a3c9f9e95
2554 o changeset: 0:ae0a3c9f9e95
2510 user: test
2555 user: test
2511 date: Thu Jan 01 00:00:00 1970 +0000
2556 date: Thu Jan 01 00:00:00 1970 +0000
2512 summary: content1
2557 summary: content1
2513
2558
2514
2559
2515 Check that log on the file does not drop the file revision.
2560 Check that log on the file does not drop the file revision.
2516
2561
2517 $ hg log -G a
2562 $ hg log -G a
2518 o changeset: 4:50b9b36e9c5d
2563 o changeset: 4:50b9b36e9c5d
2519 | tag: tip
2564 | tag: tip
2520 | user: test
2565 | user: test
2521 | date: Thu Jan 01 00:00:00 1970 +0000
2566 | date: Thu Jan 01 00:00:00 1970 +0000
2522 | summary: content3
2567 | summary: content3
2523 |
2568 |
2524 @ changeset: 3:15b2327059e5
2569 @ changeset: 3:15b2327059e5
2525 : user: test
2570 : user: test
2526 : date: Thu Jan 01 00:00:00 1970 +0000
2571 : date: Thu Jan 01 00:00:00 1970 +0000
2527 : summary: content2
2572 : summary: content2
2528 :
2573 :
2529 o changeset: 0:ae0a3c9f9e95
2574 o changeset: 0:ae0a3c9f9e95
2530 user: test
2575 user: test
2531 date: Thu Jan 01 00:00:00 1970 +0000
2576 date: Thu Jan 01 00:00:00 1970 +0000
2532 summary: content1
2577 summary: content1
2533
2578
2534
2579
2535 Even when a head revision is linkrev-shadowed.
2580 Even when a head revision is linkrev-shadowed.
2536
2581
2537 $ hg log -T '{node}\n' -r 4
2582 $ hg log -T '{node}\n' -r 4
2538 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2583 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2539 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2584 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2540 1 new obsolescence markers
2585 1 new obsolescence markers
2541 obsoleted 1 changesets
2586 obsoleted 1 changesets
2542 $ hg log -G a
2587 $ hg log -G a
2543 @ changeset: 3:15b2327059e5
2588 @ changeset: 3:15b2327059e5
2544 : tag: tip
2589 : tag: tip
2545 : user: test
2590 : user: test
2546 : date: Thu Jan 01 00:00:00 1970 +0000
2591 : date: Thu Jan 01 00:00:00 1970 +0000
2547 : summary: content2
2592 : summary: content2
2548 :
2593 :
2549 o changeset: 0:ae0a3c9f9e95
2594 o changeset: 0:ae0a3c9f9e95
2550 user: test
2595 user: test
2551 date: Thu Jan 01 00:00:00 1970 +0000
2596 date: Thu Jan 01 00:00:00 1970 +0000
2552 summary: content1
2597 summary: content1
2553
2598
2554
2599
2555 $ cd ..
2600 $ cd ..
2556
2601
2557 Even when the file revision is missing from some head:
2602 Even when the file revision is missing from some head:
2558
2603
2559 $ hg init issue4490
2604 $ hg init issue4490
2560 $ cd issue4490
2605 $ cd issue4490
2561 $ echo '[experimental]' >> .hg/hgrc
2606 $ echo '[experimental]' >> .hg/hgrc
2562 $ echo 'evolution.createmarkers=True' >> .hg/hgrc
2607 $ echo 'evolution.createmarkers=True' >> .hg/hgrc
2563 $ echo a > a
2608 $ echo a > a
2564 $ hg ci -Am0
2609 $ hg ci -Am0
2565 adding a
2610 adding a
2566 $ echo b > b
2611 $ echo b > b
2567 $ hg ci -Am1
2612 $ hg ci -Am1
2568 adding b
2613 adding b
2569 $ echo B > b
2614 $ echo B > b
2570 $ hg ci --amend -m 1
2615 $ hg ci --amend -m 1
2571 $ hg up 0
2616 $ hg up 0
2572 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2617 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2573 $ echo c > c
2618 $ echo c > c
2574 $ hg ci -Am2
2619 $ hg ci -Am2
2575 adding c
2620 adding c
2576 created new head
2621 created new head
2577 $ hg up 'head() and not .'
2622 $ hg up 'head() and not .'
2578 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2623 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2579 $ hg log -G
2624 $ hg log -G
2580 o changeset: 3:db815d6d32e6
2625 o changeset: 3:db815d6d32e6
2581 | tag: tip
2626 | tag: tip
2582 | parent: 0:f7b1eb17ad24
2627 | parent: 0:f7b1eb17ad24
2583 | user: test
2628 | user: test
2584 | date: Thu Jan 01 00:00:00 1970 +0000
2629 | date: Thu Jan 01 00:00:00 1970 +0000
2585 | summary: 2
2630 | summary: 2
2586 |
2631 |
2587 | @ changeset: 2:9bc8ce7f9356
2632 | @ changeset: 2:9bc8ce7f9356
2588 |/ parent: 0:f7b1eb17ad24
2633 |/ parent: 0:f7b1eb17ad24
2589 | user: test
2634 | user: test
2590 | date: Thu Jan 01 00:00:00 1970 +0000
2635 | date: Thu Jan 01 00:00:00 1970 +0000
2591 | summary: 1
2636 | summary: 1
2592 |
2637 |
2593 o changeset: 0:f7b1eb17ad24
2638 o changeset: 0:f7b1eb17ad24
2594 user: test
2639 user: test
2595 date: Thu Jan 01 00:00:00 1970 +0000
2640 date: Thu Jan 01 00:00:00 1970 +0000
2596 summary: 0
2641 summary: 0
2597
2642
2598 $ hg log -f -G b
2643 $ hg log -f -G b
2599 @ changeset: 2:9bc8ce7f9356
2644 @ changeset: 2:9bc8ce7f9356
2600 | parent: 0:f7b1eb17ad24
2645 | parent: 0:f7b1eb17ad24
2601 ~ user: test
2646 ~ user: test
2602 date: Thu Jan 01 00:00:00 1970 +0000
2647 date: Thu Jan 01 00:00:00 1970 +0000
2603 summary: 1
2648 summary: 1
2604
2649
2605 $ hg log -G b
2650 $ hg log -G b
2606 @ changeset: 2:9bc8ce7f9356
2651 @ changeset: 2:9bc8ce7f9356
2607 | parent: 0:f7b1eb17ad24
2652 | parent: 0:f7b1eb17ad24
2608 ~ user: test
2653 ~ user: test
2609 date: Thu Jan 01 00:00:00 1970 +0000
2654 date: Thu Jan 01 00:00:00 1970 +0000
2610 summary: 1
2655 summary: 1
2611
2656
2612 $ cd ..
2657 $ cd ..
2613
2658
2614 Check proper report when the manifest changes but not the file issue4499
2659 Check proper report when the manifest changes but not the file issue4499
2615 ------------------------------------------------------------------------
2660 ------------------------------------------------------------------------
2616
2661
2617 $ hg init issue4499
2662 $ hg init issue4499
2618 $ cd issue4499
2663 $ cd issue4499
2619 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
2664 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
2620 > echo 1 > $f;
2665 > echo 1 > $f;
2621 > hg add $f;
2666 > hg add $f;
2622 > done
2667 > done
2623 $ hg commit -m 'A1B1C1'
2668 $ hg commit -m 'A1B1C1'
2624 $ echo 2 > A
2669 $ echo 2 > A
2625 $ echo 2 > B
2670 $ echo 2 > B
2626 $ echo 2 > C
2671 $ echo 2 > C
2627 $ hg commit -m 'A2B2C2'
2672 $ hg commit -m 'A2B2C2'
2628 $ hg up 0
2673 $ hg up 0
2629 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2674 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2630 $ echo 3 > A
2675 $ echo 3 > A
2631 $ echo 2 > B
2676 $ echo 2 > B
2632 $ echo 2 > C
2677 $ echo 2 > C
2633 $ hg commit -m 'A3B2C2'
2678 $ hg commit -m 'A3B2C2'
2634 created new head
2679 created new head
2635
2680
2636 $ hg log -G
2681 $ hg log -G
2637 @ changeset: 2:fe5fc3d0eb17
2682 @ changeset: 2:fe5fc3d0eb17
2638 | tag: tip
2683 | tag: tip
2639 | parent: 0:abf4f0e38563
2684 | parent: 0:abf4f0e38563
2640 | user: test
2685 | user: test
2641 | date: Thu Jan 01 00:00:00 1970 +0000
2686 | date: Thu Jan 01 00:00:00 1970 +0000
2642 | summary: A3B2C2
2687 | summary: A3B2C2
2643 |
2688 |
2644 | o changeset: 1:07dcc6b312c0
2689 | o changeset: 1:07dcc6b312c0
2645 |/ user: test
2690 |/ user: test
2646 | date: Thu Jan 01 00:00:00 1970 +0000
2691 | date: Thu Jan 01 00:00:00 1970 +0000
2647 | summary: A2B2C2
2692 | summary: A2B2C2
2648 |
2693 |
2649 o changeset: 0:abf4f0e38563
2694 o changeset: 0:abf4f0e38563
2650 user: test
2695 user: test
2651 date: Thu Jan 01 00:00:00 1970 +0000
2696 date: Thu Jan 01 00:00:00 1970 +0000
2652 summary: A1B1C1
2697 summary: A1B1C1
2653
2698
2654
2699
2655 Log -f on B should reports current changesets
2700 Log -f on B should reports current changesets
2656
2701
2657 $ hg log -fG B
2702 $ hg log -fG B
2658 @ changeset: 2:fe5fc3d0eb17
2703 @ changeset: 2:fe5fc3d0eb17
2659 | tag: tip
2704 | tag: tip
2660 | parent: 0:abf4f0e38563
2705 | parent: 0:abf4f0e38563
2661 | user: test
2706 | user: test
2662 | date: Thu Jan 01 00:00:00 1970 +0000
2707 | date: Thu Jan 01 00:00:00 1970 +0000
2663 | summary: A3B2C2
2708 | summary: A3B2C2
2664 |
2709 |
2665 o changeset: 0:abf4f0e38563
2710 o changeset: 0:abf4f0e38563
2666 user: test
2711 user: test
2667 date: Thu Jan 01 00:00:00 1970 +0000
2712 date: Thu Jan 01 00:00:00 1970 +0000
2668 summary: A1B1C1
2713 summary: A1B1C1
2669
2714
2670 $ cd ..
2715 $ cd ..
2671
2716
2672 --- going to test line wrap fix on using both --stat and -G (issue5800)
2717 --- going to test line wrap fix on using both --stat and -G (issue5800)
2673 $ hg init issue5800
2718 $ hg init issue5800
2674 $ cd issue5800
2719 $ cd issue5800
2675 $ touch a
2720 $ touch a
2676 $ hg ci -Am 'add a'
2721 $ hg ci -Am 'add a'
2677 adding a
2722 adding a
2678 ---- now we are going to add 300 lines to a
2723 ---- now we are going to add 300 lines to a
2679 $ for i in `$TESTDIR/seq.py 1 300`; do echo $i >> a; done
2724 $ for i in `$TESTDIR/seq.py 1 300`; do echo $i >> a; done
2680 $ hg ci -m 'modify a'
2725 $ hg ci -m 'modify a'
2681 $ hg log
2726 $ hg log
2682 changeset: 1:a98683e6a834
2727 changeset: 1:a98683e6a834
2683 tag: tip
2728 tag: tip
2684 user: test
2729 user: test
2685 date: Thu Jan 01 00:00:00 1970 +0000
2730 date: Thu Jan 01 00:00:00 1970 +0000
2686 summary: modify a
2731 summary: modify a
2687
2732
2688 changeset: 0:ac82d8b1f7c4
2733 changeset: 0:ac82d8b1f7c4
2689 user: test
2734 user: test
2690 date: Thu Jan 01 00:00:00 1970 +0000
2735 date: Thu Jan 01 00:00:00 1970 +0000
2691 summary: add a
2736 summary: add a
2692
2737
2693 ---- now visualise the changes we made without template
2738 ---- now visualise the changes we made without template
2694 $ hg log -l1 -r a98683e6a834 --stat -G
2739 $ hg log -l1 -r a98683e6a834 --stat -G
2695 @ changeset: 1:a98683e6a834
2740 @ changeset: 1:a98683e6a834
2696 | tag: tip
2741 | tag: tip
2697 ~ user: test
2742 ~ user: test
2698 date: Thu Jan 01 00:00:00 1970 +0000
2743 date: Thu Jan 01 00:00:00 1970 +0000
2699 summary: modify a
2744 summary: modify a
2700
2745
2701 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2746 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2702 1 files changed, 300 insertions(+), 0 deletions(-)
2747 1 files changed, 300 insertions(+), 0 deletions(-)
2703
2748
2704 ---- with template
2749 ---- with template
2705 $ hg log -l1 -r a98683e6a834 --stat -G -T bisect
2750 $ hg log -l1 -r a98683e6a834 --stat -G -T bisect
2706 @ changeset: 1:a98683e6a834
2751 @ changeset: 1:a98683e6a834
2707 | bisect:
2752 | bisect:
2708 ~ tag: tip
2753 ~ tag: tip
2709 user: test
2754 user: test
2710 date: Thu Jan 01 00:00:00 1970 +0000
2755 date: Thu Jan 01 00:00:00 1970 +0000
2711 summary: modify a
2756 summary: modify a
2712
2757
2713 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2758 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2714 1 files changed, 300 insertions(+), 0 deletions(-)
2759 1 files changed, 300 insertions(+), 0 deletions(-)
2715
2760
2716 $ hg log -l1 -r a98683e6a834 --stat -G -T changelog
2761 $ hg log -l1 -r a98683e6a834 --stat -G -T changelog
2717 1970-01-01 test <test>
2762 1970-01-01 test <test>
2718
2763
2719 @ * a:
2764 @ * a:
2720 | modify a
2765 | modify a
2721 ~ [a98683e6a834] [tip]
2766 ~ [a98683e6a834] [tip]
2722
2767
2723 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2768 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2724 1 files changed, 300 insertions(+), 0 deletions(-)
2769 1 files changed, 300 insertions(+), 0 deletions(-)
2725
2770
2726 $ hg log -l1 -r a98683e6a834 --stat -G -T compact
2771 $ hg log -l1 -r a98683e6a834 --stat -G -T compact
2727 @ 1[tip] a98683e6a834 1970-01-01 00:00 +0000 test
2772 @ 1[tip] a98683e6a834 1970-01-01 00:00 +0000 test
2728 | modify a
2773 | modify a
2729 ~
2774 ~
2730 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2775 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2731 1 files changed, 300 insertions(+), 0 deletions(-)
2776 1 files changed, 300 insertions(+), 0 deletions(-)
2732
2777
2733 $ hg log -l1 -r a98683e6a834 --stat -G -T default
2778 $ hg log -l1 -r a98683e6a834 --stat -G -T default
2734 @ changeset: 1:a98683e6a834
2779 @ changeset: 1:a98683e6a834
2735 | tag: tip
2780 | tag: tip
2736 ~ user: test
2781 ~ user: test
2737 date: Thu Jan 01 00:00:00 1970 +0000
2782 date: Thu Jan 01 00:00:00 1970 +0000
2738 summary: modify a
2783 summary: modify a
2739
2784
2740 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2785 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2741 1 files changed, 300 insertions(+), 0 deletions(-)
2786 1 files changed, 300 insertions(+), 0 deletions(-)
2742
2787
2743 $ hg log -l1 -r a98683e6a834 --stat -G -T phases
2788 $ hg log -l1 -r a98683e6a834 --stat -G -T phases
2744 @ changeset: 1:a98683e6a834
2789 @ changeset: 1:a98683e6a834
2745 | tag: tip
2790 | tag: tip
2746 ~ phase: draft
2791 ~ phase: draft
2747 user: test
2792 user: test
2748 date: Thu Jan 01 00:00:00 1970 +0000
2793 date: Thu Jan 01 00:00:00 1970 +0000
2749 summary: modify a
2794 summary: modify a
2750
2795
2751 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2796 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2752 1 files changed, 300 insertions(+), 0 deletions(-)
2797 1 files changed, 300 insertions(+), 0 deletions(-)
2753
2798
2754 $ hg log -l1 -r a98683e6a834 --stat -G -T show
2799 $ hg log -l1 -r a98683e6a834 --stat -G -T show
2755 @ changeset: 1:a98683e6a834
2800 @ changeset: 1:a98683e6a834
2756 | tag: tip
2801 | tag: tip
2757 ~ user: test
2802 ~ user: test
2758 date: Thu Jan 01 00:00:00 1970 +0000
2803 date: Thu Jan 01 00:00:00 1970 +0000
2759 summary: modify a
2804 summary: modify a
2760
2805
2761 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2806 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2762 1 files changed, 300 insertions(+), 0 deletions(-)
2807 1 files changed, 300 insertions(+), 0 deletions(-)
2763
2808
2764 $ hg log -l1 -r a98683e6a834 --stat -G -T status
2809 $ hg log -l1 -r a98683e6a834 --stat -G -T status
2765 @ changeset: 1:a98683e6a834
2810 @ changeset: 1:a98683e6a834
2766 | tag: tip
2811 | tag: tip
2767 ~ user: test
2812 ~ user: test
2768 date: Thu Jan 01 00:00:00 1970 +0000
2813 date: Thu Jan 01 00:00:00 1970 +0000
2769 summary: modify a
2814 summary: modify a
2770 files:
2815 files:
2771 M a
2816 M a
2772
2817
2773 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2818 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2774 1 files changed, 300 insertions(+), 0 deletions(-)
2819 1 files changed, 300 insertions(+), 0 deletions(-)
2775
2820
2776 $ hg log -l1 -r a98683e6a834 --stat -G -T xml
2821 $ hg log -l1 -r a98683e6a834 --stat -G -T xml
2777 <?xml version="1.0"?>
2822 <?xml version="1.0"?>
2778 <log>
2823 <log>
2779 @ <logentry revision="1" node="a98683e6a8340830a7683909768b62871e84bc9d">
2824 @ <logentry revision="1" node="a98683e6a8340830a7683909768b62871e84bc9d">
2780 | <tag>tip</tag>
2825 | <tag>tip</tag>
2781 ~ <author email="test">test</author>
2826 ~ <author email="test">test</author>
2782 <date>1970-01-01T00:00:00+00:00</date>
2827 <date>1970-01-01T00:00:00+00:00</date>
2783 <msg xml:space="preserve">modify a</msg>
2828 <msg xml:space="preserve">modify a</msg>
2784 </logentry>
2829 </logentry>
2785 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2830 a | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2786 1 files changed, 300 insertions(+), 0 deletions(-)
2831 1 files changed, 300 insertions(+), 0 deletions(-)
2787
2832
2788 </log>
2833 </log>
2789
2834
2790 $ cd ..
2835 $ cd ..
@@ -1,157 +1,181 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > rebase=
3 > rebase=
4 >
4 >
5 > [phases]
5 > [phases]
6 > publish=False
6 > publish=False
7 >
7 >
8 > [alias]
8 > [alias]
9 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
9 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
10 > EOF
10 > EOF
11
11
12
12
13 $ hg init a
13 $ hg init a
14 $ cd a
14 $ cd a
15
15
16 $ echo A > A
16 $ echo A > A
17 $ hg add A
17 $ hg add A
18 $ hg ci -m A
18 $ hg ci -m A
19
19
20 $ echo 'B' > B
20 $ echo 'B' > B
21 $ hg add B
21 $ hg add B
22 $ hg ci -m B
22 $ hg ci -m B
23
23
24 $ echo C >> A
24 $ echo C >> A
25 $ hg ci -m C
25 $ hg ci -m C
26
26
27 $ hg up -q -C 0
27 $ hg up -q -C 0
28
28
29 $ echo D >> A
29 $ echo D >> A
30 $ hg ci -m D
30 $ hg ci -m D
31 created new head
31 created new head
32
32
33 $ echo E > E
33 $ echo E > E
34 $ hg add E
34 $ hg add E
35 $ hg ci -m E
35 $ hg ci -m E
36
36
37 $ hg up -q -C 0
37 $ hg up -q -C 0
38
38
39 $ hg branch 'notdefault'
39 $ hg branch 'notdefault'
40 marked working directory as branch notdefault
40 marked working directory as branch notdefault
41 (branches are permanent and global, did you want a bookmark?)
41 (branches are permanent and global, did you want a bookmark?)
42 $ echo F >> A
42 $ echo F >> A
43 $ hg ci -m F
43 $ hg ci -m F
44
44
45 $ cd ..
45 $ cd ..
46
46
47
47
48 Rebasing B onto E - check keep: and phases
48 Rebasing B onto E - check keep: and phases
49
49
50 $ hg clone -q -u . a a1
50 $ hg clone -q -u . a a1
51 $ cd a1
51 $ cd a1
52 $ hg phase --force --secret 2
52 $ hg phase --force --secret 2
53
53
54 $ hg tglog
54 $ hg tglog
55 @ 5:draft 'F' notdefault
55 @ 5:draft 'F' notdefault
56 |
56 |
57 | o 4:draft 'E'
57 | o 4:draft 'E'
58 | |
58 | |
59 | o 3:draft 'D'
59 | o 3:draft 'D'
60 |/
60 |/
61 | o 2:secret 'C'
61 | o 2:secret 'C'
62 | |
62 | |
63 | o 1:draft 'B'
63 | o 1:draft 'B'
64 |/
64 |/
65 o 0:draft 'A'
65 o 0:draft 'A'
66
66
67 $ hg rebase -s 1 -d 4 --keep
67 $ hg rebase -s 1 -d 4 --keep
68 rebasing 1:27547f69f254 "B"
68 rebasing 1:27547f69f254 "B"
69 rebasing 2:965c486023db "C"
69 rebasing 2:965c486023db "C"
70 merging A
70 merging A
71 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
71 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
72 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
72 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
73 [1]
73 [1]
74
74
75 Solve the conflict and go on:
75 Solve the conflict and go on:
76
76
77 $ echo 'conflict solved' > A
77 $ echo 'conflict solved' > A
78 $ rm A.orig
78 $ rm A.orig
79 $ hg resolve -m A
79 $ hg resolve -m A
80 (no more unresolved files)
80 (no more unresolved files)
81 continue: hg rebase --continue
81 continue: hg rebase --continue
82 $ hg rebase --continue
82 $ hg rebase --continue
83 already rebased 1:27547f69f254 "B" as 45396c49d53b
83 already rebased 1:27547f69f254 "B" as 45396c49d53b
84 rebasing 2:965c486023db "C"
84 rebasing 2:965c486023db "C"
85
85
86 $ hg tglog
86 $ hg tglog
87 o 7:secret 'C'
87 o 7:secret 'C'
88 |
88 |
89 o 6:draft 'B'
89 o 6:draft 'B'
90 |
90 |
91 | @ 5:draft 'F' notdefault
91 | @ 5:draft 'F' notdefault
92 | |
92 | |
93 o | 4:draft 'E'
93 o | 4:draft 'E'
94 | |
94 | |
95 o | 3:draft 'D'
95 o | 3:draft 'D'
96 |/
96 |/
97 | o 2:secret 'C'
97 | o 2:secret 'C'
98 | |
98 | |
99 | o 1:draft 'B'
99 | o 1:draft 'B'
100 |/
100 |/
101 o 0:draft 'A'
101 o 0:draft 'A'
102
102
103 $ cd ..
103 $ cd ..
104
104
105
105
106 Rebase F onto E - check keepbranches:
106 Rebase F onto E - check keepbranches:
107
107
108 $ hg clone -q -u . a a2
108 $ hg clone -q -u . a a2
109 $ cd a2
109 $ cd a2
110 $ hg phase --force --secret 2
110 $ hg phase --force --secret 2
111
111
112 $ hg tglog
112 $ hg tglog
113 @ 5:draft 'F' notdefault
113 @ 5:draft 'F' notdefault
114 |
114 |
115 | o 4:draft 'E'
115 | o 4:draft 'E'
116 | |
116 | |
117 | o 3:draft 'D'
117 | o 3:draft 'D'
118 |/
118 |/
119 | o 2:secret 'C'
119 | o 2:secret 'C'
120 | |
120 | |
121 | o 1:draft 'B'
121 | o 1:draft 'B'
122 |/
122 |/
123 o 0:draft 'A'
123 o 0:draft 'A'
124
124
125 $ hg rebase -s 5 -d 4 --keepbranches
125 $ hg rebase -s 5 -d 4 --keepbranches
126 rebasing 5:01e6ebbd8272 "F" (tip)
126 rebasing 5:01e6ebbd8272 "F" (tip)
127 merging A
127 merging A
128 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
128 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
129 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
129 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
130 [1]
130 [1]
131
131
132 Solve the conflict and go on:
132 Solve the conflict and go on:
133
133
134 $ echo 'conflict solved' > A
134 $ echo 'conflict solved' > A
135 $ rm A.orig
135 $ rm A.orig
136 $ hg resolve -m A
136 $ hg resolve -m A
137 (no more unresolved files)
137 (no more unresolved files)
138 continue: hg rebase --continue
138 continue: hg rebase --continue
139 $ hg rebase --continue
139 $ hg rebase --continue
140 rebasing 5:01e6ebbd8272 "F" (tip)
140 rebasing 5:01e6ebbd8272 "F" (tip)
141 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/01e6ebbd8272-6fd3a015-rebase.hg
141 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/01e6ebbd8272-6fd3a015-rebase.hg
142
142
143 $ hg tglog
143 $ hg tglog
144 @ 5:draft 'F' notdefault
144 @ 5:draft 'F' notdefault
145 |
145 |
146 o 4:draft 'E'
146 o 4:draft 'E'
147 |
147 |
148 o 3:draft 'D'
148 o 3:draft 'D'
149 |
149 |
150 | o 2:secret 'C'
150 | o 2:secret 'C'
151 | |
151 | |
152 | o 1:draft 'B'
152 | o 1:draft 'B'
153 |/
153 |/
154 o 0:draft 'A'
154 o 0:draft 'A'
155
155
156 $ cat >> .hg/hgrc << EOF
157 > [experimental]
158 > evolution.createmarkers=True
159 > EOF
160
161 When updating away from a dirty, obsolete wdir, don't complain that the old p1
162 is filtered and requires --hidden.
163
164 $ echo conflict > A
165 $ hg debugobsolete 071d07019675449d53b7e312c65bcf28adbbdb64 965c486023dbfdc9c32c52dc249a231882fd5c17
166 1 new obsolescence markers
167 obsoleted 1 changesets
168 $ hg update -r 2 --config ui.merge=internal:merge --merge
169 merging A
170 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
171 1 files updated, 0 files merged, 1 files removed, 1 files unresolved
172 use 'hg resolve' to retry unresolved file merges
173 [1]
174 $ hg resolve A
175 merging A
176 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
177 [1]
178
179 $ hg up -C -q .
156
180
157 $ cd ..
181 $ cd ..
@@ -1,2138 +1,2140 b''
1 ==========================
1 ==========================
2 Test rebase with obsolete
2 Test rebase with obsolete
3 ==========================
3 ==========================
4
4
5 Enable obsolete
5 Enable obsolete
6
6
7 $ cat >> $HGRCPATH << EOF
7 $ cat >> $HGRCPATH << EOF
8 > [ui]
8 > [ui]
9 > logtemplate= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')}
9 > logtemplate= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')}
10 > [experimental]
10 > [experimental]
11 > evolution.createmarkers=True
11 > evolution.createmarkers=True
12 > evolution.allowunstable=True
12 > evolution.allowunstable=True
13 > [phases]
13 > [phases]
14 > publish=False
14 > publish=False
15 > [extensions]
15 > [extensions]
16 > rebase=
16 > rebase=
17 > drawdag=$TESTDIR/drawdag.py
17 > drawdag=$TESTDIR/drawdag.py
18 > strip=
18 > strip=
19 > EOF
19 > EOF
20
20
21 Setup rebase canonical repo
21 Setup rebase canonical repo
22
22
23 $ hg init base
23 $ hg init base
24 $ cd base
24 $ cd base
25 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
25 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
26 adding changesets
26 adding changesets
27 adding manifests
27 adding manifests
28 adding file changes
28 adding file changes
29 added 8 changesets with 7 changes to 7 files (+2 heads)
29 added 8 changesets with 7 changes to 7 files (+2 heads)
30 new changesets cd010b8cd998:02de42196ebe (8 drafts)
30 new changesets cd010b8cd998:02de42196ebe (8 drafts)
31 (run 'hg heads' to see heads, 'hg merge' to merge)
31 (run 'hg heads' to see heads, 'hg merge' to merge)
32 $ hg up tip
32 $ hg up tip
33 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 $ hg log -G
34 $ hg log -G
35 @ 7:02de42196ebe H
35 @ 7:02de42196ebe H
36 |
36 |
37 | o 6:eea13746799a G
37 | o 6:eea13746799a G
38 |/|
38 |/|
39 o | 5:24b6387c8c8c F
39 o | 5:24b6387c8c8c F
40 | |
40 | |
41 | o 4:9520eea781bc E
41 | o 4:9520eea781bc E
42 |/
42 |/
43 | o 3:32af7686d403 D
43 | o 3:32af7686d403 D
44 | |
44 | |
45 | o 2:5fddd98957c8 C
45 | o 2:5fddd98957c8 C
46 | |
46 | |
47 | o 1:42ccdea3bb16 B
47 | o 1:42ccdea3bb16 B
48 |/
48 |/
49 o 0:cd010b8cd998 A
49 o 0:cd010b8cd998 A
50
50
51 $ cd ..
51 $ cd ..
52
52
53 simple rebase
53 simple rebase
54 ---------------------------------
54 ---------------------------------
55
55
56 $ hg clone base simple
56 $ hg clone base simple
57 updating to branch default
57 updating to branch default
58 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 $ cd simple
59 $ cd simple
60 $ hg up 32af7686d403
60 $ hg up 32af7686d403
61 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
61 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
62 $ hg rebase -d eea13746799a
62 $ hg rebase -d eea13746799a
63 rebasing 1:42ccdea3bb16 "B"
63 rebasing 1:42ccdea3bb16 "B"
64 rebasing 2:5fddd98957c8 "C"
64 rebasing 2:5fddd98957c8 "C"
65 rebasing 3:32af7686d403 "D"
65 rebasing 3:32af7686d403 "D"
66 $ hg log -G
66 $ hg log -G
67 @ 10:8eeb3c33ad33 D
67 @ 10:8eeb3c33ad33 D
68 |
68 |
69 o 9:2327fea05063 C
69 o 9:2327fea05063 C
70 |
70 |
71 o 8:e4e5be0395b2 B
71 o 8:e4e5be0395b2 B
72 |
72 |
73 | o 7:02de42196ebe H
73 | o 7:02de42196ebe H
74 | |
74 | |
75 o | 6:eea13746799a G
75 o | 6:eea13746799a G
76 |\|
76 |\|
77 | o 5:24b6387c8c8c F
77 | o 5:24b6387c8c8c F
78 | |
78 | |
79 o | 4:9520eea781bc E
79 o | 4:9520eea781bc E
80 |/
80 |/
81 o 0:cd010b8cd998 A
81 o 0:cd010b8cd998 A
82
82
83 $ hg log --hidden -G
83 $ hg log --hidden -G
84 @ 10:8eeb3c33ad33 D
84 @ 10:8eeb3c33ad33 D
85 |
85 |
86 o 9:2327fea05063 C
86 o 9:2327fea05063 C
87 |
87 |
88 o 8:e4e5be0395b2 B
88 o 8:e4e5be0395b2 B
89 |
89 |
90 | o 7:02de42196ebe H
90 | o 7:02de42196ebe H
91 | |
91 | |
92 o | 6:eea13746799a G
92 o | 6:eea13746799a G
93 |\|
93 |\|
94 | o 5:24b6387c8c8c F
94 | o 5:24b6387c8c8c F
95 | |
95 | |
96 o | 4:9520eea781bc E
96 o | 4:9520eea781bc E
97 |/
97 |/
98 | x 3:32af7686d403 D (rewritten using rebase as 10:8eeb3c33ad33)
98 | x 3:32af7686d403 D (rewritten using rebase as 10:8eeb3c33ad33)
99 | |
99 | |
100 | x 2:5fddd98957c8 C (rewritten using rebase as 9:2327fea05063)
100 | x 2:5fddd98957c8 C (rewritten using rebase as 9:2327fea05063)
101 | |
101 | |
102 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:e4e5be0395b2)
102 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:e4e5be0395b2)
103 |/
103 |/
104 o 0:cd010b8cd998 A
104 o 0:cd010b8cd998 A
105
105
106 $ hg debugobsolete
106 $ hg debugobsolete
107 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
107 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
108 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
108 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
109 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
109 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
110
110
111
111
112 $ cd ..
112 $ cd ..
113
113
114 empty changeset
114 empty changeset
115 ---------------------------------
115 ---------------------------------
116
116
117 $ hg clone base empty
117 $ hg clone base empty
118 updating to branch default
118 updating to branch default
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 $ cd empty
120 $ cd empty
121 $ hg up eea13746799a
121 $ hg up eea13746799a
122 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
122 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
123
123
124 We make a copy of both the first changeset in the rebased and some other in the
124 We make a copy of both the first changeset in the rebased and some other in the
125 set.
125 set.
126
126
127 $ hg graft 42ccdea3bb16 32af7686d403
127 $ hg graft 42ccdea3bb16 32af7686d403
128 grafting 1:42ccdea3bb16 "B"
128 grafting 1:42ccdea3bb16 "B"
129 grafting 3:32af7686d403 "D"
129 grafting 3:32af7686d403 "D"
130 $ hg rebase -s 42ccdea3bb16 -d .
130 $ hg rebase -s 42ccdea3bb16 -d .
131 rebasing 1:42ccdea3bb16 "B"
131 rebasing 1:42ccdea3bb16 "B"
132 note: not rebasing 1:42ccdea3bb16 "B", its destination already has all its changes
132 note: not rebasing 1:42ccdea3bb16 "B", its destination already has all its changes
133 rebasing 2:5fddd98957c8 "C"
133 rebasing 2:5fddd98957c8 "C"
134 rebasing 3:32af7686d403 "D"
134 rebasing 3:32af7686d403 "D"
135 note: not rebasing 3:32af7686d403 "D", its destination already has all its changes
135 note: not rebasing 3:32af7686d403 "D", its destination already has all its changes
136 $ hg log -G
136 $ hg log -G
137 o 10:5ae4c968c6ac C
137 o 10:5ae4c968c6ac C
138 |
138 |
139 @ 9:08483444fef9 D
139 @ 9:08483444fef9 D
140 |
140 |
141 o 8:8877864f1edb B
141 o 8:8877864f1edb B
142 |
142 |
143 | o 7:02de42196ebe H
143 | o 7:02de42196ebe H
144 | |
144 | |
145 o | 6:eea13746799a G
145 o | 6:eea13746799a G
146 |\|
146 |\|
147 | o 5:24b6387c8c8c F
147 | o 5:24b6387c8c8c F
148 | |
148 | |
149 o | 4:9520eea781bc E
149 o | 4:9520eea781bc E
150 |/
150 |/
151 o 0:cd010b8cd998 A
151 o 0:cd010b8cd998 A
152
152
153 $ hg log --hidden -G
153 $ hg log --hidden -G
154 o 10:5ae4c968c6ac C
154 o 10:5ae4c968c6ac C
155 |
155 |
156 @ 9:08483444fef9 D
156 @ 9:08483444fef9 D
157 |
157 |
158 o 8:8877864f1edb B
158 o 8:8877864f1edb B
159 |
159 |
160 | o 7:02de42196ebe H
160 | o 7:02de42196ebe H
161 | |
161 | |
162 o | 6:eea13746799a G
162 o | 6:eea13746799a G
163 |\|
163 |\|
164 | o 5:24b6387c8c8c F
164 | o 5:24b6387c8c8c F
165 | |
165 | |
166 o | 4:9520eea781bc E
166 o | 4:9520eea781bc E
167 |/
167 |/
168 | x 3:32af7686d403 D (pruned using rebase)
168 | x 3:32af7686d403 D (pruned using rebase)
169 | |
169 | |
170 | x 2:5fddd98957c8 C (rewritten using rebase as 10:5ae4c968c6ac)
170 | x 2:5fddd98957c8 C (rewritten using rebase as 10:5ae4c968c6ac)
171 | |
171 | |
172 | x 1:42ccdea3bb16 B (pruned using rebase)
172 | x 1:42ccdea3bb16 B (pruned using rebase)
173 |/
173 |/
174 o 0:cd010b8cd998 A
174 o 0:cd010b8cd998 A
175
175
176 $ hg debugobsolete
176 $ hg debugobsolete
177 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
177 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
178 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
178 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
179 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
179 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
180
180
181
181
182 More complex case where part of the rebase set were already rebased
182 More complex case where part of the rebase set were already rebased
183
183
184 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
184 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
185 rebasing 9:08483444fef9 "D"
185 rebasing 9:08483444fef9 "D"
186 1 new orphan changesets
186 1 new orphan changesets
187 $ hg debugobsolete
187 $ hg debugobsolete
188 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
188 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
189 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
189 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
190 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
190 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
191 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
191 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
192 $ hg log -G
192 $ hg log -G
193 @ 11:4596109a6a43 D
193 @ 11:4596109a6a43 D
194 |
194 |
195 | * 10:5ae4c968c6ac C
195 | * 10:5ae4c968c6ac C
196 | |
196 | |
197 | x 9:08483444fef9 D (rewritten using rebase as 11:4596109a6a43)
197 | x 9:08483444fef9 D (rewritten using rebase as 11:4596109a6a43)
198 | |
198 | |
199 | o 8:8877864f1edb B
199 | o 8:8877864f1edb B
200 | |
200 | |
201 o | 7:02de42196ebe H
201 o | 7:02de42196ebe H
202 | |
202 | |
203 | o 6:eea13746799a G
203 | o 6:eea13746799a G
204 |/|
204 |/|
205 o | 5:24b6387c8c8c F
205 o | 5:24b6387c8c8c F
206 | |
206 | |
207 | o 4:9520eea781bc E
207 | o 4:9520eea781bc E
208 |/
208 |/
209 o 0:cd010b8cd998 A
209 o 0:cd010b8cd998 A
210
210
211 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
211 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
212 rebasing 8:8877864f1edb "B"
212 rebasing 8:8877864f1edb "B"
213 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip)
213 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip)
214 rebasing 10:5ae4c968c6ac "C"
214 rebasing 10:5ae4c968c6ac "C"
215 $ hg debugobsolete
215 $ hg debugobsolete
216 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
216 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
217 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
217 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
218 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
218 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
219 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
219 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
220 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
220 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
221 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
221 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
222 $ hg log --rev 'contentdivergent()'
222 $ hg log --rev 'contentdivergent()'
223 $ hg log -G
223 $ hg log -G
224 o 13:98f6af4ee953 C
224 o 13:98f6af4ee953 C
225 |
225 |
226 o 12:462a34d07e59 B
226 o 12:462a34d07e59 B
227 |
227 |
228 @ 11:4596109a6a43 D
228 @ 11:4596109a6a43 D
229 |
229 |
230 o 7:02de42196ebe H
230 o 7:02de42196ebe H
231 |
231 |
232 | o 6:eea13746799a G
232 | o 6:eea13746799a G
233 |/|
233 |/|
234 o | 5:24b6387c8c8c F
234 o | 5:24b6387c8c8c F
235 | |
235 | |
236 | o 4:9520eea781bc E
236 | o 4:9520eea781bc E
237 |/
237 |/
238 o 0:cd010b8cd998 A
238 o 0:cd010b8cd998 A
239
239
240 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
240 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
241 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
241 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
242 phase: draft
242 phase: draft
243 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
243 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
244 parent: -1:0000000000000000000000000000000000000000
244 parent: -1:0000000000000000000000000000000000000000
245 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
245 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
246 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
246 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
247 date: Sat Apr 30 15:24:48 2011 +0200
247 date: Sat Apr 30 15:24:48 2011 +0200
248 files+: D
248 files+: D
249 extra: branch=default
249 extra: branch=default
250 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
250 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
251 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
251 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
252 description:
252 description:
253 D
253 D
254
254
255
255
256 $ hg up -qr 'desc(G)'
256 $ hg up -qr 'desc(G)'
257 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
257 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
258 grafting 11:4596109a6a43 "D"
258 grafting 11:4596109a6a43 "D"
259 $ hg up -qr 'desc(E)'
259 $ hg up -qr 'desc(E)'
260 $ hg rebase -s tip -d .
260 $ hg rebase -s tip -d .
261 rebasing 14:9e36056a46e3 "D" (tip)
261 rebasing 14:9e36056a46e3 "D" (tip)
262 $ hg log --style default --debug -r tip
262 $ hg log --style default --debug -r tip
263 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
263 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
264 tag: tip
264 tag: tip
265 phase: draft
265 phase: draft
266 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
266 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
267 parent: -1:0000000000000000000000000000000000000000
267 parent: -1:0000000000000000000000000000000000000000
268 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
268 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
269 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
269 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
270 date: Sat Apr 30 15:24:48 2011 +0200
270 date: Sat Apr 30 15:24:48 2011 +0200
271 files+: D
271 files+: D
272 extra: branch=default
272 extra: branch=default
273 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
273 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
274 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
274 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
275 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
275 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
276 description:
276 description:
277 D
277 D
278
278
279
279
280 Start rebase from a commit that is obsolete but not hidden only because it's
280 Start rebase from a commit that is obsolete but not hidden only because it's
281 a working copy parent. We should be moved back to the starting commit as usual
281 a working copy parent. We should be moved back to the starting commit as usual
282 even though it is hidden (until we're moved there).
282 even though it is hidden (until we're moved there).
283
283
284 $ hg --hidden up -qr 'first(hidden())'
284 $ hg --hidden up -qr 'first(hidden())'
285 updated to hidden changeset 42ccdea3bb16
285 updated to hidden changeset 42ccdea3bb16
286 (hidden revision '42ccdea3bb16' is pruned)
286 (hidden revision '42ccdea3bb16' is pruned)
287 $ hg rebase --rev 13 --dest 15
287 $ hg rebase --rev 13 --dest 15
288 rebasing 13:98f6af4ee953 "C"
288 rebasing 13:98f6af4ee953 "C"
289 $ hg log -G
289 $ hg log -G
290 o 16:294a2b93eb4d C
290 o 16:294a2b93eb4d C
291 |
291 |
292 o 15:627d46148090 D
292 o 15:627d46148090 D
293 |
293 |
294 | o 12:462a34d07e59 B
294 | o 12:462a34d07e59 B
295 | |
295 | |
296 | o 11:4596109a6a43 D
296 | o 11:4596109a6a43 D
297 | |
297 | |
298 | o 7:02de42196ebe H
298 | o 7:02de42196ebe H
299 | |
299 | |
300 +---o 6:eea13746799a G
300 +---o 6:eea13746799a G
301 | |/
301 | |/
302 | o 5:24b6387c8c8c F
302 | o 5:24b6387c8c8c F
303 | |
303 | |
304 o | 4:9520eea781bc E
304 o | 4:9520eea781bc E
305 |/
305 |/
306 | @ 1:42ccdea3bb16 B (pruned using rebase)
306 | @ 1:42ccdea3bb16 B (pruned using rebase)
307 |/
307 |/
308 o 0:cd010b8cd998 A
308 o 0:cd010b8cd998 A
309
309
310
310
311 $ cd ..
311 $ cd ..
312
312
313 collapse rebase
313 collapse rebase
314 ---------------------------------
314 ---------------------------------
315
315
316 $ hg clone base collapse
316 $ hg clone base collapse
317 updating to branch default
317 updating to branch default
318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 $ cd collapse
319 $ cd collapse
320 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
320 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
321 rebasing 1:42ccdea3bb16 "B"
321 rebasing 1:42ccdea3bb16 "B"
322 rebasing 2:5fddd98957c8 "C"
322 rebasing 2:5fddd98957c8 "C"
323 rebasing 3:32af7686d403 "D"
323 rebasing 3:32af7686d403 "D"
324 $ hg log -G
324 $ hg log -G
325 o 8:4dc2197e807b Collapsed revision
325 o 8:4dc2197e807b Collapsed revision
326 |
326 |
327 | @ 7:02de42196ebe H
327 | @ 7:02de42196ebe H
328 | |
328 | |
329 o | 6:eea13746799a G
329 o | 6:eea13746799a G
330 |\|
330 |\|
331 | o 5:24b6387c8c8c F
331 | o 5:24b6387c8c8c F
332 | |
332 | |
333 o | 4:9520eea781bc E
333 o | 4:9520eea781bc E
334 |/
334 |/
335 o 0:cd010b8cd998 A
335 o 0:cd010b8cd998 A
336
336
337 $ hg log --hidden -G
337 $ hg log --hidden -G
338 o 8:4dc2197e807b Collapsed revision
338 o 8:4dc2197e807b Collapsed revision
339 |
339 |
340 | @ 7:02de42196ebe H
340 | @ 7:02de42196ebe H
341 | |
341 | |
342 o | 6:eea13746799a G
342 o | 6:eea13746799a G
343 |\|
343 |\|
344 | o 5:24b6387c8c8c F
344 | o 5:24b6387c8c8c F
345 | |
345 | |
346 o | 4:9520eea781bc E
346 o | 4:9520eea781bc E
347 |/
347 |/
348 | x 3:32af7686d403 D (rewritten using rebase as 8:4dc2197e807b)
348 | x 3:32af7686d403 D (rewritten using rebase as 8:4dc2197e807b)
349 | |
349 | |
350 | x 2:5fddd98957c8 C (rewritten using rebase as 8:4dc2197e807b)
350 | x 2:5fddd98957c8 C (rewritten using rebase as 8:4dc2197e807b)
351 | |
351 | |
352 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:4dc2197e807b)
352 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:4dc2197e807b)
353 |/
353 |/
354 o 0:cd010b8cd998 A
354 o 0:cd010b8cd998 A
355
355
356 $ hg id --debug -r tip
356 $ hg id --debug -r tip
357 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
357 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
358 $ hg debugobsolete
358 $ hg debugobsolete
359 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '1', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
359 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '1', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
360 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '2', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
360 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '2', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
361 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '3', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
361 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '3', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
362
362
363 $ cd ..
363 $ cd ..
364
364
365 Rebase set has hidden descendants
365 Rebase set has hidden descendants
366 ---------------------------------
366 ---------------------------------
367
367
368 We rebase a changeset which has hidden descendants. Hidden changesets must not
368 We rebase a changeset which has hidden descendants. Hidden changesets must not
369 be rebased.
369 be rebased.
370
370
371 $ hg clone base hidden
371 $ hg clone base hidden
372 updating to branch default
372 updating to branch default
373 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
373 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 $ cd hidden
374 $ cd hidden
375 $ hg log -G
375 $ hg log -G
376 @ 7:02de42196ebe H
376 @ 7:02de42196ebe H
377 |
377 |
378 | o 6:eea13746799a G
378 | o 6:eea13746799a G
379 |/|
379 |/|
380 o | 5:24b6387c8c8c F
380 o | 5:24b6387c8c8c F
381 | |
381 | |
382 | o 4:9520eea781bc E
382 | o 4:9520eea781bc E
383 |/
383 |/
384 | o 3:32af7686d403 D
384 | o 3:32af7686d403 D
385 | |
385 | |
386 | o 2:5fddd98957c8 C
386 | o 2:5fddd98957c8 C
387 | |
387 | |
388 | o 1:42ccdea3bb16 B
388 | o 1:42ccdea3bb16 B
389 |/
389 |/
390 o 0:cd010b8cd998 A
390 o 0:cd010b8cd998 A
391
391
392 $ hg rebase -s 5fddd98957c8 -d eea13746799a
392 $ hg rebase -s 5fddd98957c8 -d eea13746799a
393 rebasing 2:5fddd98957c8 "C"
393 rebasing 2:5fddd98957c8 "C"
394 rebasing 3:32af7686d403 "D"
394 rebasing 3:32af7686d403 "D"
395 $ hg log -G
395 $ hg log -G
396 o 9:cf44d2f5a9f4 D
396 o 9:cf44d2f5a9f4 D
397 |
397 |
398 o 8:e273c5e7d2d2 C
398 o 8:e273c5e7d2d2 C
399 |
399 |
400 | @ 7:02de42196ebe H
400 | @ 7:02de42196ebe H
401 | |
401 | |
402 o | 6:eea13746799a G
402 o | 6:eea13746799a G
403 |\|
403 |\|
404 | o 5:24b6387c8c8c F
404 | o 5:24b6387c8c8c F
405 | |
405 | |
406 o | 4:9520eea781bc E
406 o | 4:9520eea781bc E
407 |/
407 |/
408 | o 1:42ccdea3bb16 B
408 | o 1:42ccdea3bb16 B
409 |/
409 |/
410 o 0:cd010b8cd998 A
410 o 0:cd010b8cd998 A
411
411
412 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
412 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
413 rebasing 1:42ccdea3bb16 "B"
413 rebasing 1:42ccdea3bb16 "B"
414 $ hg log -G
414 $ hg log -G
415 o 10:7c6027df6a99 B
415 o 10:7c6027df6a99 B
416 |
416 |
417 | o 9:cf44d2f5a9f4 D
417 | o 9:cf44d2f5a9f4 D
418 | |
418 | |
419 | o 8:e273c5e7d2d2 C
419 | o 8:e273c5e7d2d2 C
420 | |
420 | |
421 @ | 7:02de42196ebe H
421 @ | 7:02de42196ebe H
422 | |
422 | |
423 | o 6:eea13746799a G
423 | o 6:eea13746799a G
424 |/|
424 |/|
425 o | 5:24b6387c8c8c F
425 o | 5:24b6387c8c8c F
426 | |
426 | |
427 | o 4:9520eea781bc E
427 | o 4:9520eea781bc E
428 |/
428 |/
429 o 0:cd010b8cd998 A
429 o 0:cd010b8cd998 A
430
430
431 $ hg log --hidden -G
431 $ hg log --hidden -G
432 o 10:7c6027df6a99 B
432 o 10:7c6027df6a99 B
433 |
433 |
434 | o 9:cf44d2f5a9f4 D
434 | o 9:cf44d2f5a9f4 D
435 | |
435 | |
436 | o 8:e273c5e7d2d2 C
436 | o 8:e273c5e7d2d2 C
437 | |
437 | |
438 @ | 7:02de42196ebe H
438 @ | 7:02de42196ebe H
439 | |
439 | |
440 | o 6:eea13746799a G
440 | o 6:eea13746799a G
441 |/|
441 |/|
442 o | 5:24b6387c8c8c F
442 o | 5:24b6387c8c8c F
443 | |
443 | |
444 | o 4:9520eea781bc E
444 | o 4:9520eea781bc E
445 |/
445 |/
446 | x 3:32af7686d403 D (rewritten using rebase as 9:cf44d2f5a9f4)
446 | x 3:32af7686d403 D (rewritten using rebase as 9:cf44d2f5a9f4)
447 | |
447 | |
448 | x 2:5fddd98957c8 C (rewritten using rebase as 8:e273c5e7d2d2)
448 | x 2:5fddd98957c8 C (rewritten using rebase as 8:e273c5e7d2d2)
449 | |
449 | |
450 | x 1:42ccdea3bb16 B (rewritten using rebase as 10:7c6027df6a99)
450 | x 1:42ccdea3bb16 B (rewritten using rebase as 10:7c6027df6a99)
451 |/
451 |/
452 o 0:cd010b8cd998 A
452 o 0:cd010b8cd998 A
453
453
454 $ hg debugobsolete
454 $ hg debugobsolete
455 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
455 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
456 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
456 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
457 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
457 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
458
458
459 Test that rewriting leaving instability behind is allowed
459 Test that rewriting leaving instability behind is allowed
460 ---------------------------------------------------------------------
460 ---------------------------------------------------------------------
461
461
462 $ hg log -r 'children(8)'
462 $ hg log -r 'children(8)'
463 9:cf44d2f5a9f4 D (no-eol)
463 9:cf44d2f5a9f4 D (no-eol)
464 $ hg rebase -r 8
464 $ hg rebase -r 8
465 rebasing 8:e273c5e7d2d2 "C"
465 rebasing 8:e273c5e7d2d2 "C"
466 1 new orphan changesets
466 1 new orphan changesets
467 $ hg log -G
467 $ hg log -G
468 o 11:0d8f238b634c C
468 o 11:0d8f238b634c C
469 |
469 |
470 o 10:7c6027df6a99 B
470 o 10:7c6027df6a99 B
471 |
471 |
472 | * 9:cf44d2f5a9f4 D
472 | * 9:cf44d2f5a9f4 D
473 | |
473 | |
474 | x 8:e273c5e7d2d2 C (rewritten using rebase as 11:0d8f238b634c)
474 | x 8:e273c5e7d2d2 C (rewritten using rebase as 11:0d8f238b634c)
475 | |
475 | |
476 @ | 7:02de42196ebe H
476 @ | 7:02de42196ebe H
477 | |
477 | |
478 | o 6:eea13746799a G
478 | o 6:eea13746799a G
479 |/|
479 |/|
480 o | 5:24b6387c8c8c F
480 o | 5:24b6387c8c8c F
481 | |
481 | |
482 | o 4:9520eea781bc E
482 | o 4:9520eea781bc E
483 |/
483 |/
484 o 0:cd010b8cd998 A
484 o 0:cd010b8cd998 A
485
485
486 $ cd ..
486 $ cd ..
487 $ cp -R hidden stabilize
487 $ cp -R hidden stabilize
488 $ cd stabilize
488 $ cd stabilize
489 $ hg rebase --auto-orphans '0::' -d 10
489 $ hg rebase --auto-orphans '0::' -d 10
490 abort: cannot specify both --auto-orphans and --dest
490 abort: cannot specify both --auto-orphans and --dest
491 [255]
491 [255]
492 $ hg rebase --auto-orphans '0::'
492 $ hg rebase --auto-orphans '0::'
493 rebasing 9:cf44d2f5a9f4 "D"
493 rebasing 9:cf44d2f5a9f4 "D"
494 $ hg log -G
494 $ hg log -G
495 o 12:7e3935feaa68 D
495 o 12:7e3935feaa68 D
496 |
496 |
497 o 11:0d8f238b634c C
497 o 11:0d8f238b634c C
498 |
498 |
499 o 10:7c6027df6a99 B
499 o 10:7c6027df6a99 B
500 |
500 |
501 @ 7:02de42196ebe H
501 @ 7:02de42196ebe H
502 |
502 |
503 | o 6:eea13746799a G
503 | o 6:eea13746799a G
504 |/|
504 |/|
505 o | 5:24b6387c8c8c F
505 o | 5:24b6387c8c8c F
506 | |
506 | |
507 | o 4:9520eea781bc E
507 | o 4:9520eea781bc E
508 |/
508 |/
509 o 0:cd010b8cd998 A
509 o 0:cd010b8cd998 A
510
510
511
511
512 $ cd ../hidden
512 $ cd ../hidden
513 $ rm -r ../stabilize
513 $ rm -r ../stabilize
514
514
515 Test multiple root handling
515 Test multiple root handling
516 ------------------------------------
516 ------------------------------------
517
517
518 $ hg rebase --dest 4 --rev '7+11+9'
518 $ hg rebase --dest 4 --rev '7+11+9'
519 rebasing 9:cf44d2f5a9f4 "D"
519 rebasing 9:cf44d2f5a9f4 "D"
520 rebasing 7:02de42196ebe "H"
520 rebasing 7:02de42196ebe "H"
521 rebasing 11:0d8f238b634c "C" (tip)
521 rebasing 11:0d8f238b634c "C" (tip)
522 $ hg log -G
522 $ hg log -G
523 o 14:1e8370e38cca C
523 o 14:1e8370e38cca C
524 |
524 |
525 @ 13:bfe264faf697 H
525 @ 13:bfe264faf697 H
526 |
526 |
527 | o 12:102b4c1d889b D
527 | o 12:102b4c1d889b D
528 |/
528 |/
529 | * 10:7c6027df6a99 B
529 | * 10:7c6027df6a99 B
530 | |
530 | |
531 | x 7:02de42196ebe H (rewritten using rebase as 13:bfe264faf697)
531 | x 7:02de42196ebe H (rewritten using rebase as 13:bfe264faf697)
532 | |
532 | |
533 +---o 6:eea13746799a G
533 +---o 6:eea13746799a G
534 | |/
534 | |/
535 | o 5:24b6387c8c8c F
535 | o 5:24b6387c8c8c F
536 | |
536 | |
537 o | 4:9520eea781bc E
537 o | 4:9520eea781bc E
538 |/
538 |/
539 o 0:cd010b8cd998 A
539 o 0:cd010b8cd998 A
540
540
541 $ cd ..
541 $ cd ..
542
542
543 Detach both parents
543 Detach both parents
544
544
545 $ hg init double-detach
545 $ hg init double-detach
546 $ cd double-detach
546 $ cd double-detach
547
547
548 $ hg debugdrawdag <<EOF
548 $ hg debugdrawdag <<EOF
549 > F
549 > F
550 > /|
550 > /|
551 > C E
551 > C E
552 > | |
552 > | |
553 > B D G
553 > B D G
554 > \|/
554 > \|/
555 > A
555 > A
556 > EOF
556 > EOF
557
557
558 $ hg rebase -d G -r 'B + D + F'
558 $ hg rebase -d G -r 'B + D + F'
559 rebasing 1:112478962961 "B" (B)
559 rebasing 1:112478962961 "B" (B)
560 rebasing 2:b18e25de2cf5 "D" (D)
560 rebasing 2:b18e25de2cf5 "D" (D)
561 rebasing 6:f15c3adaf214 "F" (F tip)
561 rebasing 6:f15c3adaf214 "F" (F tip)
562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
563 [255]
563 [255]
564
564
565 $ cd ..
565 $ cd ..
566
566
567 test on rebase dropping a merge
567 test on rebase dropping a merge
568
568
569 (setup)
569 (setup)
570
570
571 $ hg init dropmerge
571 $ hg init dropmerge
572 $ cd dropmerge
572 $ cd dropmerge
573 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
573 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
574 adding changesets
574 adding changesets
575 adding manifests
575 adding manifests
576 adding file changes
576 adding file changes
577 added 8 changesets with 7 changes to 7 files (+2 heads)
577 added 8 changesets with 7 changes to 7 files (+2 heads)
578 new changesets cd010b8cd998:02de42196ebe (8 drafts)
578 new changesets cd010b8cd998:02de42196ebe (8 drafts)
579 (run 'hg heads' to see heads, 'hg merge' to merge)
579 (run 'hg heads' to see heads, 'hg merge' to merge)
580 $ hg up 3
580 $ hg up 3
581 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
581 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
582 $ hg merge 7
582 $ hg merge 7
583 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
583 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 (branch merge, don't forget to commit)
584 (branch merge, don't forget to commit)
585 $ hg ci -m 'M'
585 $ hg ci -m 'M'
586 $ echo I > I
586 $ echo I > I
587 $ hg add I
587 $ hg add I
588 $ hg ci -m I
588 $ hg ci -m I
589 $ hg log -G
589 $ hg log -G
590 @ 9:4bde274eefcf I
590 @ 9:4bde274eefcf I
591 |
591 |
592 o 8:53a6a128b2b7 M
592 o 8:53a6a128b2b7 M
593 |\
593 |\
594 | o 7:02de42196ebe H
594 | o 7:02de42196ebe H
595 | |
595 | |
596 | | o 6:eea13746799a G
596 | | o 6:eea13746799a G
597 | |/|
597 | |/|
598 | o | 5:24b6387c8c8c F
598 | o | 5:24b6387c8c8c F
599 | | |
599 | | |
600 | | o 4:9520eea781bc E
600 | | o 4:9520eea781bc E
601 | |/
601 | |/
602 o | 3:32af7686d403 D
602 o | 3:32af7686d403 D
603 | |
603 | |
604 o | 2:5fddd98957c8 C
604 o | 2:5fddd98957c8 C
605 | |
605 | |
606 o | 1:42ccdea3bb16 B
606 o | 1:42ccdea3bb16 B
607 |/
607 |/
608 o 0:cd010b8cd998 A
608 o 0:cd010b8cd998 A
609
609
610 (actual test)
610 (actual test)
611
611
612 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
612 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
613 rebasing 3:32af7686d403 "D"
613 rebasing 3:32af7686d403 "D"
614 rebasing 7:02de42196ebe "H"
614 rebasing 7:02de42196ebe "H"
615 rebasing 9:4bde274eefcf "I" (tip)
615 rebasing 9:4bde274eefcf "I" (tip)
616 1 new orphan changesets
616 1 new orphan changesets
617 $ hg log -G
617 $ hg log -G
618 @ 12:acd174b7ab39 I
618 @ 12:acd174b7ab39 I
619 |
619 |
620 o 11:6c11a6218c97 H
620 o 11:6c11a6218c97 H
621 |
621 |
622 | o 10:b5313c85b22e D
622 | o 10:b5313c85b22e D
623 |/
623 |/
624 | * 8:53a6a128b2b7 M
624 | * 8:53a6a128b2b7 M
625 | |\
625 | |\
626 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
626 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
627 | | |
627 | | |
628 o---+ 6:eea13746799a G
628 o---+ 6:eea13746799a G
629 | | |
629 | | |
630 | | o 5:24b6387c8c8c F
630 | | o 5:24b6387c8c8c F
631 | | |
631 | | |
632 o---+ 4:9520eea781bc E
632 o---+ 4:9520eea781bc E
633 / /
633 / /
634 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
634 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
635 | |
635 | |
636 o | 2:5fddd98957c8 C
636 o | 2:5fddd98957c8 C
637 | |
637 | |
638 o | 1:42ccdea3bb16 B
638 o | 1:42ccdea3bb16 B
639 |/
639 |/
640 o 0:cd010b8cd998 A
640 o 0:cd010b8cd998 A
641
641
642
642
643 Test hidden changesets in the rebase set (issue4504)
643 Test hidden changesets in the rebase set (issue4504)
644
644
645 $ hg up --hidden 9
645 $ hg up --hidden 9
646 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
646 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
647 updated to hidden changeset 4bde274eefcf
647 updated to hidden changeset 4bde274eefcf
648 (hidden revision '4bde274eefcf' was rewritten as: acd174b7ab39)
648 (hidden revision '4bde274eefcf' was rewritten as: acd174b7ab39)
649 $ echo J > J
649 $ echo J > J
650 $ hg add J
650 $ hg add J
651 $ hg commit -m J
651 $ hg commit -m J
652 1 new orphan changesets
652 1 new orphan changesets
653 $ hg debugobsolete `hg log --rev . -T '{node}'`
653 $ hg debugobsolete `hg log --rev . -T '{node}'`
654 1 new obsolescence markers
654 1 new obsolescence markers
655 obsoleted 1 changesets
655 obsoleted 1 changesets
656
656
657 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
657 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
658 rebasing 9:4bde274eefcf "I"
658 rebasing 9:4bde274eefcf "I"
659 rebasing 13:06edfc82198f "J" (tip)
659 rebasing 13:06edfc82198f "J" (tip)
660 2 new content-divergent changesets
660 2 new content-divergent changesets
661 $ hg log -G
661 $ hg log -G
662 @ 15:5ae8a643467b J
662 @ 15:5ae8a643467b J
663 |
663 |
664 * 14:9ad579b4a5de I
664 * 14:9ad579b4a5de I
665 |
665 |
666 | * 12:acd174b7ab39 I
666 | * 12:acd174b7ab39 I
667 | |
667 | |
668 | o 11:6c11a6218c97 H
668 | o 11:6c11a6218c97 H
669 | |
669 | |
670 o | 10:b5313c85b22e D
670 o | 10:b5313c85b22e D
671 |/
671 |/
672 | * 8:53a6a128b2b7 M
672 | * 8:53a6a128b2b7 M
673 | |\
673 | |\
674 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
674 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
675 | | |
675 | | |
676 o---+ 6:eea13746799a G
676 o---+ 6:eea13746799a G
677 | | |
677 | | |
678 | | o 5:24b6387c8c8c F
678 | | o 5:24b6387c8c8c F
679 | | |
679 | | |
680 o---+ 4:9520eea781bc E
680 o---+ 4:9520eea781bc E
681 / /
681 / /
682 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
682 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
683 | |
683 | |
684 o | 2:5fddd98957c8 C
684 o | 2:5fddd98957c8 C
685 | |
685 | |
686 o | 1:42ccdea3bb16 B
686 o | 1:42ccdea3bb16 B
687 |/
687 |/
688 o 0:cd010b8cd998 A
688 o 0:cd010b8cd998 A
689
689
690 $ hg up 14 -C
690 $ hg up 14 -C
691 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
691 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
692 $ echo "K" > K
692 $ echo "K" > K
693 $ hg add K
693 $ hg add K
694 $ hg commit --amend -m "K"
694 $ hg commit --amend -m "K"
695 1 new orphan changesets
695 1 new orphan changesets
696 $ echo "L" > L
696 $ echo "L" > L
697 $ hg add L
697 $ hg add L
698 $ hg commit -m "L"
698 $ hg commit -m "L"
699 $ hg up '.^'
699 $ hg up '.^'
700 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
700 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
701 $ echo "M" > M
701 $ echo "M" > M
702 $ hg add M
702 $ hg add M
703 $ hg commit --amend -m "M"
703 $ hg commit --amend -m "M"
704 1 new orphan changesets
704 1 new orphan changesets
705 $ hg log -G
705 $ hg log -G
706 @ 18:bfaedf8eb73b M
706 @ 18:bfaedf8eb73b M
707 |
707 |
708 | * 17:97219452e4bd L
708 | * 17:97219452e4bd L
709 | |
709 | |
710 | x 16:fc37a630c901 K (rewritten using amend as 18:bfaedf8eb73b)
710 | x 16:fc37a630c901 K (rewritten using amend as 18:bfaedf8eb73b)
711 |/
711 |/
712 | * 15:5ae8a643467b J
712 | * 15:5ae8a643467b J
713 | |
713 | |
714 | x 14:9ad579b4a5de I (rewritten using amend as 16:fc37a630c901)
714 | x 14:9ad579b4a5de I (rewritten using amend as 16:fc37a630c901)
715 |/
715 |/
716 | * 12:acd174b7ab39 I
716 | * 12:acd174b7ab39 I
717 | |
717 | |
718 | o 11:6c11a6218c97 H
718 | o 11:6c11a6218c97 H
719 | |
719 | |
720 o | 10:b5313c85b22e D
720 o | 10:b5313c85b22e D
721 |/
721 |/
722 | * 8:53a6a128b2b7 M
722 | * 8:53a6a128b2b7 M
723 | |\
723 | |\
724 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
724 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
725 | | |
725 | | |
726 o---+ 6:eea13746799a G
726 o---+ 6:eea13746799a G
727 | | |
727 | | |
728 | | o 5:24b6387c8c8c F
728 | | o 5:24b6387c8c8c F
729 | | |
729 | | |
730 o---+ 4:9520eea781bc E
730 o---+ 4:9520eea781bc E
731 / /
731 / /
732 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
732 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
733 | |
733 | |
734 o | 2:5fddd98957c8 C
734 o | 2:5fddd98957c8 C
735 | |
735 | |
736 o | 1:42ccdea3bb16 B
736 o | 1:42ccdea3bb16 B
737 |/
737 |/
738 o 0:cd010b8cd998 A
738 o 0:cd010b8cd998 A
739
739
740 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
740 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
741 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
741 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
742 rebasing 15:5ae8a643467b "J"
742 rebasing 15:5ae8a643467b "J"
743 1 new orphan changesets
743 1 new orphan changesets
744
744
745 $ cd ..
745 $ cd ..
746
746
747 Skip obsolete changeset even with multiple hops
747 Skip obsolete changeset even with multiple hops
748 -----------------------------------------------
748 -----------------------------------------------
749
749
750 setup
750 setup
751
751
752 $ hg init obsskip
752 $ hg init obsskip
753 $ cd obsskip
753 $ cd obsskip
754 $ cat << EOF >> .hg/hgrc
754 $ cat << EOF >> .hg/hgrc
755 > [experimental]
755 > [experimental]
756 > rebaseskipobsolete = True
756 > rebaseskipobsolete = True
757 > [extensions]
757 > [extensions]
758 > strip =
758 > strip =
759 > EOF
759 > EOF
760 $ echo A > A
760 $ echo A > A
761 $ hg add A
761 $ hg add A
762 $ hg commit -m A
762 $ hg commit -m A
763 $ echo B > B
763 $ echo B > B
764 $ hg add B
764 $ hg add B
765 $ hg commit -m B0
765 $ hg commit -m B0
766 $ hg commit --amend -m B1
766 $ hg commit --amend -m B1
767 $ hg commit --amend -m B2
767 $ hg commit --amend -m B2
768 $ hg up --hidden 'desc(B0)'
768 $ hg up --hidden 'desc(B0)'
769 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
769 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
770 updated to hidden changeset a8b11f55fb19
770 updated to hidden changeset a8b11f55fb19
771 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
771 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
772 $ echo C > C
772 $ echo C > C
773 $ hg add C
773 $ hg add C
774 $ hg commit -m C
774 $ hg commit -m C
775 1 new orphan changesets
775 1 new orphan changesets
776 $ hg log -G
776 $ hg log -G
777 @ 4:212cb178bcbb C
777 @ 4:212cb178bcbb C
778 |
778 |
779 | o 3:261e70097290 B2
779 | o 3:261e70097290 B2
780 | |
780 | |
781 x | 1:a8b11f55fb19 B0 (rewritten using amend as 3:261e70097290)
781 x | 1:a8b11f55fb19 B0 (rewritten using amend as 3:261e70097290)
782 |/
782 |/
783 o 0:4a2df7238c3b A
783 o 0:4a2df7238c3b A
784
784
785
785
786 Rebase finds its way in a chain of marker
786 Rebase finds its way in a chain of marker
787
787
788 $ hg rebase -d 'desc(B2)'
788 $ hg rebase -d 'desc(B2)'
789 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
789 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
790 rebasing 4:212cb178bcbb "C" (tip)
790 rebasing 4:212cb178bcbb "C" (tip)
791
791
792 Even when the chain include missing node
792 Even when the chain include missing node
793
793
794 $ hg up --hidden 'desc(B0)'
794 $ hg up --hidden 'desc(B0)'
795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 updated to hidden changeset a8b11f55fb19
796 updated to hidden changeset a8b11f55fb19
797 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
797 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
798 $ echo D > D
798 $ echo D > D
799 $ hg add D
799 $ hg add D
800 $ hg commit -m D
800 $ hg commit -m D
801 1 new orphan changesets
801 1 new orphan changesets
802 $ hg --hidden strip -r 'desc(B1)'
802 $ hg --hidden strip -r 'desc(B1)'
803 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
803 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
804 1 new orphan changesets
804 1 new orphan changesets
805 $ hg log -G
805 $ hg log -G
806 @ 5:1a79b7535141 D
806 @ 5:1a79b7535141 D
807 |
807 |
808 | o 4:ff2c4d47b71d C
808 | o 4:ff2c4d47b71d C
809 | |
809 | |
810 | o 2:261e70097290 B2
810 | o 2:261e70097290 B2
811 | |
811 | |
812 x | 1:a8b11f55fb19 B0 (rewritten using amend as 2:261e70097290)
812 x | 1:a8b11f55fb19 B0 (rewritten using amend as 2:261e70097290)
813 |/
813 |/
814 o 0:4a2df7238c3b A
814 o 0:4a2df7238c3b A
815
815
816
816
817 $ hg rebase -d 'desc(B2)'
817 $ hg rebase -d 'desc(B2)'
818 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
818 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
819 rebasing 5:1a79b7535141 "D" (tip)
819 rebasing 5:1a79b7535141 "D" (tip)
820 $ hg up 4
820 $ hg up 4
821 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
821 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
822 $ echo "O" > O
822 $ echo "O" > O
823 $ hg add O
823 $ hg add O
824 $ hg commit -m O
824 $ hg commit -m O
825 $ echo "P" > P
825 $ echo "P" > P
826 $ hg add P
826 $ hg add P
827 $ hg commit -m P
827 $ hg commit -m P
828 $ hg log -G
828 $ hg log -G
829 @ 8:8d47583e023f P
829 @ 8:8d47583e023f P
830 |
830 |
831 o 7:360bbaa7d3ce O
831 o 7:360bbaa7d3ce O
832 |
832 |
833 | o 6:9c48361117de D
833 | o 6:9c48361117de D
834 | |
834 | |
835 o | 4:ff2c4d47b71d C
835 o | 4:ff2c4d47b71d C
836 |/
836 |/
837 o 2:261e70097290 B2
837 o 2:261e70097290 B2
838 |
838 |
839 o 0:4a2df7238c3b A
839 o 0:4a2df7238c3b A
840
840
841 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.evolution=true
841 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.evolution=true
842 1 new obsolescence markers
842 1 new obsolescence markers
843 obsoleted 1 changesets
843 obsoleted 1 changesets
844 1 new orphan changesets
844 1 new orphan changesets
845 $ hg rebase -d 6 -r "4::"
845 $ hg rebase -d 6 -r "4::"
846 rebasing 4:ff2c4d47b71d "C"
846 rebasing 4:ff2c4d47b71d "C"
847 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
847 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
848 rebasing 8:8d47583e023f "P" (tip)
848 rebasing 8:8d47583e023f "P" (tip)
849
849
850 If all the changeset to be rebased are obsolete and present in the destination, we
850 If all the changeset to be rebased are obsolete and present in the destination, we
851 should display a friendly error message
851 should display a friendly error message
852
852
853 $ hg log -G
853 $ hg log -G
854 @ 10:121d9e3bc4c6 P
854 @ 10:121d9e3bc4c6 P
855 |
855 |
856 o 9:4be60e099a77 C
856 o 9:4be60e099a77 C
857 |
857 |
858 o 6:9c48361117de D
858 o 6:9c48361117de D
859 |
859 |
860 o 2:261e70097290 B2
860 o 2:261e70097290 B2
861 |
861 |
862 o 0:4a2df7238c3b A
862 o 0:4a2df7238c3b A
863
863
864
864
865 $ hg up 9
865 $ hg up 9
866 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
866 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
867 $ echo "non-relevant change" > nonrelevant
867 $ echo "non-relevant change" > nonrelevant
868 $ hg add nonrelevant
868 $ hg add nonrelevant
869 $ hg commit -m nonrelevant
869 $ hg commit -m nonrelevant
870 created new head
870 created new head
871 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.evolution=true
871 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.evolution=true
872 1 new obsolescence markers
872 1 new obsolescence markers
873 obsoleted 1 changesets
873 obsoleted 1 changesets
874 $ hg log -G
874 $ hg log -G
875 @ 11:f44da1f4954c nonrelevant (pruned)
875 @ 11:f44da1f4954c nonrelevant (pruned)
876 |
876 |
877 | o 10:121d9e3bc4c6 P
877 | o 10:121d9e3bc4c6 P
878 |/
878 |/
879 o 9:4be60e099a77 C
879 o 9:4be60e099a77 C
880 |
880 |
881 o 6:9c48361117de D
881 o 6:9c48361117de D
882 |
882 |
883 o 2:261e70097290 B2
883 o 2:261e70097290 B2
884 |
884 |
885 o 0:4a2df7238c3b A
885 o 0:4a2df7238c3b A
886
886
887 $ hg rebase -r . -d 10
887 $ hg rebase -r . -d 10
888 note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor
888 note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor
889
889
890 If a rebase is going to create divergence, it should abort
890 If a rebase is going to create divergence, it should abort
891
891
892 $ hg log -G
892 $ hg log -G
893 @ 10:121d9e3bc4c6 P
893 @ 10:121d9e3bc4c6 P
894 |
894 |
895 o 9:4be60e099a77 C
895 o 9:4be60e099a77 C
896 |
896 |
897 o 6:9c48361117de D
897 o 6:9c48361117de D
898 |
898 |
899 o 2:261e70097290 B2
899 o 2:261e70097290 B2
900 |
900 |
901 o 0:4a2df7238c3b A
901 o 0:4a2df7238c3b A
902
902
903
903
904 $ hg up 9
904 $ hg up 9
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
906 $ echo "john" > doe
906 $ echo "john" > doe
907 $ hg add doe
907 $ hg add doe
908 $ hg commit -m "john doe"
908 $ hg commit -m "john doe"
909 created new head
909 created new head
910 $ hg up 10
910 $ hg up 10
911 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
911 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
912 $ echo "foo" > bar
912 $ echo "foo" > bar
913 $ hg add bar
913 $ hg add bar
914 $ hg commit --amend -m "10'"
914 $ hg commit --amend -m "10'"
915 $ hg up 10 --hidden
915 $ hg up 10 --hidden
916 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
916 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
917 updated to hidden changeset 121d9e3bc4c6
917 updated to hidden changeset 121d9e3bc4c6
918 (hidden revision '121d9e3bc4c6' was rewritten as: 77d874d096a2)
918 (hidden revision '121d9e3bc4c6' was rewritten as: 77d874d096a2)
919 $ echo "bar" > foo
919 $ echo "bar" > foo
920 $ hg add foo
920 $ hg add foo
921 $ hg commit -m "bar foo"
921 $ hg commit -m "bar foo"
922 1 new orphan changesets
922 1 new orphan changesets
923 $ hg log -G
923 $ hg log -G
924 @ 14:73568ab6879d bar foo
924 @ 14:73568ab6879d bar foo
925 |
925 |
926 | o 13:77d874d096a2 10'
926 | o 13:77d874d096a2 10'
927 | |
927 | |
928 | | o 12:3eb461388009 john doe
928 | | o 12:3eb461388009 john doe
929 | |/
929 | |/
930 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
930 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
931 |/
931 |/
932 o 9:4be60e099a77 C
932 o 9:4be60e099a77 C
933 |
933 |
934 o 6:9c48361117de D
934 o 6:9c48361117de D
935 |
935 |
936 o 2:261e70097290 B2
936 o 2:261e70097290 B2
937 |
937 |
938 o 0:4a2df7238c3b A
938 o 0:4a2df7238c3b A
939
939
940 $ hg summary
940 $ hg summary
941 parent: 14:73568ab6879d tip (orphan)
941 parent: 14:73568ab6879d tip (orphan)
942 bar foo
942 bar foo
943 branch: default
943 branch: default
944 commit: (clean)
944 commit: (clean)
945 update: 2 new changesets, 3 branch heads (merge)
945 update: 2 new changesets, 3 branch heads (merge)
946 phases: 8 draft
946 phases: 8 draft
947 orphan: 1 changesets
947 orphan: 1 changesets
948 $ hg rebase -s 10 -d 12
948 $ hg rebase -s 10 -d 12
949 abort: this rebase will cause divergences from: 121d9e3bc4c6
949 abort: this rebase will cause divergences from: 121d9e3bc4c6
950 (to force the rebase please set experimental.evolution.allowdivergence=True)
950 (to force the rebase please set experimental.evolution.allowdivergence=True)
951 [255]
951 [255]
952 $ hg log -G
952 $ hg log -G
953 @ 14:73568ab6879d bar foo
953 @ 14:73568ab6879d bar foo
954 |
954 |
955 | o 13:77d874d096a2 10'
955 | o 13:77d874d096a2 10'
956 | |
956 | |
957 | | o 12:3eb461388009 john doe
957 | | o 12:3eb461388009 john doe
958 | |/
958 | |/
959 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
959 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
960 |/
960 |/
961 o 9:4be60e099a77 C
961 o 9:4be60e099a77 C
962 |
962 |
963 o 6:9c48361117de D
963 o 6:9c48361117de D
964 |
964 |
965 o 2:261e70097290 B2
965 o 2:261e70097290 B2
966 |
966 |
967 o 0:4a2df7238c3b A
967 o 0:4a2df7238c3b A
968
968
969 With experimental.evolution.allowdivergence=True, rebase can create divergence
969 With experimental.evolution.allowdivergence=True, rebase can create divergence
970
970
971 $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True
971 $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True
972 rebasing 10:121d9e3bc4c6 "P"
972 rebasing 10:121d9e3bc4c6 "P"
973 rebasing 14:73568ab6879d "bar foo" (tip)
973 rebasing 14:73568ab6879d "bar foo" (tip)
974 2 new content-divergent changesets
974 2 new content-divergent changesets
975 $ hg summary
975 $ hg summary
976 parent: 16:61bd55f69bc4 tip
976 parent: 16:61bd55f69bc4 tip
977 bar foo
977 bar foo
978 branch: default
978 branch: default
979 commit: (clean)
979 commit: (clean)
980 update: 1 new changesets, 2 branch heads (merge)
980 update: 1 new changesets, 2 branch heads (merge)
981 phases: 8 draft
981 phases: 8 draft
982 content-divergent: 2 changesets
982 content-divergent: 2 changesets
983
983
984 rebase --continue + skipped rev because their successors are in destination
984 rebase --continue + skipped rev because their successors are in destination
985 we make a change in trunk and work on conflicting changes to make rebase abort.
985 we make a change in trunk and work on conflicting changes to make rebase abort.
986
986
987 $ hg log -G -r 16::
987 $ hg log -G -r 16::
988 @ 16:61bd55f69bc4 bar foo
988 @ 16:61bd55f69bc4 bar foo
989 |
989 |
990 ~
990 ~
991
991
992 Create the two changes in trunk
992 Create the two changes in trunk
993 $ printf "a" > willconflict
993 $ printf "a" > willconflict
994 $ hg add willconflict
994 $ hg add willconflict
995 $ hg commit -m "willconflict first version"
995 $ hg commit -m "willconflict first version"
996
996
997 $ printf "dummy" > C
997 $ printf "dummy" > C
998 $ hg commit -m "dummy change successor"
998 $ hg commit -m "dummy change successor"
999
999
1000 Create the changes that we will rebase
1000 Create the changes that we will rebase
1001 $ hg update -C 16 -q
1001 $ hg update -C 16 -q
1002 $ printf "b" > willconflict
1002 $ printf "b" > willconflict
1003 $ hg add willconflict
1003 $ hg add willconflict
1004 $ hg commit -m "willconflict second version"
1004 $ hg commit -m "willconflict second version"
1005 created new head
1005 created new head
1006 $ printf "dummy" > K
1006 $ printf "dummy" > K
1007 $ hg add K
1007 $ hg add K
1008 $ hg commit -m "dummy change"
1008 $ hg commit -m "dummy change"
1009 $ printf "dummy" > L
1009 $ printf "dummy" > L
1010 $ hg add L
1010 $ hg add L
1011 $ hg commit -m "dummy change"
1011 $ hg commit -m "dummy change"
1012 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.evolution=true
1012 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.evolution=true
1013 1 new obsolescence markers
1013 1 new obsolescence markers
1014 obsoleted 1 changesets
1014 obsoleted 1 changesets
1015 1 new orphan changesets
1015 1 new orphan changesets
1016
1016
1017 $ hg log -G -r 16::
1017 $ hg log -G -r 16::
1018 @ 21:7bdc8a87673d dummy change
1018 @ 21:7bdc8a87673d dummy change
1019 |
1019 |
1020 x 20:8b31da3c4919 dummy change (rewritten as 18:601db7a18f51)
1020 x 20:8b31da3c4919 dummy change (rewritten as 18:601db7a18f51)
1021 |
1021 |
1022 o 19:b82fb57ea638 willconflict second version
1022 o 19:b82fb57ea638 willconflict second version
1023 |
1023 |
1024 | o 18:601db7a18f51 dummy change successor
1024 | o 18:601db7a18f51 dummy change successor
1025 | |
1025 | |
1026 | o 17:357ddf1602d5 willconflict first version
1026 | o 17:357ddf1602d5 willconflict first version
1027 |/
1027 |/
1028 o 16:61bd55f69bc4 bar foo
1028 o 16:61bd55f69bc4 bar foo
1029 |
1029 |
1030 ~
1030 ~
1031 $ hg rebase -r ".^^ + .^ + ." -d 18
1031 $ hg rebase -r ".^^ + .^ + ." -d 18
1032 rebasing 19:b82fb57ea638 "willconflict second version"
1032 rebasing 19:b82fb57ea638 "willconflict second version"
1033 merging willconflict
1033 merging willconflict
1034 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
1034 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
1035 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1035 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1036 [1]
1036 [1]
1037
1037
1038 $ hg resolve --mark willconflict
1038 $ hg resolve --mark willconflict
1039 (no more unresolved files)
1039 (no more unresolved files)
1040 continue: hg rebase --continue
1040 continue: hg rebase --continue
1041 $ hg rebase --continue
1041 $ hg rebase --continue
1042 rebasing 19:b82fb57ea638 "willconflict second version"
1042 rebasing 19:b82fb57ea638 "willconflict second version"
1043 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
1043 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
1044 rebasing 21:7bdc8a87673d "dummy change" (tip)
1044 rebasing 21:7bdc8a87673d "dummy change" (tip)
1045 $ cd ..
1045 $ cd ..
1046
1046
1047 Divergence cases due to obsolete changesets
1047 Divergence cases due to obsolete changesets
1048 -------------------------------------------
1048 -------------------------------------------
1049
1049
1050 We should ignore branches with unstable changesets when they are based on an
1050 We should ignore branches with unstable changesets when they are based on an
1051 obsolete changeset which successor is in rebase set.
1051 obsolete changeset which successor is in rebase set.
1052
1052
1053 $ hg init divergence
1053 $ hg init divergence
1054 $ cd divergence
1054 $ cd divergence
1055 $ cat >> .hg/hgrc << EOF
1055 $ cat >> .hg/hgrc << EOF
1056 > [extensions]
1056 > [extensions]
1057 > strip =
1057 > strip =
1058 > [alias]
1058 > [alias]
1059 > strip = strip --no-backup --quiet
1059 > strip = strip --no-backup --quiet
1060 > [templates]
1060 > [templates]
1061 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1061 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1062 > EOF
1062 > EOF
1063
1063
1064 $ hg debugdrawdag <<EOF
1064 $ hg debugdrawdag <<EOF
1065 > e f
1065 > e f
1066 > | |
1066 > | |
1067 > d' d # replace: d -> d'
1067 > d' d # replace: d -> d'
1068 > \ /
1068 > \ /
1069 > c
1069 > c
1070 > |
1070 > |
1071 > x b
1071 > x b
1072 > \|
1072 > \|
1073 > a
1073 > a
1074 > EOF
1074 > EOF
1075 1 new orphan changesets
1075 1 new orphan changesets
1076 $ hg log -G -r 'a'::
1076 $ hg log -G -r 'a'::
1077 * 7:1143e9adc121 f
1077 * 7:1143e9adc121 f
1078 |
1078 |
1079 | o 6:d60ebfa0f1cb e
1079 | o 6:d60ebfa0f1cb e
1080 | |
1080 | |
1081 | o 5:027ad6c5830d d'
1081 | o 5:027ad6c5830d d'
1082 | |
1082 | |
1083 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1083 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1084 |/
1084 |/
1085 o 3:a82ac2b38757 c
1085 o 3:a82ac2b38757 c
1086 |
1086 |
1087 | o 2:630d7c95eff7 x
1087 | o 2:630d7c95eff7 x
1088 | |
1088 | |
1089 o | 1:488e1b7e7341 b
1089 o | 1:488e1b7e7341 b
1090 |/
1090 |/
1091 o 0:b173517d0057 a
1091 o 0:b173517d0057 a
1092
1092
1093
1093
1094 Changeset d and its descendants are excluded to avoid divergence of d, which
1094 Changeset d and its descendants are excluded to avoid divergence of d, which
1095 would occur because the successor of d (d') is also in rebaseset. As a
1095 would occur because the successor of d (d') is also in rebaseset. As a
1096 consequence f (descendant of d) is left behind.
1096 consequence f (descendant of d) is left behind.
1097
1097
1098 $ hg rebase -b 'e' -d 'x'
1098 $ hg rebase -b 'e' -d 'x'
1099 rebasing 1:488e1b7e7341 "b" (b)
1099 rebasing 1:488e1b7e7341 "b" (b)
1100 rebasing 3:a82ac2b38757 "c" (c)
1100 rebasing 3:a82ac2b38757 "c" (c)
1101 rebasing 5:027ad6c5830d "d'" (d')
1101 rebasing 5:027ad6c5830d "d'" (d')
1102 rebasing 6:d60ebfa0f1cb "e" (e)
1102 rebasing 6:d60ebfa0f1cb "e" (e)
1103 note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence
1103 note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence
1104 $ hg log -G -r 'a'::
1104 $ hg log -G -r 'a'::
1105 o 11:eb6d63fc4ed5 e
1105 o 11:eb6d63fc4ed5 e
1106 |
1106 |
1107 o 10:44d8c724a70c d'
1107 o 10:44d8c724a70c d'
1108 |
1108 |
1109 o 9:d008e6b4d3fd c
1109 o 9:d008e6b4d3fd c
1110 |
1110 |
1111 o 8:67e8f4a16c49 b
1111 o 8:67e8f4a16c49 b
1112 |
1112 |
1113 | * 7:1143e9adc121 f
1113 | * 7:1143e9adc121 f
1114 | |
1114 | |
1115 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1115 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1116 | | |
1116 | | |
1117 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1117 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1118 | | |
1118 | | |
1119 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1119 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1120 | |/
1120 | |/
1121 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1121 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1122 | |
1122 | |
1123 o | 2:630d7c95eff7 x
1123 o | 2:630d7c95eff7 x
1124 | |
1124 | |
1125 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1125 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1126 |/
1126 |/
1127 o 0:b173517d0057 a
1127 o 0:b173517d0057 a
1128
1128
1129 $ hg strip -r 8:
1129 $ hg strip -r 8:
1130 $ hg log -G -r 'a'::
1130 $ hg log -G -r 'a'::
1131 * 7:1143e9adc121 f
1131 * 7:1143e9adc121 f
1132 |
1132 |
1133 | o 6:d60ebfa0f1cb e
1133 | o 6:d60ebfa0f1cb e
1134 | |
1134 | |
1135 | o 5:027ad6c5830d d'
1135 | o 5:027ad6c5830d d'
1136 | |
1136 | |
1137 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1137 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1138 |/
1138 |/
1139 o 3:a82ac2b38757 c
1139 o 3:a82ac2b38757 c
1140 |
1140 |
1141 | o 2:630d7c95eff7 x
1141 | o 2:630d7c95eff7 x
1142 | |
1142 | |
1143 o | 1:488e1b7e7341 b
1143 o | 1:488e1b7e7341 b
1144 |/
1144 |/
1145 o 0:b173517d0057 a
1145 o 0:b173517d0057 a
1146
1146
1147
1147
1148 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1148 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1149 set and none in destination, we still get the divergence warning.
1149 set and none in destination, we still get the divergence warning.
1150 By allowing divergence, we can perform the rebase.
1150 By allowing divergence, we can perform the rebase.
1151
1151
1152 $ hg rebase -r 'c'::'f' -d 'x'
1152 $ hg rebase -r 'c'::'f' -d 'x'
1153 abort: this rebase will cause divergences from: 76be324c128b
1153 abort: this rebase will cause divergences from: 76be324c128b
1154 (to force the rebase please set experimental.evolution.allowdivergence=True)
1154 (to force the rebase please set experimental.evolution.allowdivergence=True)
1155 [255]
1155 [255]
1156 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1156 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1157 rebasing 3:a82ac2b38757 "c" (c)
1157 rebasing 3:a82ac2b38757 "c" (c)
1158 rebasing 4:76be324c128b "d" (d)
1158 rebasing 4:76be324c128b "d" (d)
1159 rebasing 7:1143e9adc121 "f" (f tip)
1159 rebasing 7:1143e9adc121 "f" (f tip)
1160 1 new orphan changesets
1160 1 new orphan changesets
1161 2 new content-divergent changesets
1161 2 new content-divergent changesets
1162 $ hg log -G -r 'a':: -T instabilities
1162 $ hg log -G -r 'a':: -T instabilities
1163 o 10:e1744ea07510 f
1163 o 10:e1744ea07510 f
1164 |
1164 |
1165 * 9:e2b36ea9a0a0 d (content-divergent)
1165 * 9:e2b36ea9a0a0 d (content-divergent)
1166 |
1166 |
1167 o 8:6a0376de376e c
1167 o 8:6a0376de376e c
1168 |
1168 |
1169 | x 7:1143e9adc121 f
1169 | x 7:1143e9adc121 f
1170 | |
1170 | |
1171 | | * 6:d60ebfa0f1cb e (orphan)
1171 | | * 6:d60ebfa0f1cb e (orphan)
1172 | | |
1172 | | |
1173 | | * 5:027ad6c5830d d' (orphan content-divergent)
1173 | | * 5:027ad6c5830d d' (orphan content-divergent)
1174 | | |
1174 | | |
1175 | x | 4:76be324c128b d
1175 | x | 4:76be324c128b d
1176 | |/
1176 | |/
1177 | x 3:a82ac2b38757 c
1177 | x 3:a82ac2b38757 c
1178 | |
1178 | |
1179 o | 2:630d7c95eff7 x
1179 o | 2:630d7c95eff7 x
1180 | |
1180 | |
1181 | o 1:488e1b7e7341 b
1181 | o 1:488e1b7e7341 b
1182 |/
1182 |/
1183 o 0:b173517d0057 a
1183 o 0:b173517d0057 a
1184
1184
1185 $ hg strip -r 8:
1185 $ hg strip -r 8:
1186
1186
1187 (Not skipping obsoletes means that divergence is allowed.)
1187 (Not skipping obsoletes means that divergence is allowed.)
1188
1188
1189 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1189 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1190 rebasing 3:a82ac2b38757 "c" (c)
1190 rebasing 3:a82ac2b38757 "c" (c)
1191 rebasing 4:76be324c128b "d" (d)
1191 rebasing 4:76be324c128b "d" (d)
1192 rebasing 7:1143e9adc121 "f" (f tip)
1192 rebasing 7:1143e9adc121 "f" (f tip)
1193 1 new orphan changesets
1193 1 new orphan changesets
1194 2 new content-divergent changesets
1194 2 new content-divergent changesets
1195
1195
1196 $ hg strip -r 0:
1196 $ hg strip -r 0:
1197
1197
1198 Similar test on a more complex graph
1198 Similar test on a more complex graph
1199
1199
1200 $ hg debugdrawdag <<EOF
1200 $ hg debugdrawdag <<EOF
1201 > g
1201 > g
1202 > |
1202 > |
1203 > f e
1203 > f e
1204 > | |
1204 > | |
1205 > e' d # replace: e -> e'
1205 > e' d # replace: e -> e'
1206 > \ /
1206 > \ /
1207 > c
1207 > c
1208 > |
1208 > |
1209 > x b
1209 > x b
1210 > \|
1210 > \|
1211 > a
1211 > a
1212 > EOF
1212 > EOF
1213 1 new orphan changesets
1213 1 new orphan changesets
1214 $ hg log -G -r 'a':
1214 $ hg log -G -r 'a':
1215 * 8:2876ce66c6eb g
1215 * 8:2876ce66c6eb g
1216 |
1216 |
1217 | o 7:3ffec603ab53 f
1217 | o 7:3ffec603ab53 f
1218 | |
1218 | |
1219 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1219 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1220 | |
1220 | |
1221 | o 5:63324dc512ea e'
1221 | o 5:63324dc512ea e'
1222 | |
1222 | |
1223 o | 4:76be324c128b d
1223 o | 4:76be324c128b d
1224 |/
1224 |/
1225 o 3:a82ac2b38757 c
1225 o 3:a82ac2b38757 c
1226 |
1226 |
1227 | o 2:630d7c95eff7 x
1227 | o 2:630d7c95eff7 x
1228 | |
1228 | |
1229 o | 1:488e1b7e7341 b
1229 o | 1:488e1b7e7341 b
1230 |/
1230 |/
1231 o 0:b173517d0057 a
1231 o 0:b173517d0057 a
1232
1232
1233 $ hg rebase -b 'f' -d 'x'
1233 $ hg rebase -b 'f' -d 'x'
1234 rebasing 1:488e1b7e7341 "b" (b)
1234 rebasing 1:488e1b7e7341 "b" (b)
1235 rebasing 3:a82ac2b38757 "c" (c)
1235 rebasing 3:a82ac2b38757 "c" (c)
1236 rebasing 5:63324dc512ea "e'" (e')
1236 rebasing 5:63324dc512ea "e'" (e')
1237 rebasing 7:3ffec603ab53 "f" (f)
1237 rebasing 7:3ffec603ab53 "f" (f)
1238 rebasing 4:76be324c128b "d" (d)
1238 rebasing 4:76be324c128b "d" (d)
1239 note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence
1239 note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence
1240 $ hg log -G -r 'a':
1240 $ hg log -G -r 'a':
1241 o 13:a1707a5b7c2c d
1241 o 13:a1707a5b7c2c d
1242 |
1242 |
1243 | o 12:ef6251596616 f
1243 | o 12:ef6251596616 f
1244 | |
1244 | |
1245 | o 11:b6f172e64af9 e'
1245 | o 11:b6f172e64af9 e'
1246 |/
1246 |/
1247 o 10:d008e6b4d3fd c
1247 o 10:d008e6b4d3fd c
1248 |
1248 |
1249 o 9:67e8f4a16c49 b
1249 o 9:67e8f4a16c49 b
1250 |
1250 |
1251 | * 8:2876ce66c6eb g
1251 | * 8:2876ce66c6eb g
1252 | |
1252 | |
1253 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1253 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1254 | | |
1254 | | |
1255 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1255 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1256 | | |
1256 | | |
1257 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1257 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1258 | | |
1258 | | |
1259 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1259 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1260 | |/
1260 | |/
1261 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1261 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1262 | |
1262 | |
1263 o | 2:630d7c95eff7 x
1263 o | 2:630d7c95eff7 x
1264 | |
1264 | |
1265 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1265 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1266 |/
1266 |/
1267 o 0:b173517d0057 a
1267 o 0:b173517d0057 a
1268
1268
1269
1269
1270 issue5782
1270 issue5782
1271 $ hg strip -r 0:
1271 $ hg strip -r 0:
1272 $ hg debugdrawdag <<EOF
1272 $ hg debugdrawdag <<EOF
1273 > d
1273 > d
1274 > |
1274 > |
1275 > c1 c # replace: c -> c1
1275 > c1 c # replace: c -> c1
1276 > \ /
1276 > \ /
1277 > b
1277 > b
1278 > |
1278 > |
1279 > a
1279 > a
1280 > EOF
1280 > EOF
1281 1 new orphan changesets
1281 1 new orphan changesets
1282 $ hg debugobsolete `hg log -T "{node}" --hidden -r 'desc("c1")'`
1282 $ hg debugobsolete `hg log -T "{node}" --hidden -r 'desc("c1")'`
1283 1 new obsolescence markers
1283 1 new obsolescence markers
1284 obsoleted 1 changesets
1284 obsoleted 1 changesets
1285 $ hg log -G -r 'a': --hidden
1285 $ hg log -G -r 'a': --hidden
1286 * 4:76be324c128b d
1286 * 4:76be324c128b d
1287 |
1287 |
1288 | x 3:ef8a456de8fa c1 (pruned)
1288 | x 3:ef8a456de8fa c1 (pruned)
1289 | |
1289 | |
1290 x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa)
1290 x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa)
1291 |/
1291 |/
1292 o 1:488e1b7e7341 b
1292 o 1:488e1b7e7341 b
1293 |
1293 |
1294 o 0:b173517d0057 a
1294 o 0:b173517d0057 a
1295
1295
1296 $ hg rebase -d 0 -r 2
1296 $ hg rebase -d 0 -r 2
1297 rebasing 2:a82ac2b38757 "c" (c)
1297 rebasing 2:a82ac2b38757 "c" (c)
1298 $ hg log -G -r 'a': --hidden
1298 $ hg log -G -r 'a': --hidden
1299 o 5:69ad416a4a26 c
1299 o 5:69ad416a4a26 c
1300 |
1300 |
1301 | * 4:76be324c128b d
1301 | * 4:76be324c128b d
1302 | |
1302 | |
1303 | | x 3:ef8a456de8fa c1 (pruned)
1303 | | x 3:ef8a456de8fa c1 (pruned)
1304 | | |
1304 | | |
1305 | x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa rewritten using rebase as 5:69ad416a4a26)
1305 | x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa rewritten using rebase as 5:69ad416a4a26)
1306 | |/
1306 | |/
1307 | o 1:488e1b7e7341 b
1307 | o 1:488e1b7e7341 b
1308 |/
1308 |/
1309 o 0:b173517d0057 a
1309 o 0:b173517d0057 a
1310
1310
1311 $ cd ..
1311 $ cd ..
1312
1312
1313 Rebase merge where successor of one parent is equal to destination (issue5198)
1313 Rebase merge where successor of one parent is equal to destination (issue5198)
1314
1314
1315 $ hg init p1-succ-is-dest
1315 $ hg init p1-succ-is-dest
1316 $ cd p1-succ-is-dest
1316 $ cd p1-succ-is-dest
1317
1317
1318 $ hg debugdrawdag <<EOF
1318 $ hg debugdrawdag <<EOF
1319 > F
1319 > F
1320 > /|
1320 > /|
1321 > E D B # replace: D -> B
1321 > E D B # replace: D -> B
1322 > \|/
1322 > \|/
1323 > A
1323 > A
1324 > EOF
1324 > EOF
1325 1 new orphan changesets
1325 1 new orphan changesets
1326
1326
1327 $ hg rebase -d B -s D
1327 $ hg rebase -d B -s D
1328 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1328 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1329 rebasing 4:66f1a38021c9 "F" (F tip)
1329 rebasing 4:66f1a38021c9 "F" (F tip)
1330 $ hg log -G
1330 $ hg log -G
1331 o 5:50e9d60b99c6 F
1331 o 5:50e9d60b99c6 F
1332 |\
1332 |\
1333 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:50e9d60b99c6)
1333 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:50e9d60b99c6)
1334 | |/|
1334 | |/|
1335 | o | 3:7fb047a69f22 E
1335 | o | 3:7fb047a69f22 E
1336 | | |
1336 | | |
1337 | | x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1337 | | x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1338 | |/
1338 | |/
1339 o | 1:112478962961 B
1339 o | 1:112478962961 B
1340 |/
1340 |/
1341 o 0:426bada5c675 A
1341 o 0:426bada5c675 A
1342
1342
1343 $ cd ..
1343 $ cd ..
1344
1344
1345 Rebase merge where successor of other parent is equal to destination
1345 Rebase merge where successor of other parent is equal to destination
1346
1346
1347 $ hg init p2-succ-is-dest
1347 $ hg init p2-succ-is-dest
1348 $ cd p2-succ-is-dest
1348 $ cd p2-succ-is-dest
1349
1349
1350 $ hg debugdrawdag <<EOF
1350 $ hg debugdrawdag <<EOF
1351 > F
1351 > F
1352 > /|
1352 > /|
1353 > E D B # replace: E -> B
1353 > E D B # replace: E -> B
1354 > \|/
1354 > \|/
1355 > A
1355 > A
1356 > EOF
1356 > EOF
1357 1 new orphan changesets
1357 1 new orphan changesets
1358
1358
1359 $ hg rebase -d B -s E
1359 $ hg rebase -d B -s E
1360 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1360 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1361 rebasing 4:66f1a38021c9 "F" (F tip)
1361 rebasing 4:66f1a38021c9 "F" (F tip)
1362 $ hg log -G
1362 $ hg log -G
1363 o 5:aae1787dacee F
1363 o 5:aae1787dacee F
1364 |\
1364 |\
1365 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:aae1787dacee)
1365 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:aae1787dacee)
1366 | |/|
1366 | |/|
1367 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1367 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1368 | | |
1368 | | |
1369 | o | 2:b18e25de2cf5 D
1369 | o | 2:b18e25de2cf5 D
1370 | |/
1370 | |/
1371 o / 1:112478962961 B
1371 o / 1:112478962961 B
1372 |/
1372 |/
1373 o 0:426bada5c675 A
1373 o 0:426bada5c675 A
1374
1374
1375 $ cd ..
1375 $ cd ..
1376
1376
1377 Rebase merge where successor of one parent is ancestor of destination
1377 Rebase merge where successor of one parent is ancestor of destination
1378
1378
1379 $ hg init p1-succ-in-dest
1379 $ hg init p1-succ-in-dest
1380 $ cd p1-succ-in-dest
1380 $ cd p1-succ-in-dest
1381
1381
1382 $ hg debugdrawdag <<EOF
1382 $ hg debugdrawdag <<EOF
1383 > F C
1383 > F C
1384 > /| |
1384 > /| |
1385 > E D B # replace: D -> B
1385 > E D B # replace: D -> B
1386 > \|/
1386 > \|/
1387 > A
1387 > A
1388 > EOF
1388 > EOF
1389 1 new orphan changesets
1389 1 new orphan changesets
1390
1390
1391 $ hg rebase -d C -s D
1391 $ hg rebase -d C -s D
1392 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1392 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1393 rebasing 5:66f1a38021c9 "F" (F tip)
1393 rebasing 5:66f1a38021c9 "F" (F tip)
1394
1394
1395 $ hg log -G
1395 $ hg log -G
1396 o 6:0913febf6439 F
1396 o 6:0913febf6439 F
1397 |\
1397 |\
1398 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:0913febf6439)
1398 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:0913febf6439)
1399 | | |
1399 | | |
1400 | o | 4:26805aba1e60 C
1400 | o | 4:26805aba1e60 C
1401 | | |
1401 | | |
1402 o | | 3:7fb047a69f22 E
1402 o | | 3:7fb047a69f22 E
1403 | | |
1403 | | |
1404 +---x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1404 +---x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1405 | |
1405 | |
1406 | o 1:112478962961 B
1406 | o 1:112478962961 B
1407 |/
1407 |/
1408 o 0:426bada5c675 A
1408 o 0:426bada5c675 A
1409
1409
1410 $ cd ..
1410 $ cd ..
1411
1411
1412 Rebase merge where successor of other parent is ancestor of destination
1412 Rebase merge where successor of other parent is ancestor of destination
1413
1413
1414 $ hg init p2-succ-in-dest
1414 $ hg init p2-succ-in-dest
1415 $ cd p2-succ-in-dest
1415 $ cd p2-succ-in-dest
1416
1416
1417 $ hg debugdrawdag <<EOF
1417 $ hg debugdrawdag <<EOF
1418 > F C
1418 > F C
1419 > /| |
1419 > /| |
1420 > E D B # replace: E -> B
1420 > E D B # replace: E -> B
1421 > \|/
1421 > \|/
1422 > A
1422 > A
1423 > EOF
1423 > EOF
1424 1 new orphan changesets
1424 1 new orphan changesets
1425
1425
1426 $ hg rebase -d C -s E
1426 $ hg rebase -d C -s E
1427 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1427 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1428 rebasing 5:66f1a38021c9 "F" (F tip)
1428 rebasing 5:66f1a38021c9 "F" (F tip)
1429 $ hg log -G
1429 $ hg log -G
1430 o 6:c6ab0cc6d220 F
1430 o 6:c6ab0cc6d220 F
1431 |\
1431 |\
1432 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:c6ab0cc6d220)
1432 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:c6ab0cc6d220)
1433 | | |
1433 | | |
1434 | o | 4:26805aba1e60 C
1434 | o | 4:26805aba1e60 C
1435 | | |
1435 | | |
1436 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1436 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1437 | | |
1437 | | |
1438 o---+ 2:b18e25de2cf5 D
1438 o---+ 2:b18e25de2cf5 D
1439 / /
1439 / /
1440 o / 1:112478962961 B
1440 o / 1:112478962961 B
1441 |/
1441 |/
1442 o 0:426bada5c675 A
1442 o 0:426bada5c675 A
1443
1443
1444 $ cd ..
1444 $ cd ..
1445
1445
1446 Rebase merge where successor of one parent is ancestor of destination
1446 Rebase merge where successor of one parent is ancestor of destination
1447
1447
1448 $ hg init p1-succ-in-dest-b
1448 $ hg init p1-succ-in-dest-b
1449 $ cd p1-succ-in-dest-b
1449 $ cd p1-succ-in-dest-b
1450
1450
1451 $ hg debugdrawdag <<EOF
1451 $ hg debugdrawdag <<EOF
1452 > F C
1452 > F C
1453 > /| |
1453 > /| |
1454 > E D B # replace: E -> B
1454 > E D B # replace: E -> B
1455 > \|/
1455 > \|/
1456 > A
1456 > A
1457 > EOF
1457 > EOF
1458 1 new orphan changesets
1458 1 new orphan changesets
1459
1459
1460 $ hg rebase -d C -b F
1460 $ hg rebase -d C -b F
1461 rebasing 2:b18e25de2cf5 "D" (D)
1461 rebasing 2:b18e25de2cf5 "D" (D)
1462 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1462 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1463 rebasing 5:66f1a38021c9 "F" (F tip)
1463 rebasing 5:66f1a38021c9 "F" (F tip)
1464 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1464 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1465 $ hg log -G
1465 $ hg log -G
1466 o 6:8f47515dda15 D
1466 o 6:8f47515dda15 D
1467 |
1467 |
1468 | x 5:66f1a38021c9 F (pruned using rebase)
1468 | x 5:66f1a38021c9 F (pruned using rebase)
1469 | |\
1469 | |\
1470 o | | 4:26805aba1e60 C
1470 o | | 4:26805aba1e60 C
1471 | | |
1471 | | |
1472 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1472 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1473 | | |
1473 | | |
1474 | x | 2:b18e25de2cf5 D (rewritten using rebase as 6:8f47515dda15)
1474 | x | 2:b18e25de2cf5 D (rewritten using rebase as 6:8f47515dda15)
1475 | |/
1475 | |/
1476 o / 1:112478962961 B
1476 o / 1:112478962961 B
1477 |/
1477 |/
1478 o 0:426bada5c675 A
1478 o 0:426bada5c675 A
1479
1479
1480 $ cd ..
1480 $ cd ..
1481
1481
1482 Rebase merge where successor of other parent is ancestor of destination
1482 Rebase merge where successor of other parent is ancestor of destination
1483
1483
1484 $ hg init p2-succ-in-dest-b
1484 $ hg init p2-succ-in-dest-b
1485 $ cd p2-succ-in-dest-b
1485 $ cd p2-succ-in-dest-b
1486
1486
1487 $ hg debugdrawdag <<EOF
1487 $ hg debugdrawdag <<EOF
1488 > F C
1488 > F C
1489 > /| |
1489 > /| |
1490 > E D B # replace: D -> B
1490 > E D B # replace: D -> B
1491 > \|/
1491 > \|/
1492 > A
1492 > A
1493 > EOF
1493 > EOF
1494 1 new orphan changesets
1494 1 new orphan changesets
1495
1495
1496 $ hg rebase -d C -b F
1496 $ hg rebase -d C -b F
1497 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1497 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1498 rebasing 3:7fb047a69f22 "E" (E)
1498 rebasing 3:7fb047a69f22 "E" (E)
1499 rebasing 5:66f1a38021c9 "F" (F tip)
1499 rebasing 5:66f1a38021c9 "F" (F tip)
1500 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1500 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1501
1501
1502 $ hg log -G
1502 $ hg log -G
1503 o 6:533690786a86 E
1503 o 6:533690786a86 E
1504 |
1504 |
1505 | x 5:66f1a38021c9 F (pruned using rebase)
1505 | x 5:66f1a38021c9 F (pruned using rebase)
1506 | |\
1506 | |\
1507 o | | 4:26805aba1e60 C
1507 o | | 4:26805aba1e60 C
1508 | | |
1508 | | |
1509 | | x 3:7fb047a69f22 E (rewritten using rebase as 6:533690786a86)
1509 | | x 3:7fb047a69f22 E (rewritten using rebase as 6:533690786a86)
1510 | | |
1510 | | |
1511 | x | 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1511 | x | 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1512 | |/
1512 | |/
1513 o / 1:112478962961 B
1513 o / 1:112478962961 B
1514 |/
1514 |/
1515 o 0:426bada5c675 A
1515 o 0:426bada5c675 A
1516
1516
1517 $ cd ..
1517 $ cd ..
1518
1518
1519 Rebase merge where extinct node has successor that is not an ancestor of
1519 Rebase merge where extinct node has successor that is not an ancestor of
1520 destination
1520 destination
1521
1521
1522 $ hg init extinct-with-succ-not-in-dest
1522 $ hg init extinct-with-succ-not-in-dest
1523 $ cd extinct-with-succ-not-in-dest
1523 $ cd extinct-with-succ-not-in-dest
1524
1524
1525 $ hg debugdrawdag <<EOF
1525 $ hg debugdrawdag <<EOF
1526 > E C # replace: C -> E
1526 > E C # replace: C -> E
1527 > | |
1527 > | |
1528 > D B
1528 > D B
1529 > |/
1529 > |/
1530 > A
1530 > A
1531 > EOF
1531 > EOF
1532
1532
1533 $ hg rebase -d D -s B
1533 $ hg rebase -d D -s B
1534 rebasing 1:112478962961 "B" (B)
1534 rebasing 1:112478962961 "B" (B)
1535 note: not rebasing 3:26805aba1e60 "C" (C) and its descendants as this would cause divergence
1535 note: not rebasing 3:26805aba1e60 "C" (C) and its descendants as this would cause divergence
1536
1536
1537 $ cd ..
1537 $ cd ..
1538
1538
1539 $ hg init p2-succ-in-dest-c
1539 $ hg init p2-succ-in-dest-c
1540 $ cd p2-succ-in-dest-c
1540 $ cd p2-succ-in-dest-c
1541
1541
1542 The scenario here was that B::D were developed on default. B was queued on
1542 The scenario here was that B::D were developed on default. B was queued on
1543 stable, but amended before being push to hg-committed. C was queued on default,
1543 stable, but amended before being push to hg-committed. C was queued on default,
1544 along with unrelated J.
1544 along with unrelated J.
1545
1545
1546 $ hg debugdrawdag <<EOF
1546 $ hg debugdrawdag <<EOF
1547 > J
1547 > J
1548 > |
1548 > |
1549 > F
1549 > F
1550 > |
1550 > |
1551 > E
1551 > E
1552 > | D
1552 > | D
1553 > | |
1553 > | |
1554 > | C # replace: C -> F
1554 > | C # replace: C -> F
1555 > | | H I # replace: B -> H -> I
1555 > | | H I # replace: B -> H -> I
1556 > | B |/
1556 > | B |/
1557 > |/ G
1557 > |/ G
1558 > A
1558 > A
1559 > EOF
1559 > EOF
1560 1 new orphan changesets
1560 1 new orphan changesets
1561
1561
1562 This strip seems to be the key to avoid an early divergence warning.
1562 This strip seems to be the key to avoid an early divergence warning.
1563 $ hg --config extensions.strip= --hidden strip -qr H
1563 $ hg --config extensions.strip= --hidden strip -qr H
1564 1 new orphan changesets
1564 1 new orphan changesets
1565
1565
1566 $ hg rebase -b 'desc("D")' -d 'desc("J")'
1566 $ hg rebase -b 'desc("D")' -d 'desc("J")'
1567 abort: this rebase will cause divergences from: 112478962961
1567 abort: this rebase will cause divergences from: 112478962961
1568 (to force the rebase please set experimental.evolution.allowdivergence=True)
1568 (to force the rebase please set experimental.evolution.allowdivergence=True)
1569 [255]
1569 [255]
1570
1570
1571 Rebase merge where both parents have successors in destination
1571 Rebase merge where both parents have successors in destination
1572
1572
1573 $ hg init p12-succ-in-dest
1573 $ hg init p12-succ-in-dest
1574 $ cd p12-succ-in-dest
1574 $ cd p12-succ-in-dest
1575 $ hg debugdrawdag <<'EOS'
1575 $ hg debugdrawdag <<'EOS'
1576 > E F
1576 > E F
1577 > /| /| # replace: A -> C
1577 > /| /| # replace: A -> C
1578 > A B C D # replace: B -> D
1578 > A B C D # replace: B -> D
1579 > | |
1579 > | |
1580 > X Y
1580 > X Y
1581 > EOS
1581 > EOS
1582 1 new orphan changesets
1582 1 new orphan changesets
1583 $ hg rebase -r A+B+E -d F
1583 $ hg rebase -r A+B+E -d F
1584 note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C)
1584 note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C)
1585 note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D)
1585 note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D)
1586 rebasing 7:dac5d11c5a7d "E" (E tip)
1586 rebasing 7:dac5d11c5a7d "E" (E tip)
1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1588 [255]
1588 [255]
1589 $ cd ..
1589 $ cd ..
1590
1590
1591 Rebase a non-clean merge. One parent has successor in destination, the other
1591 Rebase a non-clean merge. One parent has successor in destination, the other
1592 parent moves as requested.
1592 parent moves as requested.
1593
1593
1594 $ hg init p1-succ-p2-move
1594 $ hg init p1-succ-p2-move
1595 $ cd p1-succ-p2-move
1595 $ cd p1-succ-p2-move
1596 $ hg debugdrawdag <<'EOS'
1596 $ hg debugdrawdag <<'EOS'
1597 > D Z
1597 > D Z
1598 > /| | # replace: A -> C
1598 > /| | # replace: A -> C
1599 > A B C # D/D = D
1599 > A B C # D/D = D
1600 > EOS
1600 > EOS
1601 1 new orphan changesets
1601 1 new orphan changesets
1602 $ hg rebase -r A+B+D -d Z
1602 $ hg rebase -r A+B+D -d Z
1603 note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C)
1603 note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C)
1604 rebasing 1:fc2b737bb2e5 "B" (B)
1604 rebasing 1:fc2b737bb2e5 "B" (B)
1605 rebasing 3:b8ed089c80ad "D" (D)
1605 rebasing 3:b8ed089c80ad "D" (D)
1606
1606
1607 $ rm .hg/localtags
1607 $ rm .hg/localtags
1608 $ hg log -G
1608 $ hg log -G
1609 o 6:e4f78693cc88 D
1609 o 6:e4f78693cc88 D
1610 |
1610 |
1611 o 5:76840d832e98 B
1611 o 5:76840d832e98 B
1612 |
1612 |
1613 o 4:50e41c1f3950 Z
1613 o 4:50e41c1f3950 Z
1614 |
1614 |
1615 o 2:96cc3511f894 C
1615 o 2:96cc3511f894 C
1616
1616
1617 $ hg files -r tip
1617 $ hg files -r tip
1618 B
1618 B
1619 C
1619 C
1620 D
1620 D
1621 Z
1621 Z
1622
1622
1623 $ cd ..
1623 $ cd ..
1624
1624
1625 $ hg init p1-move-p2-succ
1625 $ hg init p1-move-p2-succ
1626 $ cd p1-move-p2-succ
1626 $ cd p1-move-p2-succ
1627 $ hg debugdrawdag <<'EOS'
1627 $ hg debugdrawdag <<'EOS'
1628 > D Z
1628 > D Z
1629 > /| | # replace: B -> C
1629 > /| | # replace: B -> C
1630 > A B C # D/D = D
1630 > A B C # D/D = D
1631 > EOS
1631 > EOS
1632 1 new orphan changesets
1632 1 new orphan changesets
1633 $ hg rebase -r B+A+D -d Z
1633 $ hg rebase -r B+A+D -d Z
1634 rebasing 0:426bada5c675 "A" (A)
1634 rebasing 0:426bada5c675 "A" (A)
1635 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C)
1635 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C)
1636 rebasing 3:b8ed089c80ad "D" (D)
1636 rebasing 3:b8ed089c80ad "D" (D)
1637
1637
1638 $ rm .hg/localtags
1638 $ rm .hg/localtags
1639 $ hg log -G
1639 $ hg log -G
1640 o 6:1b355ed94d82 D
1640 o 6:1b355ed94d82 D
1641 |
1641 |
1642 o 5:a81a74d764a6 A
1642 o 5:a81a74d764a6 A
1643 |
1643 |
1644 o 4:50e41c1f3950 Z
1644 o 4:50e41c1f3950 Z
1645 |
1645 |
1646 o 2:96cc3511f894 C
1646 o 2:96cc3511f894 C
1647
1647
1648 $ hg files -r tip
1648 $ hg files -r tip
1649 A
1649 A
1650 C
1650 C
1651 D
1651 D
1652 Z
1652 Z
1653
1653
1654 $ cd ..
1654 $ cd ..
1655
1655
1656 Test that bookmark is moved and working dir is updated when all changesets have
1656 Test that bookmark is moved and working dir is updated when all changesets have
1657 equivalents in destination
1657 equivalents in destination
1658 $ hg init rbsrepo && cd rbsrepo
1658 $ hg init rbsrepo && cd rbsrepo
1659 $ echo "[experimental]" > .hg/hgrc
1659 $ echo "[experimental]" > .hg/hgrc
1660 $ echo "evolution=true" >> .hg/hgrc
1660 $ echo "evolution=true" >> .hg/hgrc
1661 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1661 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1662 $ echo root > root && hg ci -Am root
1662 $ echo root > root && hg ci -Am root
1663 adding root
1663 adding root
1664 $ echo a > a && hg ci -Am a
1664 $ echo a > a && hg ci -Am a
1665 adding a
1665 adding a
1666 $ hg up 0
1666 $ hg up 0
1667 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1667 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1668 $ echo b > b && hg ci -Am b
1668 $ echo b > b && hg ci -Am b
1669 adding b
1669 adding b
1670 created new head
1670 created new head
1671 $ hg rebase -r 2 -d 1
1671 $ hg rebase -r 2 -d 1
1672 rebasing 2:1e9a3c00cbe9 "b" (tip)
1672 rebasing 2:1e9a3c00cbe9 "b" (tip)
1673 $ hg log -r . # working dir is at rev 3 (successor of 2)
1673 $ hg log -r . # working dir is at rev 3 (successor of 2)
1674 3:be1832deae9a b (no-eol)
1674 3:be1832deae9a b (no-eol)
1675 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1675 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1676 bookmarking hidden changeset 1e9a3c00cbe9
1676 bookmarking hidden changeset 1e9a3c00cbe9
1677 (hidden revision '1e9a3c00cbe9' was rewritten as: be1832deae9a)
1677 (hidden revision '1e9a3c00cbe9' was rewritten as: be1832deae9a)
1678 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1678 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1680 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol)
1680 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol)
1681 $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1
1681 $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1
1682 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
1682 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
1683 Check that working directory and bookmark was updated to rev 3 although rev 2
1683 Check that working directory and bookmark was updated to rev 3 although rev 2
1684 was skipped
1684 was skipped
1685 $ hg log -r .
1685 $ hg log -r .
1686 3:be1832deae9a b (no-eol)
1686 3:be1832deae9a b (no-eol)
1687 $ hg bookmarks
1687 $ hg bookmarks
1688 mybook 3:be1832deae9a
1688 mybook 3:be1832deae9a
1689 $ hg debugobsolete --rev tip
1689 $ hg debugobsolete --rev tip
1690 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
1690 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
1691
1691
1692 Obsoleted working parent and bookmark could be moved if an ancestor of working
1692 Obsoleted working parent and bookmark could be moved if an ancestor of working
1693 parent gets moved:
1693 parent gets moved:
1694
1694
1695 $ hg init $TESTTMP/ancestor-wd-move
1695 $ hg init $TESTTMP/ancestor-wd-move
1696 $ cd $TESTTMP/ancestor-wd-move
1696 $ cd $TESTTMP/ancestor-wd-move
1697 $ hg debugdrawdag <<'EOS'
1697 $ hg debugdrawdag <<'EOS'
1698 > E D1 # rebase: D1 -> D2
1698 > E D1 # rebase: D1 -> D2
1699 > | |
1699 > | |
1700 > | C
1700 > | C
1701 > D2 |
1701 > D2 |
1702 > | B
1702 > | B
1703 > |/
1703 > |/
1704 > A
1704 > A
1705 > EOS
1705 > EOS
1706 $ hg update D1 -q
1706 $ hg update D1 -q
1707 $ hg bookmark book -i
1707 $ hg bookmark book -i
1708 $ hg rebase -r B+D1 -d E
1708 $ hg rebase -r B+D1 -d E
1709 rebasing 1:112478962961 "B" (B)
1709 rebasing 1:112478962961 "B" (B)
1710 note: not rebasing 5:15ecf15e0114 "D1" (book D1 tip), already in destination as 2:0807738e0be9 "D2" (D2)
1710 note: not rebasing 5:15ecf15e0114 "D1" (book D1 tip), already in destination as 2:0807738e0be9 "D2" (D2)
1711 1 new orphan changesets
1711 1 new orphan changesets
1712 $ hg log -G -T '{desc} {bookmarks}'
1712 $ hg log -G -T '{desc} {bookmarks}'
1713 @ B book
1713 @ B book
1714 |
1714 |
1715 | x D1
1715 | x D1
1716 | |
1716 | |
1717 o | E
1717 o | E
1718 | |
1718 | |
1719 | * C
1719 | * C
1720 | |
1720 | |
1721 o | D2
1721 o | D2
1722 | |
1722 | |
1723 | x B
1723 | x B
1724 |/
1724 |/
1725 o A
1725 o A
1726
1726
1727 Rebasing a merge with one of its parent having a hidden successor
1727 Rebasing a merge with one of its parent having a hidden successor
1728
1728
1729 $ hg init $TESTTMP/merge-p1-hidden-successor
1729 $ hg init $TESTTMP/merge-p1-hidden-successor
1730 $ cd $TESTTMP/merge-p1-hidden-successor
1730 $ cd $TESTTMP/merge-p1-hidden-successor
1731
1731
1732 $ hg debugdrawdag <<'EOS'
1732 $ hg debugdrawdag <<'EOS'
1733 > E
1733 > E
1734 > |
1734 > |
1735 > B3 B2 # amend: B1 -> B2 -> B3
1735 > B3 B2 # amend: B1 -> B2 -> B3
1736 > |/ # B2 is hidden
1736 > |/ # B2 is hidden
1737 > | D
1737 > | D
1738 > | |\
1738 > | |\
1739 > | B1 C
1739 > | B1 C
1740 > |/
1740 > |/
1741 > A
1741 > A
1742 > EOS
1742 > EOS
1743 1 new orphan changesets
1743 1 new orphan changesets
1744
1744
1745 $ eval `hg tags -T '{tag}={node}\n'`
1745 $ eval `hg tags -T '{tag}={node}\n'`
1746 $ rm .hg/localtags
1746 $ rm .hg/localtags
1747
1747
1748 $ hg rebase -r $D -d $E
1748 $ hg rebase -r $D -d $E
1749 rebasing 5:9e62094e4d94 "D"
1749 rebasing 5:9e62094e4d94 "D"
1750
1750
1751 $ hg log -G
1751 $ hg log -G
1752 o 7:a699d059adcf D
1752 o 7:a699d059adcf D
1753 |\
1753 |\
1754 | o 6:ecc93090a95c E
1754 | o 6:ecc93090a95c E
1755 | |
1755 | |
1756 | o 4:0dc878468a23 B3
1756 | o 4:0dc878468a23 B3
1757 | |
1757 | |
1758 o | 1:96cc3511f894 C
1758 o | 1:96cc3511f894 C
1759 /
1759 /
1760 o 0:426bada5c675 A
1760 o 0:426bada5c675 A
1761
1761
1762 For some reasons (--hidden, rebaseskipobsolete=0, directaccess, etc.),
1762 For some reasons (--hidden, rebaseskipobsolete=0, directaccess, etc.),
1763 rebasestate may contain hidden hashes. "rebase --abort" should work regardless.
1763 rebasestate may contain hidden hashes. "rebase --abort" should work regardless.
1764
1764
1765 $ hg init $TESTTMP/hidden-state1
1765 $ hg init $TESTTMP/hidden-state1
1766 $ cd $TESTTMP/hidden-state1
1766 $ cd $TESTTMP/hidden-state1
1767 $ cat >> .hg/hgrc <<EOF
1767 $ cat >> .hg/hgrc <<EOF
1768 > [experimental]
1768 > [experimental]
1769 > rebaseskipobsolete=0
1769 > rebaseskipobsolete=0
1770 > EOF
1770 > EOF
1771
1771
1772 $ hg debugdrawdag <<'EOS'
1772 $ hg debugdrawdag <<'EOS'
1773 > C
1773 > C
1774 > |
1774 > |
1775 > D B # prune: B, C
1775 > D B # prune: B, C
1776 > |/ # B/D=B
1776 > |/ # B/D=B
1777 > A
1777 > A
1778 > EOS
1778 > EOS
1779
1779
1780 $ eval `hg tags -T '{tag}={node}\n'`
1780 $ eval `hg tags -T '{tag}={node}\n'`
1781 $ rm .hg/localtags
1781 $ rm .hg/localtags
1782
1782
1783 $ hg update -q $C --hidden
1783 $ hg update -q $C --hidden
1784 updated to hidden changeset 7829726be4dc
1784 updated to hidden changeset 7829726be4dc
1785 (hidden revision '7829726be4dc' is pruned)
1785 (hidden revision '7829726be4dc' is pruned)
1786 $ hg rebase -s $B -d $D
1786 $ hg rebase -s $B -d $D
1787 rebasing 1:2ec65233581b "B"
1787 rebasing 1:2ec65233581b "B"
1788 merging D
1788 merging D
1789 warning: conflicts while merging D! (edit, then use 'hg resolve --mark')
1789 warning: conflicts while merging D! (edit, then use 'hg resolve --mark')
1790 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1790 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1791 [1]
1791 [1]
1792
1792
1793 $ cp -R . $TESTTMP/hidden-state2
1793 $ cp -R . $TESTTMP/hidden-state2
1794
1794
1795 $ hg log -G
1795 $ hg log -G
1796 @ 2:b18e25de2cf5 D
1796 @ 2:b18e25de2cf5 D
1797 |
1797 |
1798 | % 1:2ec65233581b B (pruned using prune)
1799 |/
1798 o 0:426bada5c675 A
1800 o 0:426bada5c675 A
1799
1801
1800 $ hg summary
1802 $ hg summary
1801 parent: 2:b18e25de2cf5 tip
1803 parent: 2:b18e25de2cf5 tip
1802 D
1804 D
1803 branch: default
1805 branch: default
1804 commit: 1 modified, 1 added, 1 unknown, 1 unresolved
1806 commit: 1 modified, 1 added, 1 unknown, 1 unresolved
1805 update: (current)
1807 update: 1 new changesets, 2 branch heads (merge)
1806 phases: 2 draft
1808 phases: 3 draft
1807 rebase: 0 rebased, 2 remaining (rebase --continue)
1809 rebase: 0 rebased, 2 remaining (rebase --continue)
1808
1810
1809 $ hg rebase --abort
1811 $ hg rebase --abort
1810 rebase aborted
1812 rebase aborted
1811
1813
1812 Also test --continue for the above case
1814 Also test --continue for the above case
1813
1815
1814 $ cd $TESTTMP/hidden-state2
1816 $ cd $TESTTMP/hidden-state2
1815 $ hg resolve -m
1817 $ hg resolve -m
1816 (no more unresolved files)
1818 (no more unresolved files)
1817 continue: hg rebase --continue
1819 continue: hg rebase --continue
1818 $ hg rebase --continue
1820 $ hg rebase --continue
1819 rebasing 1:2ec65233581b "B"
1821 rebasing 1:2ec65233581b "B"
1820 rebasing 3:7829726be4dc "C" (tip)
1822 rebasing 3:7829726be4dc "C" (tip)
1821 $ hg log -G
1823 $ hg log -G
1822 @ 5:1964d5d5b547 C
1824 @ 5:1964d5d5b547 C
1823 |
1825 |
1824 o 4:68deb90c12a2 B
1826 o 4:68deb90c12a2 B
1825 |
1827 |
1826 o 2:b18e25de2cf5 D
1828 o 2:b18e25de2cf5 D
1827 |
1829 |
1828 o 0:426bada5c675 A
1830 o 0:426bada5c675 A
1829
1831
1830 ====================
1832 ====================
1831 Test --stop option |
1833 Test --stop option |
1832 ====================
1834 ====================
1833 $ cd ..
1835 $ cd ..
1834 $ hg init rbstop
1836 $ hg init rbstop
1835 $ cd rbstop
1837 $ cd rbstop
1836 $ echo a>a
1838 $ echo a>a
1837 $ hg ci -Aqma
1839 $ hg ci -Aqma
1838 $ echo b>b
1840 $ echo b>b
1839 $ hg ci -Aqmb
1841 $ hg ci -Aqmb
1840 $ echo c>c
1842 $ echo c>c
1841 $ hg ci -Aqmc
1843 $ hg ci -Aqmc
1842 $ echo d>d
1844 $ echo d>d
1843 $ hg ci -Aqmd
1845 $ hg ci -Aqmd
1844 $ hg up 0 -q
1846 $ hg up 0 -q
1845 $ echo f>f
1847 $ echo f>f
1846 $ hg ci -Aqmf
1848 $ hg ci -Aqmf
1847 $ echo D>d
1849 $ echo D>d
1848 $ hg ci -Aqm "conflict with d"
1850 $ hg ci -Aqm "conflict with d"
1849 $ hg up 3 -q
1851 $ hg up 3 -q
1850 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1852 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1851 o 5:00bfc9898aeb test
1853 o 5:00bfc9898aeb test
1852 | conflict with d
1854 | conflict with d
1853 |
1855 |
1854 o 4:dafd40200f93 test
1856 o 4:dafd40200f93 test
1855 | f
1857 | f
1856 |
1858 |
1857 | @ 3:055a42cdd887 test
1859 | @ 3:055a42cdd887 test
1858 | | d
1860 | | d
1859 | |
1861 | |
1860 | o 2:177f92b77385 test
1862 | o 2:177f92b77385 test
1861 | | c
1863 | | c
1862 | |
1864 | |
1863 | o 1:d2ae7f538514 test
1865 | o 1:d2ae7f538514 test
1864 |/ b
1866 |/ b
1865 |
1867 |
1866 o 0:cb9a9f314b8b test
1868 o 0:cb9a9f314b8b test
1867 a
1869 a
1868
1870
1869 $ hg rebase -s 1 -d 5
1871 $ hg rebase -s 1 -d 5
1870 rebasing 1:d2ae7f538514 "b"
1872 rebasing 1:d2ae7f538514 "b"
1871 rebasing 2:177f92b77385 "c"
1873 rebasing 2:177f92b77385 "c"
1872 rebasing 3:055a42cdd887 "d"
1874 rebasing 3:055a42cdd887 "d"
1873 merging d
1875 merging d
1874 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1876 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1875 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1877 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1876 [1]
1878 [1]
1877 $ hg rebase --stop
1879 $ hg rebase --stop
1878 1 new orphan changesets
1880 1 new orphan changesets
1879 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1881 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1880 o 7:7fffad344617 test
1882 o 7:7fffad344617 test
1881 | c
1883 | c
1882 |
1884 |
1883 o 6:b15528633407 test
1885 o 6:b15528633407 test
1884 | b
1886 | b
1885 |
1887 |
1886 o 5:00bfc9898aeb test
1888 o 5:00bfc9898aeb test
1887 | conflict with d
1889 | conflict with d
1888 |
1890 |
1889 o 4:dafd40200f93 test
1891 o 4:dafd40200f93 test
1890 | f
1892 | f
1891 |
1893 |
1892 | @ 3:055a42cdd887 test
1894 | @ 3:055a42cdd887 test
1893 | | d
1895 | | d
1894 | |
1896 | |
1895 | x 2:177f92b77385 test
1897 | x 2:177f92b77385 test
1896 | | c
1898 | | c
1897 | |
1899 | |
1898 | x 1:d2ae7f538514 test
1900 | x 1:d2ae7f538514 test
1899 |/ b
1901 |/ b
1900 |
1902 |
1901 o 0:cb9a9f314b8b test
1903 o 0:cb9a9f314b8b test
1902 a
1904 a
1903
1905
1904 Test it aborts if unstable csets is not allowed:
1906 Test it aborts if unstable csets is not allowed:
1905 ===============================================
1907 ===============================================
1906 $ cat >> $HGRCPATH << EOF
1908 $ cat >> $HGRCPATH << EOF
1907 > [experimental]
1909 > [experimental]
1908 > evolution.allowunstable=False
1910 > evolution.allowunstable=False
1909 > EOF
1911 > EOF
1910
1912
1911 $ hg strip 6 --no-backup -q
1913 $ hg strip 6 --no-backup -q
1912 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1914 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1913 o 5:00bfc9898aeb test
1915 o 5:00bfc9898aeb test
1914 | conflict with d
1916 | conflict with d
1915 |
1917 |
1916 o 4:dafd40200f93 test
1918 o 4:dafd40200f93 test
1917 | f
1919 | f
1918 |
1920 |
1919 | @ 3:055a42cdd887 test
1921 | @ 3:055a42cdd887 test
1920 | | d
1922 | | d
1921 | |
1923 | |
1922 | o 2:177f92b77385 test
1924 | o 2:177f92b77385 test
1923 | | c
1925 | | c
1924 | |
1926 | |
1925 | o 1:d2ae7f538514 test
1927 | o 1:d2ae7f538514 test
1926 |/ b
1928 |/ b
1927 |
1929 |
1928 o 0:cb9a9f314b8b test
1930 o 0:cb9a9f314b8b test
1929 a
1931 a
1930
1932
1931 $ hg rebase -s 1 -d 5
1933 $ hg rebase -s 1 -d 5
1932 rebasing 1:d2ae7f538514 "b"
1934 rebasing 1:d2ae7f538514 "b"
1933 rebasing 2:177f92b77385 "c"
1935 rebasing 2:177f92b77385 "c"
1934 rebasing 3:055a42cdd887 "d"
1936 rebasing 3:055a42cdd887 "d"
1935 merging d
1937 merging d
1936 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1938 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1937 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1939 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1938 [1]
1940 [1]
1939 $ hg rebase --stop
1941 $ hg rebase --stop
1940 abort: cannot remove original changesets with unrebased descendants
1942 abort: cannot remove original changesets with unrebased descendants
1941 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1943 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1942 [255]
1944 [255]
1943 $ hg rebase --abort
1945 $ hg rebase --abort
1944 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1946 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1945 rebase aborted
1947 rebase aborted
1946
1948
1947 Test --stop when --keep is passed:
1949 Test --stop when --keep is passed:
1948 ==================================
1950 ==================================
1949 $ hg rebase -s 1 -d 5 --keep
1951 $ hg rebase -s 1 -d 5 --keep
1950 rebasing 1:d2ae7f538514 "b"
1952 rebasing 1:d2ae7f538514 "b"
1951 rebasing 2:177f92b77385 "c"
1953 rebasing 2:177f92b77385 "c"
1952 rebasing 3:055a42cdd887 "d"
1954 rebasing 3:055a42cdd887 "d"
1953 merging d
1955 merging d
1954 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1956 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1955 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1957 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1956 [1]
1958 [1]
1957 $ hg rebase --stop
1959 $ hg rebase --stop
1958 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1960 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1959 o 7:7fffad344617 test
1961 o 7:7fffad344617 test
1960 | c
1962 | c
1961 |
1963 |
1962 o 6:b15528633407 test
1964 o 6:b15528633407 test
1963 | b
1965 | b
1964 |
1966 |
1965 o 5:00bfc9898aeb test
1967 o 5:00bfc9898aeb test
1966 | conflict with d
1968 | conflict with d
1967 |
1969 |
1968 o 4:dafd40200f93 test
1970 o 4:dafd40200f93 test
1969 | f
1971 | f
1970 |
1972 |
1971 | @ 3:055a42cdd887 test
1973 | @ 3:055a42cdd887 test
1972 | | d
1974 | | d
1973 | |
1975 | |
1974 | o 2:177f92b77385 test
1976 | o 2:177f92b77385 test
1975 | | c
1977 | | c
1976 | |
1978 | |
1977 | o 1:d2ae7f538514 test
1979 | o 1:d2ae7f538514 test
1978 |/ b
1980 |/ b
1979 |
1981 |
1980 o 0:cb9a9f314b8b test
1982 o 0:cb9a9f314b8b test
1981 a
1983 a
1982
1984
1983 Test --stop aborts when --collapse was passed:
1985 Test --stop aborts when --collapse was passed:
1984 =============================================
1986 =============================================
1985 $ cat >> $HGRCPATH << EOF
1987 $ cat >> $HGRCPATH << EOF
1986 > [experimental]
1988 > [experimental]
1987 > evolution.allowunstable=True
1989 > evolution.allowunstable=True
1988 > EOF
1990 > EOF
1989
1991
1990 $ hg strip 6
1992 $ hg strip 6
1991 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1993 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1992 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1994 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1993 o 5:00bfc9898aeb test
1995 o 5:00bfc9898aeb test
1994 | conflict with d
1996 | conflict with d
1995 |
1997 |
1996 o 4:dafd40200f93 test
1998 o 4:dafd40200f93 test
1997 | f
1999 | f
1998 |
2000 |
1999 | @ 3:055a42cdd887 test
2001 | @ 3:055a42cdd887 test
2000 | | d
2002 | | d
2001 | |
2003 | |
2002 | o 2:177f92b77385 test
2004 | o 2:177f92b77385 test
2003 | | c
2005 | | c
2004 | |
2006 | |
2005 | o 1:d2ae7f538514 test
2007 | o 1:d2ae7f538514 test
2006 |/ b
2008 |/ b
2007 |
2009 |
2008 o 0:cb9a9f314b8b test
2010 o 0:cb9a9f314b8b test
2009 a
2011 a
2010
2012
2011 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2013 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2012 rebasing 1:d2ae7f538514 "b"
2014 rebasing 1:d2ae7f538514 "b"
2013 rebasing 2:177f92b77385 "c"
2015 rebasing 2:177f92b77385 "c"
2014 rebasing 3:055a42cdd887 "d"
2016 rebasing 3:055a42cdd887 "d"
2015 merging d
2017 merging d
2016 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2018 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2017 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2019 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2018 [1]
2020 [1]
2019 $ hg rebase --stop
2021 $ hg rebase --stop
2020 abort: cannot stop in --collapse session
2022 abort: cannot stop in --collapse session
2021 [255]
2023 [255]
2022 $ hg rebase --abort
2024 $ hg rebase --abort
2023 rebase aborted
2025 rebase aborted
2024 $ hg diff
2026 $ hg diff
2025 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2027 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2026 o 5:00bfc9898aeb test
2028 o 5:00bfc9898aeb test
2027 | conflict with d
2029 | conflict with d
2028 |
2030 |
2029 o 4:dafd40200f93 test
2031 o 4:dafd40200f93 test
2030 | f
2032 | f
2031 |
2033 |
2032 | @ 3:055a42cdd887 test
2034 | @ 3:055a42cdd887 test
2033 | | d
2035 | | d
2034 | |
2036 | |
2035 | o 2:177f92b77385 test
2037 | o 2:177f92b77385 test
2036 | | c
2038 | | c
2037 | |
2039 | |
2038 | o 1:d2ae7f538514 test
2040 | o 1:d2ae7f538514 test
2039 |/ b
2041 |/ b
2040 |
2042 |
2041 o 0:cb9a9f314b8b test
2043 o 0:cb9a9f314b8b test
2042 a
2044 a
2043
2045
2044 Test --stop raise errors with conflicting options:
2046 Test --stop raise errors with conflicting options:
2045 =================================================
2047 =================================================
2046 $ hg rebase -s 3 -d 5
2048 $ hg rebase -s 3 -d 5
2047 rebasing 3:055a42cdd887 "d"
2049 rebasing 3:055a42cdd887 "d"
2048 merging d
2050 merging d
2049 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2051 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2050 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2052 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2051 [1]
2053 [1]
2052 $ hg rebase --stop --dry-run
2054 $ hg rebase --stop --dry-run
2053 abort: cannot specify both --stop and --dry-run
2055 abort: cannot specify both --stop and --dry-run
2054 [255]
2056 [255]
2055
2057
2056 $ hg rebase -s 3 -d 5
2058 $ hg rebase -s 3 -d 5
2057 abort: rebase in progress
2059 abort: rebase in progress
2058 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
2060 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
2059 [255]
2061 [255]
2060 $ hg rebase --stop --continue
2062 $ hg rebase --stop --continue
2061 abort: cannot specify both --stop and --continue
2063 abort: cannot specify both --stop and --continue
2062 [255]
2064 [255]
2063
2065
2064 Test --stop moves bookmarks of original revisions to new rebased nodes:
2066 Test --stop moves bookmarks of original revisions to new rebased nodes:
2065 ======================================================================
2067 ======================================================================
2066 $ cd ..
2068 $ cd ..
2067 $ hg init repo
2069 $ hg init repo
2068 $ cd repo
2070 $ cd repo
2069
2071
2070 $ echo a > a
2072 $ echo a > a
2071 $ hg ci -Am A
2073 $ hg ci -Am A
2072 adding a
2074 adding a
2073
2075
2074 $ echo b > b
2076 $ echo b > b
2075 $ hg ci -Am B
2077 $ hg ci -Am B
2076 adding b
2078 adding b
2077 $ hg book X
2079 $ hg book X
2078 $ hg book Y
2080 $ hg book Y
2079
2081
2080 $ echo c > c
2082 $ echo c > c
2081 $ hg ci -Am C
2083 $ hg ci -Am C
2082 adding c
2084 adding c
2083 $ hg book Z
2085 $ hg book Z
2084
2086
2085 $ echo d > d
2087 $ echo d > d
2086 $ hg ci -Am D
2088 $ hg ci -Am D
2087 adding d
2089 adding d
2088
2090
2089 $ hg up 0 -q
2091 $ hg up 0 -q
2090 $ echo e > e
2092 $ echo e > e
2091 $ hg ci -Am E
2093 $ hg ci -Am E
2092 adding e
2094 adding e
2093 created new head
2095 created new head
2094
2096
2095 $ echo doubt > d
2097 $ echo doubt > d
2096 $ hg ci -Am "conflict with d"
2098 $ hg ci -Am "conflict with d"
2097 adding d
2099 adding d
2098
2100
2099 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2101 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2100 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2102 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2101 |
2103 |
2102 o 4: 9c1e55f411b6 'E' bookmarks:
2104 o 4: 9c1e55f411b6 'E' bookmarks:
2103 |
2105 |
2104 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2106 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2105 | |
2107 | |
2106 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2108 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2107 | |
2109 | |
2108 | o 1: 6c81ed0049f8 'B' bookmarks: X
2110 | o 1: 6c81ed0049f8 'B' bookmarks: X
2109 |/
2111 |/
2110 o 0: 1994f17a630e 'A' bookmarks:
2112 o 0: 1994f17a630e 'A' bookmarks:
2111
2113
2112 $ hg rebase -s 1 -d 5
2114 $ hg rebase -s 1 -d 5
2113 rebasing 1:6c81ed0049f8 "B" (X)
2115 rebasing 1:6c81ed0049f8 "B" (X)
2114 rebasing 2:49cb3485fa0c "C" (Y)
2116 rebasing 2:49cb3485fa0c "C" (Y)
2115 rebasing 3:67a385d4e6f2 "D" (Z)
2117 rebasing 3:67a385d4e6f2 "D" (Z)
2116 merging d
2118 merging d
2117 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2119 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2118 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2120 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2119 [1]
2121 [1]
2120 $ hg rebase --stop
2122 $ hg rebase --stop
2121 1 new orphan changesets
2123 1 new orphan changesets
2122 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2124 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2123 o 7: 9c86c650b686 'C' bookmarks: Y
2125 o 7: 9c86c650b686 'C' bookmarks: Y
2124 |
2126 |
2125 o 6: 9b87b54e5fd8 'B' bookmarks: X
2127 o 6: 9b87b54e5fd8 'B' bookmarks: X
2126 |
2128 |
2127 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2129 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2128 |
2130 |
2129 o 4: 9c1e55f411b6 'E' bookmarks:
2131 o 4: 9c1e55f411b6 'E' bookmarks:
2130 |
2132 |
2131 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2133 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2132 | |
2134 | |
2133 | x 2: 49cb3485fa0c 'C' bookmarks:
2135 | x 2: 49cb3485fa0c 'C' bookmarks:
2134 | |
2136 | |
2135 | x 1: 6c81ed0049f8 'B' bookmarks:
2137 | x 1: 6c81ed0049f8 'B' bookmarks:
2136 |/
2138 |/
2137 o 0: 1994f17a630e 'A' bookmarks:
2139 o 0: 1994f17a630e 'A' bookmarks:
2138
2140
General Comments 0
You need to be logged in to leave comments. Login now