##// END OF EJS Templates
destutil: if wdp is obsolete, update to the closest non-obsolete ancestor...
av6 -
r49538:fbf7e383 default
parent child Browse files
Show More
@@ -1,493 +1,496 b''
1 # destutil.py - Mercurial utility function for command destination
1 # destutil.py - Mercurial utility function for command destination
2 #
2 #
3 # Copyright Olivia Mackall <olivia@selenic.com> and other
3 # Copyright Olivia Mackall <olivia@selenic.com> and other
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 from .i18n import _
10 from .i18n import _
11 from . import bookmarks, error, obsutil, scmutil, stack
11 from . import bookmarks, error, obsutil, scmutil, stack
12
12
13
13
14 def orphanpossibledestination(repo, rev):
14 def orphanpossibledestination(repo, rev):
15 """Return all changesets that may be a new parent for orphan `rev`.
15 """Return all changesets that may be a new parent for orphan `rev`.
16
16
17 This function works fine on non-orphan revisions, it's just silly
17 This function works fine on non-orphan revisions, it's just silly
18 because there's no destination implied by obsolete markers, so
18 because there's no destination implied by obsolete markers, so
19 it'll return nothing.
19 it'll return nothing.
20 """
20 """
21 tonode = repo.changelog.node
21 tonode = repo.changelog.node
22 parents = repo.changelog.parentrevs
22 parents = repo.changelog.parentrevs
23 torev = repo.changelog.rev
23 torev = repo.changelog.rev
24 dest = set()
24 dest = set()
25 tovisit = list(parents(rev))
25 tovisit = list(parents(rev))
26 while tovisit:
26 while tovisit:
27 r = tovisit.pop()
27 r = tovisit.pop()
28 succsets = obsutil.successorssets(repo, tonode(r))
28 succsets = obsutil.successorssets(repo, tonode(r))
29 if not succsets:
29 if not succsets:
30 # if there are no successors for r, r was probably pruned
30 # if there are no successors for r, r was probably pruned
31 # and we should walk up to r's parents to try and find
31 # and we should walk up to r's parents to try and find
32 # some successors.
32 # some successors.
33 tovisit.extend(parents(r))
33 tovisit.extend(parents(r))
34 else:
34 else:
35 # We should probably pick only one destination from split
35 # We should probably pick only one destination from split
36 # (case where '1 < len(ss)'), This could be the currently
36 # (case where '1 < len(ss)'), This could be the currently
37 # tipmost, but the correct result is less clear when
37 # tipmost, but the correct result is less clear when
38 # results of the split have been moved such that they
38 # results of the split have been moved such that they
39 # reside on multiple branches.
39 # reside on multiple branches.
40 for ss in succsets:
40 for ss in succsets:
41 for n in ss:
41 for n in ss:
42 dr = torev(n)
42 dr = torev(n)
43 if dr != -1:
43 if dr != -1:
44 dest.add(dr)
44 dest.add(dr)
45 return dest
45 return dest
46
46
47
47
48 def _destupdateobs(repo, clean):
48 def _destupdateobs(repo, clean):
49 """decide of an update destination from obsolescence markers"""
49 """decide of an update destination from obsolescence markers"""
50 node = None
50 node = None
51 wc = repo[None]
51 wc = repo[None]
52 p1 = wc.p1()
52 p1 = wc.p1()
53 movemark = None
53 movemark = None
54
54
55 if p1.obsolete() and not p1.children():
55 if p1.obsolete() and not p1.children():
56 # allow updating to successors
56 # allow updating to successors
57 successors = obsutil.successorssets(repo, p1.node())
57 successors = obsutil.successorssets(repo, p1.node())
58
58
59 # behavior of certain cases is as follows,
59 # behavior of certain cases is as follows,
60 #
60 #
61 # divergent changesets: update to highest rev, similar to what
61 # divergent changesets: update to highest rev, similar to what
62 # is currently done when there are more than one head
62 # is currently done when there are more than one head
63 # (i.e. 'tip')
63 # (i.e. 'tip')
64 #
64 #
65 # replaced changesets: same as divergent except we know there
65 # replaced changesets: same as divergent except we know there
66 # is no conflict
66 # is no conflict
67 #
67 #
68 # pruned changeset: no update is done; though, we could
68 # pruned changeset: update to the closest non-obsolete ancestor,
69 # consider updating to the first non-obsolete parent,
69 # similar to what 'hg prune' currently does
70 # similar to what is current done for 'hg prune'
71
70
72 if successors:
71 if successors:
73 # flatten the list here handles both divergent (len > 1)
72 # flatten the list here handles both divergent (len > 1)
74 # and the usual case (len = 1)
73 # and the usual case (len = 1)
75 successors = [n for sub in successors for n in sub]
74 successors = [n for sub in successors for n in sub]
76
75
77 # get the max revision for the given successors set,
76 # get the max revision for the given successors set,
78 # i.e. the 'tip' of a set
77 # i.e. the 'tip' of a set
79 node = repo.revs(b'max(%ln)', successors).first()
78 node = repo.revs(b'max(%ln)', successors).first()
80 if bookmarks.isactivewdirparent(repo):
81 movemark = repo[b'.'].node()
82 else:
79 else:
83 # TODO: copy hg prune logic
80 p1 = p1.p1()
84 node = repo[b'.'].node()
81 while p1.obsolete():
82 p1 = p1.p1()
83 node = p1.node()
84
85 if node is not None and bookmarks.isactivewdirparent(repo):
86 movemark = repo[b'.'].node()
87
85 return node, movemark, None
88 return node, movemark, None
86
89
87
90
88 def _destupdatebook(repo, clean):
91 def _destupdatebook(repo, clean):
89 """decide on an update destination from active bookmark"""
92 """decide on an update destination from active bookmark"""
90 # we also move the active bookmark, if any
93 # we also move the active bookmark, if any
91 node = None
94 node = None
92 activemark, movemark = bookmarks.calculateupdate(repo.ui, repo)
95 activemark, movemark = bookmarks.calculateupdate(repo.ui, repo)
93 if activemark is not None:
96 if activemark is not None:
94 node = repo._bookmarks[activemark]
97 node = repo._bookmarks[activemark]
95 return node, movemark, activemark
98 return node, movemark, activemark
96
99
97
100
98 def _destupdatebranch(repo, clean):
101 def _destupdatebranch(repo, clean):
99 """decide on an update destination from current branch
102 """decide on an update destination from current branch
100
103
101 This ignores closed branch heads.
104 This ignores closed branch heads.
102 """
105 """
103 wc = repo[None]
106 wc = repo[None]
104 movemark = node = None
107 movemark = node = None
105 currentbranch = wc.branch()
108 currentbranch = wc.branch()
106
109
107 if clean:
110 if clean:
108 currentbranch = repo[b'.'].branch()
111 currentbranch = repo[b'.'].branch()
109
112
110 if currentbranch in repo.branchmap():
113 if currentbranch in repo.branchmap():
111 heads = repo.branchheads(currentbranch)
114 heads = repo.branchheads(currentbranch)
112 if heads:
115 if heads:
113 node = repo.revs(b'max(.::(%ln))', heads).first()
116 node = repo.revs(b'max(.::(%ln))', heads).first()
114 if bookmarks.isactivewdirparent(repo):
117 if bookmarks.isactivewdirparent(repo):
115 movemark = repo[b'.'].node()
118 movemark = repo[b'.'].node()
116 elif currentbranch == b'default' and not wc.p1():
119 elif currentbranch == b'default' and not wc.p1():
117 # "null" parent belongs to "default" branch, but it doesn't exist, so
120 # "null" parent belongs to "default" branch, but it doesn't exist, so
118 # update to the tipmost non-closed branch head
121 # update to the tipmost non-closed branch head
119 node = repo.revs(b'max(head() and not closed())').first()
122 node = repo.revs(b'max(head() and not closed())').first()
120 else:
123 else:
121 node = repo[b'.'].node()
124 node = repo[b'.'].node()
122 return node, movemark, None
125 return node, movemark, None
123
126
124
127
125 def _destupdatebranchfallback(repo, clean):
128 def _destupdatebranchfallback(repo, clean):
126 """decide on an update destination from closed heads in current branch"""
129 """decide on an update destination from closed heads in current branch"""
127 wc = repo[None]
130 wc = repo[None]
128 currentbranch = wc.branch()
131 currentbranch = wc.branch()
129 movemark = None
132 movemark = None
130 if currentbranch in repo.branchmap():
133 if currentbranch in repo.branchmap():
131 # here, all descendant branch heads are closed
134 # here, all descendant branch heads are closed
132 heads = repo.branchheads(currentbranch, closed=True)
135 heads = repo.branchheads(currentbranch, closed=True)
133 assert heads, b"any branch has at least one head"
136 assert heads, b"any branch has at least one head"
134 node = repo.revs(b'max(.::(%ln))', heads).first()
137 node = repo.revs(b'max(.::(%ln))', heads).first()
135 assert (
138 assert (
136 node is not None
139 node is not None
137 ), b"any revision has at least one descendant branch head"
140 ), b"any revision has at least one descendant branch head"
138 if bookmarks.isactivewdirparent(repo):
141 if bookmarks.isactivewdirparent(repo):
139 movemark = repo[b'.'].node()
142 movemark = repo[b'.'].node()
140 else:
143 else:
141 # here, no "default" branch, and all branches are closed
144 # here, no "default" branch, and all branches are closed
142 node = repo.lookup(b'tip')
145 node = repo.lookup(b'tip')
143 assert node is not None, b"'tip' exists even in empty repository"
146 assert node is not None, b"'tip' exists even in empty repository"
144 return node, movemark, None
147 return node, movemark, None
145
148
146
149
147 # order in which each step should be evaluated
150 # order in which each step should be evaluated
148 # steps are run until one finds a destination
151 # steps are run until one finds a destination
149 destupdatesteps = [b'evolution', b'bookmark', b'branch', b'branchfallback']
152 destupdatesteps = [b'evolution', b'bookmark', b'branch', b'branchfallback']
150 # mapping to ease extension overriding steps.
153 # mapping to ease extension overriding steps.
151 destupdatestepmap = {
154 destupdatestepmap = {
152 b'evolution': _destupdateobs,
155 b'evolution': _destupdateobs,
153 b'bookmark': _destupdatebook,
156 b'bookmark': _destupdatebook,
154 b'branch': _destupdatebranch,
157 b'branch': _destupdatebranch,
155 b'branchfallback': _destupdatebranchfallback,
158 b'branchfallback': _destupdatebranchfallback,
156 }
159 }
157
160
158
161
159 def destupdate(repo, clean=False):
162 def destupdate(repo, clean=False):
160 """destination for bare update operation
163 """destination for bare update operation
161
164
162 return (rev, movemark, activemark)
165 return (rev, movemark, activemark)
163
166
164 - rev: the revision to update to,
167 - rev: the revision to update to,
165 - movemark: node to move the active bookmark from
168 - movemark: node to move the active bookmark from
166 (cf bookmark.calculate update),
169 (cf bookmark.calculate update),
167 - activemark: a bookmark to activate at the end of the update.
170 - activemark: a bookmark to activate at the end of the update.
168 """
171 """
169 node = movemark = activemark = None
172 node = movemark = activemark = None
170
173
171 for step in destupdatesteps:
174 for step in destupdatesteps:
172 node, movemark, activemark = destupdatestepmap[step](repo, clean)
175 node, movemark, activemark = destupdatestepmap[step](repo, clean)
173 if node is not None:
176 if node is not None:
174 break
177 break
175 rev = repo[node].rev()
178 rev = repo[node].rev()
176
179
177 return rev, movemark, activemark
180 return rev, movemark, activemark
178
181
179
182
180 msgdestmerge = {
183 msgdestmerge = {
181 # too many matching divergent bookmark
184 # too many matching divergent bookmark
182 b'toomanybookmarks': {
185 b'toomanybookmarks': {
183 b'merge': (
186 b'merge': (
184 _(
187 _(
185 b"multiple matching bookmarks to merge -"
188 b"multiple matching bookmarks to merge -"
186 b" please merge with an explicit rev or bookmark"
189 b" please merge with an explicit rev or bookmark"
187 ),
190 ),
188 _(b"run 'hg heads' to see all heads, specify rev with -r"),
191 _(b"run 'hg heads' to see all heads, specify rev with -r"),
189 ),
192 ),
190 b'rebase': (
193 b'rebase': (
191 _(
194 _(
192 b"multiple matching bookmarks to rebase -"
195 b"multiple matching bookmarks to rebase -"
193 b" please rebase to an explicit rev or bookmark"
196 b" please rebase to an explicit rev or bookmark"
194 ),
197 ),
195 _(b"run 'hg heads' to see all heads, specify destination with -d"),
198 _(b"run 'hg heads' to see all heads, specify destination with -d"),
196 ),
199 ),
197 },
200 },
198 # no other matching divergent bookmark
201 # no other matching divergent bookmark
199 b'nootherbookmarks': {
202 b'nootherbookmarks': {
200 b'merge': (
203 b'merge': (
201 _(
204 _(
202 b"no matching bookmark to merge - "
205 b"no matching bookmark to merge - "
203 b"please merge with an explicit rev or bookmark"
206 b"please merge with an explicit rev or bookmark"
204 ),
207 ),
205 _(b"run 'hg heads' to see all heads, specify rev with -r"),
208 _(b"run 'hg heads' to see all heads, specify rev with -r"),
206 ),
209 ),
207 b'rebase': (
210 b'rebase': (
208 _(
211 _(
209 b"no matching bookmark to rebase - "
212 b"no matching bookmark to rebase - "
210 b"please rebase to an explicit rev or bookmark"
213 b"please rebase to an explicit rev or bookmark"
211 ),
214 ),
212 _(b"run 'hg heads' to see all heads, specify destination with -d"),
215 _(b"run 'hg heads' to see all heads, specify destination with -d"),
213 ),
216 ),
214 },
217 },
215 # branch have too many unbookmarked heads, no obvious destination
218 # branch have too many unbookmarked heads, no obvious destination
216 b'toomanyheads': {
219 b'toomanyheads': {
217 b'merge': (
220 b'merge': (
218 _(b"branch '%s' has %d heads - please merge with an explicit rev"),
221 _(b"branch '%s' has %d heads - please merge with an explicit rev"),
219 _(b"run 'hg heads .' to see heads, specify rev with -r"),
222 _(b"run 'hg heads .' to see heads, specify rev with -r"),
220 ),
223 ),
221 b'rebase': (
224 b'rebase': (
222 _(b"branch '%s' has %d heads - please rebase to an explicit rev"),
225 _(b"branch '%s' has %d heads - please rebase to an explicit rev"),
223 _(b"run 'hg heads .' to see heads, specify destination with -d"),
226 _(b"run 'hg heads .' to see heads, specify destination with -d"),
224 ),
227 ),
225 },
228 },
226 # branch have no other unbookmarked heads
229 # branch have no other unbookmarked heads
227 b'bookmarkedheads': {
230 b'bookmarkedheads': {
228 b'merge': (
231 b'merge': (
229 _(b"heads are bookmarked - please merge with an explicit rev"),
232 _(b"heads are bookmarked - please merge with an explicit rev"),
230 _(b"run 'hg heads' to see all heads, specify rev with -r"),
233 _(b"run 'hg heads' to see all heads, specify rev with -r"),
231 ),
234 ),
232 b'rebase': (
235 b'rebase': (
233 _(b"heads are bookmarked - please rebase to an explicit rev"),
236 _(b"heads are bookmarked - please rebase to an explicit rev"),
234 _(b"run 'hg heads' to see all heads, specify destination with -d"),
237 _(b"run 'hg heads' to see all heads, specify destination with -d"),
235 ),
238 ),
236 },
239 },
237 # branch have just a single heads, but there is other branches
240 # branch have just a single heads, but there is other branches
238 b'nootherbranchheads': {
241 b'nootherbranchheads': {
239 b'merge': (
242 b'merge': (
240 _(b"branch '%s' has one head - please merge with an explicit rev"),
243 _(b"branch '%s' has one head - please merge with an explicit rev"),
241 _(b"run 'hg heads' to see all heads, specify rev with -r"),
244 _(b"run 'hg heads' to see all heads, specify rev with -r"),
242 ),
245 ),
243 b'rebase': (
246 b'rebase': (
244 _(b"branch '%s' has one head - please rebase to an explicit rev"),
247 _(b"branch '%s' has one head - please rebase to an explicit rev"),
245 _(b"run 'hg heads' to see all heads, specify destination with -d"),
248 _(b"run 'hg heads' to see all heads, specify destination with -d"),
246 ),
249 ),
247 },
250 },
248 # repository have a single head
251 # repository have a single head
249 b'nootherheads': {
252 b'nootherheads': {
250 b'merge': (_(b'nothing to merge'), None),
253 b'merge': (_(b'nothing to merge'), None),
251 b'rebase': (_(b'nothing to rebase'), None),
254 b'rebase': (_(b'nothing to rebase'), None),
252 },
255 },
253 # repository have a single head and we are not on it
256 # repository have a single head and we are not on it
254 b'nootherheadsbehind': {
257 b'nootherheadsbehind': {
255 b'merge': (_(b'nothing to merge'), _(b"use 'hg update' instead")),
258 b'merge': (_(b'nothing to merge'), _(b"use 'hg update' instead")),
256 b'rebase': (_(b'nothing to rebase'), _(b"use 'hg update' instead")),
259 b'rebase': (_(b'nothing to rebase'), _(b"use 'hg update' instead")),
257 },
260 },
258 # We are not on a head
261 # We are not on a head
259 b'notatheads': {
262 b'notatheads': {
260 b'merge': (
263 b'merge': (
261 _(b'working directory not at a head revision'),
264 _(b'working directory not at a head revision'),
262 _(b"use 'hg update' or merge with an explicit revision"),
265 _(b"use 'hg update' or merge with an explicit revision"),
263 ),
266 ),
264 b'rebase': (
267 b'rebase': (
265 _(b'working directory not at a head revision'),
268 _(b'working directory not at a head revision'),
266 _(b"use 'hg update' or rebase to an explicit revision"),
269 _(b"use 'hg update' or rebase to an explicit revision"),
267 ),
270 ),
268 },
271 },
269 b'emptysourceset': {
272 b'emptysourceset': {
270 b'merge': (_(b'source set is empty'), None),
273 b'merge': (_(b'source set is empty'), None),
271 b'rebase': (_(b'source set is empty'), None),
274 b'rebase': (_(b'source set is empty'), None),
272 },
275 },
273 b'multiplebranchessourceset': {
276 b'multiplebranchessourceset': {
274 b'merge': (_(b'source set is rooted in multiple branches'), None),
277 b'merge': (_(b'source set is rooted in multiple branches'), None),
275 b'rebase': (
278 b'rebase': (
276 _(b'rebaseset is rooted in multiple named branches'),
279 _(b'rebaseset is rooted in multiple named branches'),
277 _(b'specify an explicit destination with --dest'),
280 _(b'specify an explicit destination with --dest'),
278 ),
281 ),
279 },
282 },
280 }
283 }
281
284
282
285
283 def _destmergebook(repo, action=b'merge', sourceset=None, destspace=None):
286 def _destmergebook(repo, action=b'merge', sourceset=None, destspace=None):
284 """find merge destination in the active bookmark case"""
287 """find merge destination in the active bookmark case"""
285 node = None
288 node = None
286 bmheads = bookmarks.headsforactive(repo)
289 bmheads = bookmarks.headsforactive(repo)
287 curhead = repo._bookmarks[repo._activebookmark]
290 curhead = repo._bookmarks[repo._activebookmark]
288 if len(bmheads) == 2:
291 if len(bmheads) == 2:
289 if curhead == bmheads[0]:
292 if curhead == bmheads[0]:
290 node = bmheads[1]
293 node = bmheads[1]
291 else:
294 else:
292 node = bmheads[0]
295 node = bmheads[0]
293 elif len(bmheads) > 2:
296 elif len(bmheads) > 2:
294 msg, hint = msgdestmerge[b'toomanybookmarks'][action]
297 msg, hint = msgdestmerge[b'toomanybookmarks'][action]
295 raise error.ManyMergeDestAbort(msg, hint=hint)
298 raise error.ManyMergeDestAbort(msg, hint=hint)
296 elif len(bmheads) <= 1:
299 elif len(bmheads) <= 1:
297 msg, hint = msgdestmerge[b'nootherbookmarks'][action]
300 msg, hint = msgdestmerge[b'nootherbookmarks'][action]
298 raise error.NoMergeDestAbort(msg, hint=hint)
301 raise error.NoMergeDestAbort(msg, hint=hint)
299 assert node is not None
302 assert node is not None
300 return node
303 return node
301
304
302
305
303 def _destmergebranch(
306 def _destmergebranch(
304 repo, action=b'merge', sourceset=None, onheadcheck=True, destspace=None
307 repo, action=b'merge', sourceset=None, onheadcheck=True, destspace=None
305 ):
308 ):
306 """find merge destination based on branch heads"""
309 """find merge destination based on branch heads"""
307 node = None
310 node = None
308
311
309 if sourceset is None:
312 if sourceset is None:
310 sourceset = [repo[repo.dirstate.p1()].rev()]
313 sourceset = [repo[repo.dirstate.p1()].rev()]
311 branch = repo.dirstate.branch()
314 branch = repo.dirstate.branch()
312 elif not sourceset:
315 elif not sourceset:
313 msg, hint = msgdestmerge[b'emptysourceset'][action]
316 msg, hint = msgdestmerge[b'emptysourceset'][action]
314 raise error.NoMergeDestAbort(msg, hint=hint)
317 raise error.NoMergeDestAbort(msg, hint=hint)
315 else:
318 else:
316 branch = None
319 branch = None
317 for ctx in repo.set(b'roots(%ld::%ld)', sourceset, sourceset):
320 for ctx in repo.set(b'roots(%ld::%ld)', sourceset, sourceset):
318 if branch is not None and ctx.branch() != branch:
321 if branch is not None and ctx.branch() != branch:
319 msg, hint = msgdestmerge[b'multiplebranchessourceset'][action]
322 msg, hint = msgdestmerge[b'multiplebranchessourceset'][action]
320 raise error.ManyMergeDestAbort(msg, hint=hint)
323 raise error.ManyMergeDestAbort(msg, hint=hint)
321 branch = ctx.branch()
324 branch = ctx.branch()
322
325
323 bheads = repo.branchheads(branch)
326 bheads = repo.branchheads(branch)
324 onhead = repo.revs(b'%ld and %ln', sourceset, bheads)
327 onhead = repo.revs(b'%ld and %ln', sourceset, bheads)
325 if onheadcheck and not onhead:
328 if onheadcheck and not onhead:
326 # Case A: working copy if not on a head. (merge only)
329 # Case A: working copy if not on a head. (merge only)
327 #
330 #
328 # This is probably a user mistake We bailout pointing at 'hg update'
331 # This is probably a user mistake We bailout pointing at 'hg update'
329 if len(repo.heads()) <= 1:
332 if len(repo.heads()) <= 1:
330 msg, hint = msgdestmerge[b'nootherheadsbehind'][action]
333 msg, hint = msgdestmerge[b'nootherheadsbehind'][action]
331 else:
334 else:
332 msg, hint = msgdestmerge[b'notatheads'][action]
335 msg, hint = msgdestmerge[b'notatheads'][action]
333 raise error.Abort(msg, hint=hint)
336 raise error.Abort(msg, hint=hint)
334 # remove heads descendants of source from the set
337 # remove heads descendants of source from the set
335 bheads = list(repo.revs(b'%ln - (%ld::)', bheads, sourceset))
338 bheads = list(repo.revs(b'%ln - (%ld::)', bheads, sourceset))
336 # filters out bookmarked heads
339 # filters out bookmarked heads
337 nbhs = list(repo.revs(b'%ld - bookmark()', bheads))
340 nbhs = list(repo.revs(b'%ld - bookmark()', bheads))
338
341
339 if destspace is not None:
342 if destspace is not None:
340 # restrict search space
343 # restrict search space
341 # used in the 'hg pull --rebase' case, see issue 5214.
344 # used in the 'hg pull --rebase' case, see issue 5214.
342 nbhs = list(repo.revs(b'%ld and %ld', destspace, nbhs))
345 nbhs = list(repo.revs(b'%ld and %ld', destspace, nbhs))
343
346
344 if len(nbhs) > 1:
347 if len(nbhs) > 1:
345 # Case B: There is more than 1 other anonymous heads
348 # Case B: There is more than 1 other anonymous heads
346 #
349 #
347 # This means that there will be more than 1 candidate. This is
350 # This means that there will be more than 1 candidate. This is
348 # ambiguous. We abort asking the user to pick as explicit destination
351 # ambiguous. We abort asking the user to pick as explicit destination
349 # instead.
352 # instead.
350 msg, hint = msgdestmerge[b'toomanyheads'][action]
353 msg, hint = msgdestmerge[b'toomanyheads'][action]
351 msg %= (branch, len(bheads) + 1)
354 msg %= (branch, len(bheads) + 1)
352 raise error.ManyMergeDestAbort(msg, hint=hint)
355 raise error.ManyMergeDestAbort(msg, hint=hint)
353 elif not nbhs:
356 elif not nbhs:
354 # Case B: There is no other anonymous heads
357 # Case B: There is no other anonymous heads
355 #
358 #
356 # This means that there is no natural candidate to merge with.
359 # This means that there is no natural candidate to merge with.
357 # We abort, with various messages for various cases.
360 # We abort, with various messages for various cases.
358 if bheads:
361 if bheads:
359 msg, hint = msgdestmerge[b'bookmarkedheads'][action]
362 msg, hint = msgdestmerge[b'bookmarkedheads'][action]
360 elif len(repo.heads()) > 1:
363 elif len(repo.heads()) > 1:
361 msg, hint = msgdestmerge[b'nootherbranchheads'][action]
364 msg, hint = msgdestmerge[b'nootherbranchheads'][action]
362 msg %= branch
365 msg %= branch
363 elif not onhead:
366 elif not onhead:
364 # if 'onheadcheck == False' (rebase case),
367 # if 'onheadcheck == False' (rebase case),
365 # this was not caught in Case A.
368 # this was not caught in Case A.
366 msg, hint = msgdestmerge[b'nootherheadsbehind'][action]
369 msg, hint = msgdestmerge[b'nootherheadsbehind'][action]
367 else:
370 else:
368 msg, hint = msgdestmerge[b'nootherheads'][action]
371 msg, hint = msgdestmerge[b'nootherheads'][action]
369 raise error.NoMergeDestAbort(msg, hint=hint)
372 raise error.NoMergeDestAbort(msg, hint=hint)
370 else:
373 else:
371 node = nbhs[0]
374 node = nbhs[0]
372 assert node is not None
375 assert node is not None
373 return node
376 return node
374
377
375
378
376 def destmerge(
379 def destmerge(
377 repo, action=b'merge', sourceset=None, onheadcheck=True, destspace=None
380 repo, action=b'merge', sourceset=None, onheadcheck=True, destspace=None
378 ):
381 ):
379 """return the default destination for a merge
382 """return the default destination for a merge
380
383
381 (or raise exception about why it can't pick one)
384 (or raise exception about why it can't pick one)
382
385
383 :action: the action being performed, controls emitted error message
386 :action: the action being performed, controls emitted error message
384 """
387 """
385 # destspace is here to work around issues with `hg pull --rebase` see
388 # destspace is here to work around issues with `hg pull --rebase` see
386 # issue5214 for details
389 # issue5214 for details
387 if repo._activebookmark:
390 if repo._activebookmark:
388 node = _destmergebook(
391 node = _destmergebook(
389 repo, action=action, sourceset=sourceset, destspace=destspace
392 repo, action=action, sourceset=sourceset, destspace=destspace
390 )
393 )
391 else:
394 else:
392 node = _destmergebranch(
395 node = _destmergebranch(
393 repo,
396 repo,
394 action=action,
397 action=action,
395 sourceset=sourceset,
398 sourceset=sourceset,
396 onheadcheck=onheadcheck,
399 onheadcheck=onheadcheck,
397 destspace=destspace,
400 destspace=destspace,
398 )
401 )
399 return repo[node].rev()
402 return repo[node].rev()
400
403
401
404
402 def desthistedit(ui, repo):
405 def desthistedit(ui, repo):
403 """Default base revision to edit for `hg histedit`."""
406 """Default base revision to edit for `hg histedit`."""
404 default = ui.config(b'histedit', b'defaultrev')
407 default = ui.config(b'histedit', b'defaultrev')
405
408
406 if default is None:
409 if default is None:
407 revs = stack.getstack(repo)
410 revs = stack.getstack(repo)
408 elif default:
411 elif default:
409 revs = scmutil.revrange(repo, [default])
412 revs = scmutil.revrange(repo, [default])
410 else:
413 else:
411 raise error.ConfigError(
414 raise error.ConfigError(
412 _(b"config option histedit.defaultrev can't be empty")
415 _(b"config option histedit.defaultrev can't be empty")
413 )
416 )
414
417
415 if revs:
418 if revs:
416 # Take the first revision of the revset as the root
419 # Take the first revision of the revset as the root
417 return revs.min()
420 return revs.min()
418
421
419 return None
422 return None
420
423
421
424
422 def stackbase(ui, repo):
425 def stackbase(ui, repo):
423 revs = stack.getstack(repo)
426 revs = stack.getstack(repo)
424 return revs.first() if revs else None
427 return revs.first() if revs else None
425
428
426
429
427 def _statusotherbook(ui, repo):
430 def _statusotherbook(ui, repo):
428 bmheads = bookmarks.headsforactive(repo)
431 bmheads = bookmarks.headsforactive(repo)
429 curhead = repo._bookmarks[repo._activebookmark]
432 curhead = repo._bookmarks[repo._activebookmark]
430 if repo.revs(b'%n and parents()', curhead):
433 if repo.revs(b'%n and parents()', curhead):
431 # we are on the active bookmark
434 # we are on the active bookmark
432 bmheads = [b for b in bmheads if curhead != b]
435 bmheads = [b for b in bmheads if curhead != b]
433 if bmheads:
436 if bmheads:
434 msg = _(b'%i other divergent bookmarks for "%s"\n')
437 msg = _(b'%i other divergent bookmarks for "%s"\n')
435 ui.status(msg % (len(bmheads), repo._activebookmark))
438 ui.status(msg % (len(bmheads), repo._activebookmark))
436
439
437
440
438 def _statusotherbranchheads(ui, repo):
441 def _statusotherbranchheads(ui, repo):
439 currentbranch = repo.dirstate.branch()
442 currentbranch = repo.dirstate.branch()
440 allheads = repo.branchheads(currentbranch, closed=True)
443 allheads = repo.branchheads(currentbranch, closed=True)
441 heads = repo.branchheads(currentbranch)
444 heads = repo.branchheads(currentbranch)
442 if repo.revs(b'%ln and parents()', allheads):
445 if repo.revs(b'%ln and parents()', allheads):
443 # we are on a head, even though it might be closed
446 # we are on a head, even though it might be closed
444 #
447 #
445 # on closed otherheads
448 # on closed otherheads
446 # ========= ==========
449 # ========= ==========
447 # o 0 all heads for current branch are closed
450 # o 0 all heads for current branch are closed
448 # N only descendant branch heads are closed
451 # N only descendant branch heads are closed
449 # x 0 there is only one non-closed branch head
452 # x 0 there is only one non-closed branch head
450 # N there are some non-closed branch heads
453 # N there are some non-closed branch heads
451 # ========= ==========
454 # ========= ==========
452 otherheads = repo.revs(b'%ln - parents()', heads)
455 otherheads = repo.revs(b'%ln - parents()', heads)
453 if repo[b'.'].closesbranch():
456 if repo[b'.'].closesbranch():
454 ui.warn(
457 ui.warn(
455 _(
458 _(
456 b'no open descendant heads on branch "%s", '
459 b'no open descendant heads on branch "%s", '
457 b'updating to a closed head\n'
460 b'updating to a closed head\n'
458 )
461 )
459 % currentbranch
462 % currentbranch
460 )
463 )
461 if otherheads:
464 if otherheads:
462 ui.warn(
465 ui.warn(
463 _(
466 _(
464 b"(committing will reopen the head, "
467 b"(committing will reopen the head, "
465 b"use 'hg heads .' to see %i other heads)\n"
468 b"use 'hg heads .' to see %i other heads)\n"
466 )
469 )
467 % (len(otherheads))
470 % (len(otherheads))
468 )
471 )
469 else:
472 else:
470 ui.warn(
473 ui.warn(
471 _(b'(committing will reopen branch "%s")\n') % currentbranch
474 _(b'(committing will reopen branch "%s")\n') % currentbranch
472 )
475 )
473 elif otherheads:
476 elif otherheads:
474 curhead = repo[b'.']
477 curhead = repo[b'.']
475 ui.status(
478 ui.status(
476 _(b'updated to "%s: %s"\n')
479 _(b'updated to "%s: %s"\n')
477 % (curhead, curhead.description().split(b'\n')[0])
480 % (curhead, curhead.description().split(b'\n')[0])
478 )
481 )
479 ui.status(
482 ui.status(
480 _(b'%i other heads for branch "%s"\n')
483 _(b'%i other heads for branch "%s"\n')
481 % (len(otherheads), currentbranch)
484 % (len(otherheads), currentbranch)
482 )
485 )
483
486
484
487
485 def statusotherdests(ui, repo):
488 def statusotherdests(ui, repo):
486 """Print message about other head"""
489 """Print message about other head"""
487 # XXX we should probably include a hint:
490 # XXX we should probably include a hint:
488 # - about what to do
491 # - about what to do
489 # - how to see such heads
492 # - how to see such heads
490 if repo._activebookmark:
493 if repo._activebookmark:
491 _statusotherbook(ui, repo)
494 _statusotherbook(ui, repo)
492 else:
495 else:
493 _statusotherbranchheads(ui, repo)
496 _statusotherbranchheads(ui, repo)
@@ -1,726 +1,722 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [commands]
2 > [commands]
3 > status.verbose=1
3 > status.verbose=1
4 > EOF
4 > EOF
5
5
6 # Construct the following history tree:
6 # Construct the following history tree:
7 #
7 #
8 # @ 5:e1bb631146ca b1
8 # @ 5:e1bb631146ca b1
9 # |
9 # |
10 # o 4:a4fdb3b883c4 0:b608b9236435 b1
10 # o 4:a4fdb3b883c4 0:b608b9236435 b1
11 # |
11 # |
12 # | o 3:4b57d2520816 1:44592833ba9f
12 # | o 3:4b57d2520816 1:44592833ba9f
13 # | |
13 # | |
14 # | | o 2:063f31070f65
14 # | | o 2:063f31070f65
15 # | |/
15 # | |/
16 # | o 1:44592833ba9f
16 # | o 1:44592833ba9f
17 # |/
17 # |/
18 # o 0:b608b9236435
18 # o 0:b608b9236435
19
19
20 $ mkdir b1
20 $ mkdir b1
21 $ cd b1
21 $ cd b1
22 $ hg init
22 $ hg init
23 $ echo foo > foo
23 $ echo foo > foo
24 $ echo zero > a
24 $ echo zero > a
25 $ hg init sub
25 $ hg init sub
26 $ echo suba > sub/suba
26 $ echo suba > sub/suba
27 $ hg --cwd sub ci -Am addsuba
27 $ hg --cwd sub ci -Am addsuba
28 adding suba
28 adding suba
29 $ echo 'sub = sub' > .hgsub
29 $ echo 'sub = sub' > .hgsub
30 $ hg ci -qAm0
30 $ hg ci -qAm0
31 $ echo one > a ; hg ci -m1
31 $ echo one > a ; hg ci -m1
32 $ echo two > a ; hg ci -m2
32 $ echo two > a ; hg ci -m2
33 $ hg up -q 1
33 $ hg up -q 1
34 $ echo three > a ; hg ci -qm3
34 $ echo three > a ; hg ci -qm3
35 $ hg up -q 0
35 $ hg up -q 0
36 $ hg branch -q b1
36 $ hg branch -q b1
37 $ echo four > a ; hg ci -qm4
37 $ echo four > a ; hg ci -qm4
38 $ echo five > a ; hg ci -qm5
38 $ echo five > a ; hg ci -qm5
39
39
40 Initial repo state:
40 Initial repo state:
41
41
42 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
42 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
43 @ 5:ff252e8273df b1
43 @ 5:ff252e8273df b1
44 |
44 |
45 o 4:d047485b3896 0:60829823a42a b1
45 o 4:d047485b3896 0:60829823a42a b1
46 |
46 |
47 | o 3:6efa171f091b 1:0786582aa4b1
47 | o 3:6efa171f091b 1:0786582aa4b1
48 | |
48 | |
49 | | o 2:bd10386d478c
49 | | o 2:bd10386d478c
50 | |/
50 | |/
51 | o 1:0786582aa4b1
51 | o 1:0786582aa4b1
52 |/
52 |/
53 o 0:60829823a42a
53 o 0:60829823a42a
54
54
55
55
56 Make sure update doesn't assume b1 is a repository if invoked from outside:
56 Make sure update doesn't assume b1 is a repository if invoked from outside:
57
57
58 $ cd ..
58 $ cd ..
59 $ hg update b1
59 $ hg update b1
60 abort: no repository found in '$TESTTMP' (.hg not found)
60 abort: no repository found in '$TESTTMP' (.hg not found)
61 [10]
61 [10]
62 $ cd b1
62 $ cd b1
63
63
64 Test helper functions:
64 Test helper functions:
65
65
66 $ revtest () {
66 $ revtest () {
67 > msg=$1
67 > msg=$1
68 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
68 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
69 > startrev=$3
69 > startrev=$3
70 > targetrev=$4
70 > targetrev=$4
71 > opt=$5
71 > opt=$5
72 > hg up -qC $startrev
72 > hg up -qC $startrev
73 > test $dirtyflag = dirty && echo dirty > foo
73 > test $dirtyflag = dirty && echo dirty > foo
74 > test $dirtyflag = dirtysub && echo dirty > sub/suba
74 > test $dirtyflag = dirtysub && echo dirty > sub/suba
75 > hg up $opt $targetrev
75 > hg up $opt $targetrev
76 > hg parent --template 'parent={rev}\n'
76 > hg parent --template 'parent={rev}\n'
77 > hg stat -S
77 > hg stat -S
78 > }
78 > }
79
79
80 $ norevtest () {
80 $ norevtest () {
81 > msg=$1
81 > msg=$1
82 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
82 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
83 > startrev=$3
83 > startrev=$3
84 > opt=$4
84 > opt=$4
85 > hg up -qC $startrev
85 > hg up -qC $startrev
86 > test $dirtyflag = dirty && echo dirty > foo
86 > test $dirtyflag = dirty && echo dirty > foo
87 > test $dirtyflag = dirtysub && echo dirty > sub/suba
87 > test $dirtyflag = dirtysub && echo dirty > sub/suba
88 > hg up $opt
88 > hg up $opt
89 > hg parent --template 'parent={rev}\n'
89 > hg parent --template 'parent={rev}\n'
90 > hg stat -S
90 > hg stat -S
91 > }
91 > }
92
92
93 Test cases are documented in a table in the update function of merge.py.
93 Test cases are documented in a table in the update function of merge.py.
94 Cases are run as shown in that table, row by row.
94 Cases are run as shown in that table, row by row.
95
95
96 $ norevtest 'none clean linear' clean 4
96 $ norevtest 'none clean linear' clean 4
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 parent=5
98 parent=5
99
99
100 $ norevtest 'none clean same' clean 2
100 $ norevtest 'none clean same' clean 2
101 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 updated to "bd10386d478c: 2"
102 updated to "bd10386d478c: 2"
103 1 other heads for branch "default"
103 1 other heads for branch "default"
104 parent=2
104 parent=2
105
105
106
106
107 $ revtest 'none clean linear' clean 1 2
107 $ revtest 'none clean linear' clean 1 2
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 parent=2
109 parent=2
110
110
111 $ revtest 'none clean same' clean 2 3
111 $ revtest 'none clean same' clean 2 3
112 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 parent=3
113 parent=3
114
114
115 $ revtest 'none clean cross' clean 3 4
115 $ revtest 'none clean cross' clean 3 4
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 parent=4
117 parent=4
118
118
119
119
120 $ revtest 'none dirty linear' dirty 1 2
120 $ revtest 'none dirty linear' dirty 1 2
121 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 parent=2
122 parent=2
123 M foo
123 M foo
124
124
125 $ revtest 'none dirtysub linear' dirtysub 1 2
125 $ revtest 'none dirtysub linear' dirtysub 1 2
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 parent=2
127 parent=2
128 M sub/suba
128 M sub/suba
129
129
130 $ revtest 'none dirty same' dirty 2 3
130 $ revtest 'none dirty same' dirty 2 3
131 abort: uncommitted changes
131 abort: uncommitted changes
132 (commit or update --clean to discard changes)
132 (commit or update --clean to discard changes)
133 parent=2
133 parent=2
134 M foo
134 M foo
135
135
136 $ revtest 'none dirtysub same' dirtysub 2 3
136 $ revtest 'none dirtysub same' dirtysub 2 3
137 abort: uncommitted changes
137 abort: uncommitted changes
138 (commit or update --clean to discard changes)
138 (commit or update --clean to discard changes)
139 parent=2
139 parent=2
140 M sub/suba
140 M sub/suba
141
141
142 $ revtest 'none dirty cross' dirty 3 4
142 $ revtest 'none dirty cross' dirty 3 4
143 abort: uncommitted changes
143 abort: uncommitted changes
144 (commit or update --clean to discard changes)
144 (commit or update --clean to discard changes)
145 parent=3
145 parent=3
146 M foo
146 M foo
147
147
148 $ norevtest 'none dirty cross' dirty 2
148 $ norevtest 'none dirty cross' dirty 2
149 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 updated to "bd10386d478c: 2"
150 updated to "bd10386d478c: 2"
151 1 other heads for branch "default"
151 1 other heads for branch "default"
152 parent=2
152 parent=2
153 M foo
153 M foo
154
154
155 $ revtest 'none dirtysub cross' dirtysub 3 4
155 $ revtest 'none dirtysub cross' dirtysub 3 4
156 abort: uncommitted changes
156 abort: uncommitted changes
157 (commit or update --clean to discard changes)
157 (commit or update --clean to discard changes)
158 parent=3
158 parent=3
159 M sub/suba
159 M sub/suba
160
160
161 $ revtest '--clean dirty linear' dirty 1 2 --clean
161 $ revtest '--clean dirty linear' dirty 1 2 --clean
162 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 parent=2
163 parent=2
164
164
165 $ revtest '--check dirty linear' dirty 1 2 --check
165 $ revtest '--check dirty linear' dirty 1 2 --check
166 abort: uncommitted changes
166 abort: uncommitted changes
167 parent=1
167 parent=1
168 M foo
168 M foo
169
169
170 $ revtest '--merge dirty linear' dirty 1 2 --merge
170 $ revtest '--merge dirty linear' dirty 1 2 --merge
171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
172 parent=2
172 parent=2
173 M foo
173 M foo
174
174
175 $ revtest '--merge dirty cross' dirty 3 4 --merge
175 $ revtest '--merge dirty cross' dirty 3 4 --merge
176 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
176 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 parent=4
177 parent=4
178 M foo
178 M foo
179
179
180 $ revtest '--check dirtysub linear' dirtysub 1 2 --check
180 $ revtest '--check dirtysub linear' dirtysub 1 2 --check
181 abort: uncommitted changes in subrepository "sub"
181 abort: uncommitted changes in subrepository "sub"
182 parent=1
182 parent=1
183 M sub/suba
183 M sub/suba
184
184
185 $ norevtest '--check clean same' clean 2 -c
185 $ norevtest '--check clean same' clean 2 -c
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 updated to "bd10386d478c: 2"
187 updated to "bd10386d478c: 2"
188 1 other heads for branch "default"
188 1 other heads for branch "default"
189 parent=2
189 parent=2
190
190
191 $ revtest '--check --clean dirty linear' dirty 1 2 "--check --clean"
191 $ revtest '--check --clean dirty linear' dirty 1 2 "--check --clean"
192 abort: cannot specify both --clean and --check
192 abort: cannot specify both --clean and --check
193 parent=1
193 parent=1
194 M foo
194 M foo
195
195
196 $ revtest '--merge -checkc dirty linear' dirty 1 2 "--merge --check"
196 $ revtest '--merge -checkc dirty linear' dirty 1 2 "--merge --check"
197 abort: cannot specify both --check and --merge
197 abort: cannot specify both --check and --merge
198 parent=1
198 parent=1
199 M foo
199 M foo
200
200
201 $ revtest '--merge -clean dirty linear' dirty 1 2 "--merge --clean"
201 $ revtest '--merge -clean dirty linear' dirty 1 2 "--merge --clean"
202 abort: cannot specify both --clean and --merge
202 abort: cannot specify both --clean and --merge
203 parent=1
203 parent=1
204 M foo
204 M foo
205
205
206 $ echo '[commands]' >> .hg/hgrc
206 $ echo '[commands]' >> .hg/hgrc
207 $ echo 'update.check = abort' >> .hg/hgrc
207 $ echo 'update.check = abort' >> .hg/hgrc
208
208
209 $ revtest 'none dirty linear' dirty 1 2
209 $ revtest 'none dirty linear' dirty 1 2
210 abort: uncommitted changes
210 abort: uncommitted changes
211 parent=1
211 parent=1
212 M foo
212 M foo
213
213
214 $ revtest 'none dirty linear' dirty 1 2 --check
214 $ revtest 'none dirty linear' dirty 1 2 --check
215 abort: uncommitted changes
215 abort: uncommitted changes
216 parent=1
216 parent=1
217 M foo
217 M foo
218
218
219 $ revtest '--merge none dirty linear' dirty 1 2 --check
219 $ revtest '--merge none dirty linear' dirty 1 2 --check
220 abort: uncommitted changes
220 abort: uncommitted changes
221 parent=1
221 parent=1
222 M foo
222 M foo
223
223
224 $ revtest '--merge none dirty linear' dirty 1 2 --merge
224 $ revtest '--merge none dirty linear' dirty 1 2 --merge
225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 parent=2
226 parent=2
227 M foo
227 M foo
228
228
229 $ revtest '--merge none dirty linear' dirty 1 2 --no-check
229 $ revtest '--merge none dirty linear' dirty 1 2 --no-check
230 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 parent=2
231 parent=2
232 M foo
232 M foo
233
233
234 $ revtest 'none dirty linear' dirty 1 2 --clean
234 $ revtest 'none dirty linear' dirty 1 2 --clean
235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 parent=2
236 parent=2
237
237
238 $ echo 'update.check = none' >> .hg/hgrc
238 $ echo 'update.check = none' >> .hg/hgrc
239
239
240 $ revtest 'none dirty cross' dirty 3 4
240 $ revtest 'none dirty cross' dirty 3 4
241 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
242 parent=4
242 parent=4
243 M foo
243 M foo
244
244
245 $ revtest 'none dirty linear' dirty 1 2
245 $ revtest 'none dirty linear' dirty 1 2
246 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 parent=2
247 parent=2
248 M foo
248 M foo
249
249
250 $ revtest 'none dirty linear' dirty 1 2 --check
250 $ revtest 'none dirty linear' dirty 1 2 --check
251 abort: uncommitted changes
251 abort: uncommitted changes
252 parent=1
252 parent=1
253 M foo
253 M foo
254
254
255 $ revtest 'none dirty linear' dirty 1 2 --no-merge
255 $ revtest 'none dirty linear' dirty 1 2 --no-merge
256 abort: uncommitted changes
256 abort: uncommitted changes
257 parent=1
257 parent=1
258 M foo
258 M foo
259
259
260 $ revtest 'none dirty linear' dirty 1 2 --clean
260 $ revtest 'none dirty linear' dirty 1 2 --clean
261 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 parent=2
262 parent=2
263
263
264 $ hg co -qC 3
264 $ hg co -qC 3
265 $ echo dirty >> a
265 $ echo dirty >> a
266 $ hg co --tool :merge3 4
266 $ hg co --tool :merge3 4
267 merging a
267 merging a
268 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
268 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
269 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
269 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
270 use 'hg resolve' to retry unresolved file merges
270 use 'hg resolve' to retry unresolved file merges
271 [1]
271 [1]
272 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
272 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
273 o 5:ff252e8273df b1
273 o 5:ff252e8273df b1
274 |
274 |
275 @ 4:d047485b3896 0:60829823a42a b1
275 @ 4:d047485b3896 0:60829823a42a b1
276 |
276 |
277 | % 3:6efa171f091b 1:0786582aa4b1
277 | % 3:6efa171f091b 1:0786582aa4b1
278 | |
278 | |
279 | | o 2:bd10386d478c
279 | | o 2:bd10386d478c
280 | |/
280 | |/
281 | o 1:0786582aa4b1
281 | o 1:0786582aa4b1
282 |/
282 |/
283 o 0:60829823a42a
283 o 0:60829823a42a
284
284
285 $ hg st
285 $ hg st
286 M a
286 M a
287 ? a.orig
287 ? a.orig
288 # Unresolved merge conflicts:
288 # Unresolved merge conflicts:
289 #
289 #
290 # a
290 # a
291 #
291 #
292 # To mark files as resolved: hg resolve --mark FILE
292 # To mark files as resolved: hg resolve --mark FILE
293
293
294 $ cat a
294 $ cat a
295 <<<<<<< working copy: 6efa171f091b - test: 3
295 <<<<<<< working copy: 6efa171f091b - test: 3
296 three
296 three
297 dirty
297 dirty
298 ||||||| working copy parent: 6efa171f091b - test: 3
298 ||||||| working copy parent: 6efa171f091b - test: 3
299 three
299 three
300 =======
300 =======
301 four
301 four
302 >>>>>>> destination: d047485b3896 b1 - test: 4
302 >>>>>>> destination: d047485b3896 b1 - test: 4
303 $ rm a.orig
303 $ rm a.orig
304
304
305 $ echo 'update.check = noconflict' >> .hg/hgrc
305 $ echo 'update.check = noconflict' >> .hg/hgrc
306
306
307 $ revtest 'none dirty cross' dirty 3 4
307 $ revtest 'none dirty cross' dirty 3 4
308 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 parent=4
309 parent=4
310 M foo
310 M foo
311
311
312 $ revtest 'none dirty linear' dirty 1 2
312 $ revtest 'none dirty linear' dirty 1 2
313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 parent=2
314 parent=2
315 M foo
315 M foo
316
316
317 $ revtest 'none dirty linear' dirty 1 2 -c
317 $ revtest 'none dirty linear' dirty 1 2 -c
318 abort: uncommitted changes
318 abort: uncommitted changes
319 parent=1
319 parent=1
320 M foo
320 M foo
321
321
322 $ revtest 'none dirty linear' dirty 1 2 -C
322 $ revtest 'none dirty linear' dirty 1 2 -C
323 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
323 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
324 parent=2
324 parent=2
325
325
326 Locally added file is allowed
326 Locally added file is allowed
327 $ hg up -qC 3
327 $ hg up -qC 3
328 $ echo a > bar
328 $ echo a > bar
329 $ hg add bar
329 $ hg add bar
330 $ hg up -q 4
330 $ hg up -q 4
331 $ hg st
331 $ hg st
332 A bar
332 A bar
333 $ hg forget bar
333 $ hg forget bar
334 $ rm bar
334 $ rm bar
335
335
336 Locally removed file is allowed
336 Locally removed file is allowed
337 $ hg up -qC 3
337 $ hg up -qC 3
338 $ hg rm foo
338 $ hg rm foo
339 $ hg up -q 4
339 $ hg up -q 4
340
340
341 File conflict is not allowed
341 File conflict is not allowed
342 $ hg up -qC 3
342 $ hg up -qC 3
343 $ echo dirty >> a
343 $ echo dirty >> a
344 $ hg up -q 4
344 $ hg up -q 4
345 abort: conflicting changes
345 abort: conflicting changes
346 (commit or update --clean to discard changes)
346 (commit or update --clean to discard changes)
347 [20]
347 [20]
348 $ hg up -m 4
348 $ hg up -m 4
349 merging a
349 merging a
350 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
350 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
351 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
351 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
352 use 'hg resolve' to retry unresolved file merges
352 use 'hg resolve' to retry unresolved file merges
353 [1]
353 [1]
354 $ rm a.orig
354 $ rm a.orig
355 $ hg status
355 $ hg status
356 M a
356 M a
357 # Unresolved merge conflicts:
357 # Unresolved merge conflicts:
358 #
358 #
359 # a
359 # a
360 #
360 #
361 # To mark files as resolved: hg resolve --mark FILE
361 # To mark files as resolved: hg resolve --mark FILE
362
362
363 $ hg resolve -l
363 $ hg resolve -l
364 U a
364 U a
365
365
366 Try to make empty commit while there are conflicts
366 Try to make empty commit while there are conflicts
367 $ hg revert -r . a
367 $ hg revert -r . a
368 $ rm a.orig
368 $ rm a.orig
369 $ hg ci -m empty
369 $ hg ci -m empty
370 abort: unresolved merge conflicts (see 'hg help resolve')
370 abort: unresolved merge conflicts (see 'hg help resolve')
371 [20]
371 [20]
372 $ hg resolve -m a
372 $ hg resolve -m a
373 (no more unresolved files)
373 (no more unresolved files)
374 $ hg resolve -l
374 $ hg resolve -l
375 R a
375 R a
376 $ hg ci -m empty
376 $ hg ci -m empty
377 nothing changed
377 nothing changed
378 [1]
378 [1]
379 $ hg resolve -l
379 $ hg resolve -l
380
380
381 Change/delete conflict is not allowed
381 Change/delete conflict is not allowed
382 $ hg up -qC 3
382 $ hg up -qC 3
383 $ hg rm foo
383 $ hg rm foo
384 $ hg up -q 4
384 $ hg up -q 4
385
385
386 Uses default value of "linear" when value is misspelled
386 Uses default value of "linear" when value is misspelled
387 $ echo 'update.check = linyar' >> .hg/hgrc
387 $ echo 'update.check = linyar' >> .hg/hgrc
388
388
389 $ revtest 'dirty cross' dirty 3 4
389 $ revtest 'dirty cross' dirty 3 4
390 abort: uncommitted changes
390 abort: uncommitted changes
391 (commit or update --clean to discard changes)
391 (commit or update --clean to discard changes)
392 parent=3
392 parent=3
393 M foo
393 M foo
394
394
395 Setup for later tests
395 Setup for later tests
396 $ revtest 'none dirty linear' dirty 1 2 -c
396 $ revtest 'none dirty linear' dirty 1 2 -c
397 abort: uncommitted changes
397 abort: uncommitted changes
398 parent=1
398 parent=1
399 M foo
399 M foo
400
400
401 $ cd ..
401 $ cd ..
402
402
403 Test updating to null revision
403 Test updating to null revision
404
404
405 $ hg init null-repo
405 $ hg init null-repo
406 $ cd null-repo
406 $ cd null-repo
407 $ echo a > a
407 $ echo a > a
408 $ hg add a
408 $ hg add a
409 $ hg ci -m a
409 $ hg ci -m a
410 $ hg up -qC 0
410 $ hg up -qC 0
411 $ echo b > b
411 $ echo b > b
412 $ hg add b
412 $ hg add b
413 $ hg up null
413 $ hg up null
414 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
414 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
415 $ hg st
415 $ hg st
416 A b
416 A b
417 $ hg up -q 0
417 $ hg up -q 0
418 $ hg st
418 $ hg st
419 A b
419 A b
420 $ hg up -qC null
420 $ hg up -qC null
421 $ hg st
421 $ hg st
422 ? b
422 ? b
423 $ cd ..
423 $ cd ..
424
424
425 Test updating with closed head
425 Test updating with closed head
426 ---------------------------------------------------------------------
426 ---------------------------------------------------------------------
427
427
428 $ hg clone -U -q b1 closed-heads
428 $ hg clone -U -q b1 closed-heads
429 $ cd closed-heads
429 $ cd closed-heads
430
430
431 Test updating if at least one non-closed branch head exists
431 Test updating if at least one non-closed branch head exists
432
432
433 if on the closed branch head:
433 if on the closed branch head:
434 - update to "."
434 - update to "."
435 - "updated to a closed branch head ...." message is displayed
435 - "updated to a closed branch head ...." message is displayed
436 - "N other heads for ...." message is displayed
436 - "N other heads for ...." message is displayed
437
437
438 $ hg update -q -C 3
438 $ hg update -q -C 3
439 $ hg commit --close-branch -m 6
439 $ hg commit --close-branch -m 6
440 $ norevtest "on closed branch head" clean 6
440 $ norevtest "on closed branch head" clean 6
441 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 no open descendant heads on branch "default", updating to a closed head
442 no open descendant heads on branch "default", updating to a closed head
443 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
443 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
444 parent=6
444 parent=6
445
445
446 if descendant non-closed branch head exists, and it is only one branch head:
446 if descendant non-closed branch head exists, and it is only one branch head:
447 - update to it, even if its revision is less than closed one
447 - update to it, even if its revision is less than closed one
448 - "N other heads for ...." message isn't displayed
448 - "N other heads for ...." message isn't displayed
449
449
450 $ norevtest "non-closed 2 should be chosen" clean 1
450 $ norevtest "non-closed 2 should be chosen" clean 1
451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
452 parent=2
452 parent=2
453
453
454 if all descendant branch heads are closed, but there is another branch head:
454 if all descendant branch heads are closed, but there is another branch head:
455 - update to the tipmost descendant head
455 - update to the tipmost descendant head
456 - "updated to a closed branch head ...." message is displayed
456 - "updated to a closed branch head ...." message is displayed
457 - "N other heads for ...." message is displayed
457 - "N other heads for ...." message is displayed
458
458
459 $ norevtest "all descendant branch heads are closed" clean 3
459 $ norevtest "all descendant branch heads are closed" clean 3
460 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 no open descendant heads on branch "default", updating to a closed head
461 no open descendant heads on branch "default", updating to a closed head
462 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
462 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
463 parent=6
463 parent=6
464
464
465 Test updating if all branch heads are closed
465 Test updating if all branch heads are closed
466
466
467 if on the closed branch head:
467 if on the closed branch head:
468 - update to "."
468 - update to "."
469 - "updated to a closed branch head ...." message is displayed
469 - "updated to a closed branch head ...." message is displayed
470 - "all heads of branch ...." message is displayed
470 - "all heads of branch ...." message is displayed
471
471
472 $ hg update -q -C 2
472 $ hg update -q -C 2
473 $ hg commit --close-branch -m 7
473 $ hg commit --close-branch -m 7
474 $ norevtest "all heads of branch default are closed" clean 6
474 $ norevtest "all heads of branch default are closed" clean 6
475 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
476 no open descendant heads on branch "default", updating to a closed head
476 no open descendant heads on branch "default", updating to a closed head
477 (committing will reopen branch "default")
477 (committing will reopen branch "default")
478 parent=6
478 parent=6
479
479
480 if not on the closed branch head:
480 if not on the closed branch head:
481 - update to the tipmost descendant (closed) head
481 - update to the tipmost descendant (closed) head
482 - "updated to a closed branch head ...." message is displayed
482 - "updated to a closed branch head ...." message is displayed
483 - "all heads of branch ...." message is displayed
483 - "all heads of branch ...." message is displayed
484
484
485 $ norevtest "all heads of branch default are closed" clean 1
485 $ norevtest "all heads of branch default are closed" clean 1
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
487 no open descendant heads on branch "default", updating to a closed head
487 no open descendant heads on branch "default", updating to a closed head
488 (committing will reopen branch "default")
488 (committing will reopen branch "default")
489 parent=7
489 parent=7
490
490
491 $ cd ..
491 $ cd ..
492
492
493 Test updating if "default" branch doesn't exist and no revision is
493 Test updating if "default" branch doesn't exist and no revision is
494 checked out (= "default" is used as current branch)
494 checked out (= "default" is used as current branch)
495
495
496 $ hg init no-default-branch
496 $ hg init no-default-branch
497 $ cd no-default-branch
497 $ cd no-default-branch
498
498
499 $ hg branch foobar
499 $ hg branch foobar
500 marked working directory as branch foobar
500 marked working directory as branch foobar
501 (branches are permanent and global, did you want a bookmark?)
501 (branches are permanent and global, did you want a bookmark?)
502 $ echo a > a
502 $ echo a > a
503 $ hg commit -m "#0" -A
503 $ hg commit -m "#0" -A
504 adding a
504 adding a
505 $ echo 1 >> a
505 $ echo 1 >> a
506 $ hg commit -m "#1"
506 $ hg commit -m "#1"
507 $ hg update -q 0
507 $ hg update -q 0
508 $ echo 3 >> a
508 $ echo 3 >> a
509 $ hg commit -m "#2"
509 $ hg commit -m "#2"
510 created new head
510 created new head
511 $ hg commit --close-branch -m "#3"
511 $ hg commit --close-branch -m "#3"
512
512
513 if there is at least one non-closed branch head:
513 if there is at least one non-closed branch head:
514 - update to the tipmost branch head
514 - update to the tipmost branch head
515
515
516 $ norevtest "non-closed 1 should be chosen" clean null
516 $ norevtest "non-closed 1 should be chosen" clean null
517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
518 parent=1
518 parent=1
519
519
520 if all branch heads are closed
520 if all branch heads are closed
521 - update to "tip"
521 - update to "tip"
522 - "updated to a closed branch head ...." message is displayed
522 - "updated to a closed branch head ...." message is displayed
523 - "all heads for branch "XXXX" are closed" message is displayed
523 - "all heads for branch "XXXX" are closed" message is displayed
524
524
525 $ hg update -q -C 1
525 $ hg update -q -C 1
526 $ hg commit --close-branch -m "#4"
526 $ hg commit --close-branch -m "#4"
527
527
528 $ norevtest "all branches are closed" clean null
528 $ norevtest "all branches are closed" clean null
529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 no open descendant heads on branch "foobar", updating to a closed head
530 no open descendant heads on branch "foobar", updating to a closed head
531 (committing will reopen branch "foobar")
531 (committing will reopen branch "foobar")
532 parent=4
532 parent=4
533
533
534 $ cd ../b1
534 $ cd ../b1
535
535
536 Test obsolescence behavior
536 Test obsolescence behavior
537 ---------------------------------------------------------------------
537 ---------------------------------------------------------------------
538
538
539 successors should be taken in account when checking head destination
539 successors should be taken in account when checking head destination
540
540
541 $ cat << EOF >> $HGRCPATH
541 $ cat << EOF >> $HGRCPATH
542 > [ui]
542 > [ui]
543 > logtemplate={rev}:{node|short} {desc|firstline}
543 > logtemplate={rev}:{node|short} {desc|firstline}
544 > [experimental]
544 > [experimental]
545 > evolution.createmarkers=True
545 > evolution.createmarkers=True
546 > EOF
546 > EOF
547
547
548 Test no-argument update to a successor of an obsoleted changeset
548 Test no-argument update to a successor of an obsoleted changeset
549
549
550 $ hg log -G
550 $ hg log -G
551 o 5:ff252e8273df 5
551 o 5:ff252e8273df 5
552 |
552 |
553 o 4:d047485b3896 4
553 o 4:d047485b3896 4
554 |
554 |
555 | o 3:6efa171f091b 3
555 | o 3:6efa171f091b 3
556 | |
556 | |
557 | | o 2:bd10386d478c 2
557 | | o 2:bd10386d478c 2
558 | |/
558 | |/
559 | @ 1:0786582aa4b1 1
559 | @ 1:0786582aa4b1 1
560 |/
560 |/
561 o 0:60829823a42a 0
561 o 0:60829823a42a 0
562
562
563 $ hg book bm -r 3
563 $ hg book bm -r 3
564 $ hg status
564 $ hg status
565 M foo
565 M foo
566
566
567 We add simple obsolescence marker between 3 and 4 (indirect successors)
567 We add simple obsolescence marker between 3 and 4 (indirect successors)
568
568
569 $ hg id --debug -i -r 3
569 $ hg id --debug -i -r 3
570 6efa171f091b00a3c35edc15d48c52a498929953
570 6efa171f091b00a3c35edc15d48c52a498929953
571 $ hg id --debug -i -r 4
571 $ hg id --debug -i -r 4
572 d047485b3896813b2a624e86201983520f003206
572 d047485b3896813b2a624e86201983520f003206
573 $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
573 $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
574 1 new obsolescence markers
574 1 new obsolescence markers
575 obsoleted 1 changesets
575 obsoleted 1 changesets
576 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
576 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
577 1 new obsolescence markers
577 1 new obsolescence markers
578
578
579 Test that 5 is detected as a valid destination from 3 and also accepts moving
579 Test that 5 is detected as a valid destination from 3 and also accepts moving
580 the bookmark (issue4015)
580 the bookmark (issue4015)
581
581
582 $ hg up --quiet --hidden 3
582 $ hg up --quiet --hidden 3
583 $ hg up 5
583 $ hg up 5
584 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 $ hg book bm
585 $ hg book bm
586 moving bookmark 'bm' forward from 6efa171f091b
586 moving bookmark 'bm' forward from 6efa171f091b
587 $ hg bookmarks
587 $ hg bookmarks
588 * bm 5:ff252e8273df
588 * bm 5:ff252e8273df
589
589
590 Test that we abort before we warn about the hidden commit if the working
590 Test that we abort before we warn about the hidden commit if the working
591 directory is dirty
591 directory is dirty
592 $ echo conflict > a
592 $ echo conflict > a
593 $ hg up --hidden 3
593 $ hg up --hidden 3
594 abort: uncommitted changes
594 abort: uncommitted changes
595 (commit or update --clean to discard changes)
595 (commit or update --clean to discard changes)
596 [255]
596 [255]
597
597
598 Test that we still warn also when there are conflicts
598 Test that we still warn also when there are conflicts
599 $ hg up -m --hidden 3
599 $ hg up -m --hidden 3
600 merging a
600 merging a
601 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
601 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
602 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
602 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
603 use 'hg resolve' to retry unresolved file merges
603 use 'hg resolve' to retry unresolved file merges
604 (leaving bookmark bm)
604 (leaving bookmark bm)
605 updated to hidden changeset 6efa171f091b
605 updated to hidden changeset 6efa171f091b
606 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
606 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
607 [1]
607 [1]
608
608
609 Test that statuses are reported properly before and after merge resolution.
609 Test that statuses are reported properly before and after merge resolution.
610 $ rm a.orig
610 $ rm a.orig
611 $ hg resolve -l
611 $ hg resolve -l
612 U a
612 U a
613 $ hg status
613 $ hg status
614 M a
614 M a
615 M foo
615 M foo
616 # Unresolved merge conflicts:
616 # Unresolved merge conflicts:
617 #
617 #
618 # a
618 # a
619 #
619 #
620 # To mark files as resolved: hg resolve --mark FILE
620 # To mark files as resolved: hg resolve --mark FILE
621
621
622
622
623 $ hg revert -r . a
623 $ hg revert -r . a
624
624
625 $ rm a.orig
625 $ rm a.orig
626 $ hg resolve -l
626 $ hg resolve -l
627 U a
627 U a
628 $ hg status
628 $ hg status
629 M foo
629 M foo
630 # Unresolved merge conflicts:
630 # Unresolved merge conflicts:
631 #
631 #
632 # a
632 # a
633 #
633 #
634 # To mark files as resolved: hg resolve --mark FILE
634 # To mark files as resolved: hg resolve --mark FILE
635
635
636 $ hg status -Tjson
636 $ hg status -Tjson
637 [
637 [
638 {
638 {
639 "itemtype": "file",
639 "itemtype": "file",
640 "path": "foo",
640 "path": "foo",
641 "status": "M"
641 "status": "M"
642 },
642 },
643 {
643 {
644 "itemtype": "file",
644 "itemtype": "file",
645 "path": "a",
645 "path": "a",
646 "unresolved": true
646 "unresolved": true
647 }
647 }
648 ]
648 ]
649
649
650 $ hg resolve -m
650 $ hg resolve -m
651 (no more unresolved files)
651 (no more unresolved files)
652
652
653 $ hg resolve -l
653 $ hg resolve -l
654 R a
654 R a
655 $ hg status
655 $ hg status
656 M foo
656 M foo
657 # No unresolved merge conflicts.
657 # No unresolved merge conflicts.
658
658
659 $ hg status -Tjson
659 $ hg status -Tjson
660 [
660 [
661 {
661 {
662 "itemtype": "file",
662 "itemtype": "file",
663 "path": "foo",
663 "path": "foo",
664 "status": "M"
664 "status": "M"
665 }
665 }
666 ]
666 ]
667
667
668 Test that 4 is detected as the no-argument destination from 3 and also moves
668 Test that 4 is detected as the no-argument destination from 3 and also moves
669 the bookmark with it
669 the bookmark with it
670 $ hg up --quiet 0 # we should be able to update to 3 directly
670 $ hg up --quiet 0 # we should be able to update to 3 directly
671 $ hg status
671 $ hg status
672 M foo
672 M foo
673 $ hg up --quiet --hidden 3 # but not implemented yet.
673 $ hg up --quiet --hidden 3 # but not implemented yet.
674 updated to hidden changeset 6efa171f091b
674 updated to hidden changeset 6efa171f091b
675 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
675 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
676 $ hg book -f bm
676 $ hg book -f bm
677 $ hg up
677 $ hg up
678 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
678 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
679 updating bookmark bm
679 updating bookmark bm
680 $ hg book
680 $ hg book
681 * bm 4:d047485b3896
681 * bm 4:d047485b3896
682
682
683 Test that 5 is detected as a valid destination from 1
683 Test that 5 is detected as a valid destination from 1
684 $ hg up --quiet 0 # we should be able to update to 3 directly
684 $ hg up --quiet 0 # we should be able to update to 3 directly
685 $ hg up --quiet --hidden 3 # but not implemented yet.
685 $ hg up --quiet --hidden 3 # but not implemented yet.
686 updated to hidden changeset 6efa171f091b
686 updated to hidden changeset 6efa171f091b
687 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
687 (hidden revision '6efa171f091b' was rewritten as: d047485b3896)
688 $ hg up 5
688 $ hg up 5
689 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
689 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
690
690
691 Test that 5 is not detected as a valid destination from 2
691 Test that 5 is not detected as a valid destination from 2
692 $ hg up --quiet 0
692 $ hg up --quiet 0
693 $ hg up --quiet 2
693 $ hg up --quiet 2
694 $ hg up 5
694 $ hg up 5
695 abort: uncommitted changes
695 abort: uncommitted changes
696 (commit or update --clean to discard changes)
696 (commit or update --clean to discard changes)
697 [255]
697 [255]
698
698
699 Test that we don't crash when updating from a pruned changeset (i.e. has no
699 Test that we update to the closest non-obsolete ancestor when updating from a
700 successors). Behavior should probably be that we update to the first
700 pruned changeset (i.e. that has no successors)
701 non-obsolete parent but that will be decided later.
702 $ hg id --debug -r 2
701 $ hg id --debug -r 2
703 bd10386d478cd5a9faf2e604114c8e6da62d3889
702 bd10386d478cd5a9faf2e604114c8e6da62d3889
704 $ hg up --quiet 0
703 $ hg up --quiet 0
705 $ hg up --quiet 2
704 $ hg up --quiet 2
706 $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
705 $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
707 1 new obsolescence markers
706 1 new obsolescence markers
708 obsoleted 1 changesets
707 obsoleted 1 changesets
708 $ hg log -r '_destupdate()'
709 1:0786582aa4b1 1 (no-eol)
709 $ hg up
710 $ hg up
710 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
711 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
711
712 Test experimental revset support
713
714 $ hg log -r '_destupdate()'
715 2:bd10386d478c 2 (no-eol)
716
712
717 Test that boolean flags allow --no-flag specification to override [defaults]
713 Test that boolean flags allow --no-flag specification to override [defaults]
718 $ cat >> $HGRCPATH <<EOF
714 $ cat >> $HGRCPATH <<EOF
719 > [defaults]
715 > [defaults]
720 > update = --check
716 > update = --check
721 > EOF
717 > EOF
722 $ hg co 2
718 $ hg co 1
723 abort: uncommitted changes
719 abort: uncommitted changes
724 [20]
720 [20]
725 $ hg co --no-check 2
721 $ hg co --no-check 1
726 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
722 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
General Comments 0
You need to be logged in to leave comments. Login now