##// END OF EJS Templates
update: use single quotes in use warning
timeless -
r29964:40f84553 default
parent child Browse files
Show More
@@ -1,437 +1,437 b''
1 # destutil.py - Mercurial utility function for command destination
1 # destutil.py - Mercurial utility function for command destination
2 #
2 #
3 # Copyright Matt Mackall <mpm@selenic.com> and other
3 # Copyright Matt Mackall <mpm@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 (
11 from . import (
12 bookmarks,
12 bookmarks,
13 error,
13 error,
14 obsolete,
14 obsolete,
15 )
15 )
16
16
17 def _destupdatevalidate(repo, rev, clean, check):
17 def _destupdatevalidate(repo, rev, clean, check):
18 """validate that the destination comply to various rules
18 """validate that the destination comply to various rules
19
19
20 This exists as its own function to help wrapping from extensions."""
20 This exists as its own function to help wrapping from extensions."""
21 wc = repo[None]
21 wc = repo[None]
22 p1 = wc.p1()
22 p1 = wc.p1()
23 if not clean:
23 if not clean:
24 # Check that the update is linear.
24 # Check that the update is linear.
25 #
25 #
26 # Mercurial do not allow update-merge for non linear pattern
26 # Mercurial do not allow update-merge for non linear pattern
27 # (that would be technically possible but was considered too confusing
27 # (that would be technically possible but was considered too confusing
28 # for user a long time ago)
28 # for user a long time ago)
29 #
29 #
30 # See mercurial.merge.update for details
30 # See mercurial.merge.update for details
31 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
31 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
32 dirty = wc.dirty(missing=True)
32 dirty = wc.dirty(missing=True)
33 foreground = obsolete.foreground(repo, [p1.node()])
33 foreground = obsolete.foreground(repo, [p1.node()])
34 if not repo[rev].node() in foreground:
34 if not repo[rev].node() in foreground:
35 if dirty:
35 if dirty:
36 msg = _("uncommitted changes")
36 msg = _("uncommitted changes")
37 hint = _("commit and merge, or update --clean to"
37 hint = _("commit and merge, or update --clean to"
38 " discard changes")
38 " discard changes")
39 raise error.UpdateAbort(msg, hint=hint)
39 raise error.UpdateAbort(msg, hint=hint)
40 elif not check: # destination is not a descendant.
40 elif not check: # destination is not a descendant.
41 msg = _("not a linear update")
41 msg = _("not a linear update")
42 hint = _("merge or update --check to force update")
42 hint = _("merge or update --check to force update")
43 raise error.UpdateAbort(msg, hint=hint)
43 raise error.UpdateAbort(msg, hint=hint)
44
44
45 def _destupdateobs(repo, clean, check):
45 def _destupdateobs(repo, clean, check):
46 """decide of an update destination from obsolescence markers"""
46 """decide of an update destination from obsolescence markers"""
47 node = None
47 node = None
48 wc = repo[None]
48 wc = repo[None]
49 p1 = wc.p1()
49 p1 = wc.p1()
50 movemark = None
50 movemark = None
51
51
52 if p1.obsolete() and not p1.children():
52 if p1.obsolete() and not p1.children():
53 # allow updating to successors
53 # allow updating to successors
54 successors = obsolete.successorssets(repo, p1.node())
54 successors = obsolete.successorssets(repo, p1.node())
55
55
56 # behavior of certain cases is as follows,
56 # behavior of certain cases is as follows,
57 #
57 #
58 # divergent changesets: update to highest rev, similar to what
58 # divergent changesets: update to highest rev, similar to what
59 # is currently done when there are more than one head
59 # is currently done when there are more than one head
60 # (i.e. 'tip')
60 # (i.e. 'tip')
61 #
61 #
62 # replaced changesets: same as divergent except we know there
62 # replaced changesets: same as divergent except we know there
63 # is no conflict
63 # is no conflict
64 #
64 #
65 # pruned changeset: no update is done; though, we could
65 # pruned changeset: no update is done; though, we could
66 # consider updating to the first non-obsolete parent,
66 # consider updating to the first non-obsolete parent,
67 # similar to what is current done for 'hg prune'
67 # similar to what is current done for 'hg prune'
68
68
69 if successors:
69 if successors:
70 # flatten the list here handles both divergent (len > 1)
70 # flatten the list here handles both divergent (len > 1)
71 # and the usual case (len = 1)
71 # and the usual case (len = 1)
72 successors = [n for sub in successors for n in sub]
72 successors = [n for sub in successors for n in sub]
73
73
74 # get the max revision for the given successors set,
74 # get the max revision for the given successors set,
75 # i.e. the 'tip' of a set
75 # i.e. the 'tip' of a set
76 node = repo.revs('max(%ln)', successors).first()
76 node = repo.revs('max(%ln)', successors).first()
77 if bookmarks.isactivewdirparent(repo):
77 if bookmarks.isactivewdirparent(repo):
78 movemark = repo['.'].node()
78 movemark = repo['.'].node()
79 return node, movemark, None
79 return node, movemark, None
80
80
81 def _destupdatebook(repo, clean, check):
81 def _destupdatebook(repo, clean, check):
82 """decide on an update destination from active bookmark"""
82 """decide on an update destination from active bookmark"""
83 # we also move the active bookmark, if any
83 # we also move the active bookmark, if any
84 activemark = None
84 activemark = None
85 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
85 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
86 if node is not None:
86 if node is not None:
87 activemark = node
87 activemark = node
88 return node, movemark, activemark
88 return node, movemark, activemark
89
89
90 def _destupdatebranch(repo, clean, check):
90 def _destupdatebranch(repo, clean, check):
91 """decide on an update destination from current branch
91 """decide on an update destination from current branch
92
92
93 This ignores closed branch heads.
93 This ignores closed branch heads.
94 """
94 """
95 wc = repo[None]
95 wc = repo[None]
96 movemark = node = None
96 movemark = node = None
97 currentbranch = wc.branch()
97 currentbranch = wc.branch()
98
98
99 if clean:
99 if clean:
100 currentbranch = repo['.'].branch()
100 currentbranch = repo['.'].branch()
101
101
102 if currentbranch in repo.branchmap():
102 if currentbranch in repo.branchmap():
103 heads = repo.branchheads(currentbranch)
103 heads = repo.branchheads(currentbranch)
104 if heads:
104 if heads:
105 node = repo.revs('max(.::(%ln))', heads).first()
105 node = repo.revs('max(.::(%ln))', heads).first()
106 if bookmarks.isactivewdirparent(repo):
106 if bookmarks.isactivewdirparent(repo):
107 movemark = repo['.'].node()
107 movemark = repo['.'].node()
108 elif currentbranch == 'default' and not wc.p1():
108 elif currentbranch == 'default' and not wc.p1():
109 # "null" parent belongs to "default" branch, but it doesn't exist, so
109 # "null" parent belongs to "default" branch, but it doesn't exist, so
110 # update to the tipmost non-closed branch head
110 # update to the tipmost non-closed branch head
111 node = repo.revs('max(head() and not closed())').first()
111 node = repo.revs('max(head() and not closed())').first()
112 else:
112 else:
113 node = repo['.'].node()
113 node = repo['.'].node()
114 return node, movemark, None
114 return node, movemark, None
115
115
116 def _destupdatebranchfallback(repo, clean, check):
116 def _destupdatebranchfallback(repo, clean, check):
117 """decide on an update destination from closed heads in current branch"""
117 """decide on an update destination from closed heads in current branch"""
118 wc = repo[None]
118 wc = repo[None]
119 currentbranch = wc.branch()
119 currentbranch = wc.branch()
120 movemark = None
120 movemark = None
121 if currentbranch in repo.branchmap():
121 if currentbranch in repo.branchmap():
122 # here, all descendant branch heads are closed
122 # here, all descendant branch heads are closed
123 heads = repo.branchheads(currentbranch, closed=True)
123 heads = repo.branchheads(currentbranch, closed=True)
124 assert heads, "any branch has at least one head"
124 assert heads, "any branch has at least one head"
125 node = repo.revs('max(.::(%ln))', heads).first()
125 node = repo.revs('max(.::(%ln))', heads).first()
126 assert node is not None, ("any revision has at least "
126 assert node is not None, ("any revision has at least "
127 "one descendant branch head")
127 "one descendant branch head")
128 if bookmarks.isactivewdirparent(repo):
128 if bookmarks.isactivewdirparent(repo):
129 movemark = repo['.'].node()
129 movemark = repo['.'].node()
130 else:
130 else:
131 # here, no "default" branch, and all branches are closed
131 # here, no "default" branch, and all branches are closed
132 node = repo.lookup('tip')
132 node = repo.lookup('tip')
133 assert node is not None, "'tip' exists even in empty repository"
133 assert node is not None, "'tip' exists even in empty repository"
134 return node, movemark, None
134 return node, movemark, None
135
135
136 # order in which each step should be evalutated
136 # order in which each step should be evalutated
137 # steps are run until one finds a destination
137 # steps are run until one finds a destination
138 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
138 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
139 # mapping to ease extension overriding steps.
139 # mapping to ease extension overriding steps.
140 destupdatestepmap = {'evolution': _destupdateobs,
140 destupdatestepmap = {'evolution': _destupdateobs,
141 'bookmark': _destupdatebook,
141 'bookmark': _destupdatebook,
142 'branch': _destupdatebranch,
142 'branch': _destupdatebranch,
143 'branchfallback': _destupdatebranchfallback,
143 'branchfallback': _destupdatebranchfallback,
144 }
144 }
145
145
146 def destupdate(repo, clean=False, check=False):
146 def destupdate(repo, clean=False, check=False):
147 """destination for bare update operation
147 """destination for bare update operation
148
148
149 return (rev, movemark, activemark)
149 return (rev, movemark, activemark)
150
150
151 - rev: the revision to update to,
151 - rev: the revision to update to,
152 - movemark: node to move the active bookmark from
152 - movemark: node to move the active bookmark from
153 (cf bookmark.calculate update),
153 (cf bookmark.calculate update),
154 - activemark: a bookmark to activate at the end of the update.
154 - activemark: a bookmark to activate at the end of the update.
155 """
155 """
156 node = movemark = activemark = None
156 node = movemark = activemark = None
157
157
158 for step in destupdatesteps:
158 for step in destupdatesteps:
159 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
159 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
160 if node is not None:
160 if node is not None:
161 break
161 break
162 rev = repo[node].rev()
162 rev = repo[node].rev()
163
163
164 _destupdatevalidate(repo, rev, clean, check)
164 _destupdatevalidate(repo, rev, clean, check)
165
165
166 return rev, movemark, activemark
166 return rev, movemark, activemark
167
167
168 msgdestmerge = {
168 msgdestmerge = {
169 # too many matching divergent bookmark
169 # too many matching divergent bookmark
170 'toomanybookmarks':
170 'toomanybookmarks':
171 {'merge':
171 {'merge':
172 (_("multiple matching bookmarks to merge -"
172 (_("multiple matching bookmarks to merge -"
173 " please merge with an explicit rev or bookmark"),
173 " please merge with an explicit rev or bookmark"),
174 _("run 'hg heads' to see all heads")),
174 _("run 'hg heads' to see all heads")),
175 'rebase':
175 'rebase':
176 (_("multiple matching bookmarks to rebase -"
176 (_("multiple matching bookmarks to rebase -"
177 " please rebase to an explicit rev or bookmark"),
177 " please rebase to an explicit rev or bookmark"),
178 _("run 'hg heads' to see all heads")),
178 _("run 'hg heads' to see all heads")),
179 },
179 },
180 # no other matching divergent bookmark
180 # no other matching divergent bookmark
181 'nootherbookmarks':
181 'nootherbookmarks':
182 {'merge':
182 {'merge':
183 (_("no matching bookmark to merge - "
183 (_("no matching bookmark to merge - "
184 "please merge with an explicit rev or bookmark"),
184 "please merge with an explicit rev or bookmark"),
185 _("run 'hg heads' to see all heads")),
185 _("run 'hg heads' to see all heads")),
186 'rebase':
186 'rebase':
187 (_("no matching bookmark to rebase - "
187 (_("no matching bookmark to rebase - "
188 "please rebase to an explicit rev or bookmark"),
188 "please rebase to an explicit rev or bookmark"),
189 _("run 'hg heads' to see all heads")),
189 _("run 'hg heads' to see all heads")),
190 },
190 },
191 # branch have too many unbookmarked heads, no obvious destination
191 # branch have too many unbookmarked heads, no obvious destination
192 'toomanyheads':
192 'toomanyheads':
193 {'merge':
193 {'merge':
194 (_("branch '%s' has %d heads - please merge with an explicit rev"),
194 (_("branch '%s' has %d heads - please merge with an explicit rev"),
195 _("run 'hg heads .' to see heads")),
195 _("run 'hg heads .' to see heads")),
196 'rebase':
196 'rebase':
197 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
197 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
198 _("run 'hg heads .' to see heads")),
198 _("run 'hg heads .' to see heads")),
199 },
199 },
200 # branch have no other unbookmarked heads
200 # branch have no other unbookmarked heads
201 'bookmarkedheads':
201 'bookmarkedheads':
202 {'merge':
202 {'merge':
203 (_("heads are bookmarked - please merge with an explicit rev"),
203 (_("heads are bookmarked - please merge with an explicit rev"),
204 _("run 'hg heads' to see all heads")),
204 _("run 'hg heads' to see all heads")),
205 'rebase':
205 'rebase':
206 (_("heads are bookmarked - please rebase to an explicit rev"),
206 (_("heads are bookmarked - please rebase to an explicit rev"),
207 _("run 'hg heads' to see all heads")),
207 _("run 'hg heads' to see all heads")),
208 },
208 },
209 # branch have just a single heads, but there is other branches
209 # branch have just a single heads, but there is other branches
210 'nootherbranchheads':
210 'nootherbranchheads':
211 {'merge':
211 {'merge':
212 (_("branch '%s' has one head - please merge with an explicit rev"),
212 (_("branch '%s' has one head - please merge with an explicit rev"),
213 _("run 'hg heads' to see all heads")),
213 _("run 'hg heads' to see all heads")),
214 'rebase':
214 'rebase':
215 (_("branch '%s' has one head - please rebase to an explicit rev"),
215 (_("branch '%s' has one head - please rebase to an explicit rev"),
216 _("run 'hg heads' to see all heads")),
216 _("run 'hg heads' to see all heads")),
217 },
217 },
218 # repository have a single head
218 # repository have a single head
219 'nootherheads':
219 'nootherheads':
220 {'merge':
220 {'merge':
221 (_('nothing to merge'),
221 (_('nothing to merge'),
222 None),
222 None),
223 'rebase':
223 'rebase':
224 (_('nothing to rebase'),
224 (_('nothing to rebase'),
225 None),
225 None),
226 },
226 },
227 # repository have a single head and we are not on it
227 # repository have a single head and we are not on it
228 'nootherheadsbehind':
228 'nootherheadsbehind':
229 {'merge':
229 {'merge':
230 (_('nothing to merge'),
230 (_('nothing to merge'),
231 _("use 'hg update' instead")),
231 _("use 'hg update' instead")),
232 'rebase':
232 'rebase':
233 (_('nothing to rebase'),
233 (_('nothing to rebase'),
234 _("use 'hg update' instead")),
234 _("use 'hg update' instead")),
235 },
235 },
236 # We are not on a head
236 # We are not on a head
237 'notatheads':
237 'notatheads':
238 {'merge':
238 {'merge':
239 (_('working directory not at a head revision'),
239 (_('working directory not at a head revision'),
240 _("use 'hg update' or merge with an explicit revision")),
240 _("use 'hg update' or merge with an explicit revision")),
241 'rebase':
241 'rebase':
242 (_('working directory not at a head revision'),
242 (_('working directory not at a head revision'),
243 _("use 'hg update' or rebase to an explicit revision"))
243 _("use 'hg update' or rebase to an explicit revision"))
244 },
244 },
245 'emptysourceset':
245 'emptysourceset':
246 {'merge':
246 {'merge':
247 (_('source set is empty'),
247 (_('source set is empty'),
248 None),
248 None),
249 'rebase':
249 'rebase':
250 (_('source set is empty'),
250 (_('source set is empty'),
251 None),
251 None),
252 },
252 },
253 'multiplebranchessourceset':
253 'multiplebranchessourceset':
254 {'merge':
254 {'merge':
255 (_('source set is rooted in multiple branches'),
255 (_('source set is rooted in multiple branches'),
256 None),
256 None),
257 'rebase':
257 'rebase':
258 (_('rebaseset is rooted in multiple named branches'),
258 (_('rebaseset is rooted in multiple named branches'),
259 _('specify an explicit destination with --dest')),
259 _('specify an explicit destination with --dest')),
260 },
260 },
261 }
261 }
262
262
263 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
263 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
264 """find merge destination in the active bookmark case"""
264 """find merge destination in the active bookmark case"""
265 node = None
265 node = None
266 bmheads = repo.bookmarkheads(repo._activebookmark)
266 bmheads = repo.bookmarkheads(repo._activebookmark)
267 curhead = repo[repo._activebookmark].node()
267 curhead = repo[repo._activebookmark].node()
268 if len(bmheads) == 2:
268 if len(bmheads) == 2:
269 if curhead == bmheads[0]:
269 if curhead == bmheads[0]:
270 node = bmheads[1]
270 node = bmheads[1]
271 else:
271 else:
272 node = bmheads[0]
272 node = bmheads[0]
273 elif len(bmheads) > 2:
273 elif len(bmheads) > 2:
274 msg, hint = msgdestmerge['toomanybookmarks'][action]
274 msg, hint = msgdestmerge['toomanybookmarks'][action]
275 raise error.ManyMergeDestAbort(msg, hint=hint)
275 raise error.ManyMergeDestAbort(msg, hint=hint)
276 elif len(bmheads) <= 1:
276 elif len(bmheads) <= 1:
277 msg, hint = msgdestmerge['nootherbookmarks'][action]
277 msg, hint = msgdestmerge['nootherbookmarks'][action]
278 raise error.NoMergeDestAbort(msg, hint=hint)
278 raise error.NoMergeDestAbort(msg, hint=hint)
279 assert node is not None
279 assert node is not None
280 return node
280 return node
281
281
282 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
282 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
283 destspace=None):
283 destspace=None):
284 """find merge destination based on branch heads"""
284 """find merge destination based on branch heads"""
285 node = None
285 node = None
286
286
287 if sourceset is None:
287 if sourceset is None:
288 sourceset = [repo[repo.dirstate.p1()].rev()]
288 sourceset = [repo[repo.dirstate.p1()].rev()]
289 branch = repo.dirstate.branch()
289 branch = repo.dirstate.branch()
290 elif not sourceset:
290 elif not sourceset:
291 msg, hint = msgdestmerge['emptysourceset'][action]
291 msg, hint = msgdestmerge['emptysourceset'][action]
292 raise error.NoMergeDestAbort(msg, hint=hint)
292 raise error.NoMergeDestAbort(msg, hint=hint)
293 else:
293 else:
294 branch = None
294 branch = None
295 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
295 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
296 if branch is not None and ctx.branch() != branch:
296 if branch is not None and ctx.branch() != branch:
297 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
297 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
298 raise error.ManyMergeDestAbort(msg, hint=hint)
298 raise error.ManyMergeDestAbort(msg, hint=hint)
299 branch = ctx.branch()
299 branch = ctx.branch()
300
300
301 bheads = repo.branchheads(branch)
301 bheads = repo.branchheads(branch)
302 onhead = repo.revs('%ld and %ln', sourceset, bheads)
302 onhead = repo.revs('%ld and %ln', sourceset, bheads)
303 if onheadcheck and not onhead:
303 if onheadcheck and not onhead:
304 # Case A: working copy if not on a head. (merge only)
304 # Case A: working copy if not on a head. (merge only)
305 #
305 #
306 # This is probably a user mistake We bailout pointing at 'hg update'
306 # This is probably a user mistake We bailout pointing at 'hg update'
307 if len(repo.heads()) <= 1:
307 if len(repo.heads()) <= 1:
308 msg, hint = msgdestmerge['nootherheadsbehind'][action]
308 msg, hint = msgdestmerge['nootherheadsbehind'][action]
309 else:
309 else:
310 msg, hint = msgdestmerge['notatheads'][action]
310 msg, hint = msgdestmerge['notatheads'][action]
311 raise error.Abort(msg, hint=hint)
311 raise error.Abort(msg, hint=hint)
312 # remove heads descendants of source from the set
312 # remove heads descendants of source from the set
313 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
313 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
314 # filters out bookmarked heads
314 # filters out bookmarked heads
315 nbhs = list(repo.revs('%ld - bookmark()', bheads))
315 nbhs = list(repo.revs('%ld - bookmark()', bheads))
316
316
317 if destspace is not None:
317 if destspace is not None:
318 # restrict search space
318 # restrict search space
319 # used in the 'hg pull --rebase' case, see issue 5214.
319 # used in the 'hg pull --rebase' case, see issue 5214.
320 nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
320 nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
321
321
322 if len(nbhs) > 1:
322 if len(nbhs) > 1:
323 # Case B: There is more than 1 other anonymous heads
323 # Case B: There is more than 1 other anonymous heads
324 #
324 #
325 # This means that there will be more than 1 candidate. This is
325 # This means that there will be more than 1 candidate. This is
326 # ambiguous. We abort asking the user to pick as explicit destination
326 # ambiguous. We abort asking the user to pick as explicit destination
327 # instead.
327 # instead.
328 msg, hint = msgdestmerge['toomanyheads'][action]
328 msg, hint = msgdestmerge['toomanyheads'][action]
329 msg %= (branch, len(bheads) + 1)
329 msg %= (branch, len(bheads) + 1)
330 raise error.ManyMergeDestAbort(msg, hint=hint)
330 raise error.ManyMergeDestAbort(msg, hint=hint)
331 elif not nbhs:
331 elif not nbhs:
332 # Case B: There is no other anonymous heads
332 # Case B: There is no other anonymous heads
333 #
333 #
334 # This means that there is no natural candidate to merge with.
334 # This means that there is no natural candidate to merge with.
335 # We abort, with various messages for various cases.
335 # We abort, with various messages for various cases.
336 if bheads:
336 if bheads:
337 msg, hint = msgdestmerge['bookmarkedheads'][action]
337 msg, hint = msgdestmerge['bookmarkedheads'][action]
338 elif len(repo.heads()) > 1:
338 elif len(repo.heads()) > 1:
339 msg, hint = msgdestmerge['nootherbranchheads'][action]
339 msg, hint = msgdestmerge['nootherbranchheads'][action]
340 msg %= branch
340 msg %= branch
341 elif not onhead:
341 elif not onhead:
342 # if 'onheadcheck == False' (rebase case),
342 # if 'onheadcheck == False' (rebase case),
343 # this was not caught in Case A.
343 # this was not caught in Case A.
344 msg, hint = msgdestmerge['nootherheadsbehind'][action]
344 msg, hint = msgdestmerge['nootherheadsbehind'][action]
345 else:
345 else:
346 msg, hint = msgdestmerge['nootherheads'][action]
346 msg, hint = msgdestmerge['nootherheads'][action]
347 raise error.NoMergeDestAbort(msg, hint=hint)
347 raise error.NoMergeDestAbort(msg, hint=hint)
348 else:
348 else:
349 node = nbhs[0]
349 node = nbhs[0]
350 assert node is not None
350 assert node is not None
351 return node
351 return node
352
352
353 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
353 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
354 destspace=None):
354 destspace=None):
355 """return the default destination for a merge
355 """return the default destination for a merge
356
356
357 (or raise exception about why it can't pick one)
357 (or raise exception about why it can't pick one)
358
358
359 :action: the action being performed, controls emitted error message
359 :action: the action being performed, controls emitted error message
360 """
360 """
361 # destspace is here to work around issues with `hg pull --rebase` see
361 # destspace is here to work around issues with `hg pull --rebase` see
362 # issue5214 for details
362 # issue5214 for details
363 if repo._activebookmark:
363 if repo._activebookmark:
364 node = _destmergebook(repo, action=action, sourceset=sourceset,
364 node = _destmergebook(repo, action=action, sourceset=sourceset,
365 destspace=destspace)
365 destspace=destspace)
366 else:
366 else:
367 node = _destmergebranch(repo, action=action, sourceset=sourceset,
367 node = _destmergebranch(repo, action=action, sourceset=sourceset,
368 onheadcheck=onheadcheck, destspace=destspace)
368 onheadcheck=onheadcheck, destspace=destspace)
369 return repo[node].rev()
369 return repo[node].rev()
370
370
371 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
371 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
372
372
373 def desthistedit(ui, repo):
373 def desthistedit(ui, repo):
374 """Default base revision to edit for `hg histedit`."""
374 """Default base revision to edit for `hg histedit`."""
375 # Avoid cycle: scmutil -> revset -> destutil
375 # Avoid cycle: scmutil -> revset -> destutil
376 from . import scmutil
376 from . import scmutil
377
377
378 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
378 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
379 if default:
379 if default:
380 revs = scmutil.revrange(repo, [default])
380 revs = scmutil.revrange(repo, [default])
381 if revs:
381 if revs:
382 # The revset supplied by the user may not be in ascending order nor
382 # The revset supplied by the user may not be in ascending order nor
383 # take the first revision. So do this manually.
383 # take the first revision. So do this manually.
384 revs.sort()
384 revs.sort()
385 return revs.first()
385 return revs.first()
386
386
387 return None
387 return None
388
388
389 def _statusotherbook(ui, repo):
389 def _statusotherbook(ui, repo):
390 bmheads = repo.bookmarkheads(repo._activebookmark)
390 bmheads = repo.bookmarkheads(repo._activebookmark)
391 curhead = repo[repo._activebookmark].node()
391 curhead = repo[repo._activebookmark].node()
392 if repo.revs('%n and parents()', curhead):
392 if repo.revs('%n and parents()', curhead):
393 # we are on the active bookmark
393 # we are on the active bookmark
394 bmheads = [b for b in bmheads if curhead != b]
394 bmheads = [b for b in bmheads if curhead != b]
395 if bmheads:
395 if bmheads:
396 msg = _('%i other divergent bookmarks for "%s"\n')
396 msg = _('%i other divergent bookmarks for "%s"\n')
397 ui.status(msg % (len(bmheads), repo._activebookmark))
397 ui.status(msg % (len(bmheads), repo._activebookmark))
398
398
399 def _statusotherbranchheads(ui, repo):
399 def _statusotherbranchheads(ui, repo):
400 currentbranch = repo.dirstate.branch()
400 currentbranch = repo.dirstate.branch()
401 allheads = repo.branchheads(currentbranch, closed=True)
401 allheads = repo.branchheads(currentbranch, closed=True)
402 heads = repo.branchheads(currentbranch)
402 heads = repo.branchheads(currentbranch)
403 if repo.revs('%ln and parents()', allheads):
403 if repo.revs('%ln and parents()', allheads):
404 # we are on a head, even though it might be closed
404 # we are on a head, even though it might be closed
405 #
405 #
406 # on closed otherheads
406 # on closed otherheads
407 # ========= ==========
407 # ========= ==========
408 # o 0 all heads for current branch are closed
408 # o 0 all heads for current branch are closed
409 # N only descendant branch heads are closed
409 # N only descendant branch heads are closed
410 # x 0 there is only one non-closed branch head
410 # x 0 there is only one non-closed branch head
411 # N there are some non-closed branch heads
411 # N there are some non-closed branch heads
412 # ========= ==========
412 # ========= ==========
413 otherheads = repo.revs('%ln - parents()', heads)
413 otherheads = repo.revs('%ln - parents()', heads)
414 if repo['.'].closesbranch():
414 if repo['.'].closesbranch():
415 ui.warn(_('no open descendant heads on branch "%s", '
415 ui.warn(_('no open descendant heads on branch "%s", '
416 'updating to a closed head\n') %
416 'updating to a closed head\n') %
417 (currentbranch))
417 (currentbranch))
418 if otherheads:
418 if otherheads:
419 ui.warn(_('(committing will reopen the head, '
419 ui.warn(_("(committing will reopen the head, "
420 'use `hg heads .` to see %i other heads)\n') %
420 "use 'hg heads .' to see %i other heads)\n") %
421 (len(otherheads)))
421 (len(otherheads)))
422 else:
422 else:
423 ui.warn(_('(committing will reopen branch "%s")\n') %
423 ui.warn(_('(committing will reopen branch "%s")\n') %
424 (currentbranch))
424 (currentbranch))
425 elif otherheads:
425 elif otherheads:
426 ui.status(_('%i other heads for branch "%s"\n') %
426 ui.status(_('%i other heads for branch "%s"\n') %
427 (len(otherheads), currentbranch))
427 (len(otherheads), currentbranch))
428
428
429 def statusotherdests(ui, repo):
429 def statusotherdests(ui, repo):
430 """Print message about other head"""
430 """Print message about other head"""
431 # XXX we should probably include a hint:
431 # XXX we should probably include a hint:
432 # - about what to do
432 # - about what to do
433 # - how to see such heads
433 # - how to see such heads
434 if repo._activebookmark:
434 if repo._activebookmark:
435 _statusotherbook(ui, repo)
435 _statusotherbook(ui, repo)
436 else:
436 else:
437 _statusotherbranchheads(ui, repo)
437 _statusotherbranchheads(ui, repo)
@@ -1,392 +1,392 b''
1 # Construct the following history tree:
1 # Construct the following history tree:
2 #
2 #
3 # @ 5:e1bb631146ca b1
3 # @ 5:e1bb631146ca b1
4 # |
4 # |
5 # o 4:a4fdb3b883c4 0:b608b9236435 b1
5 # o 4:a4fdb3b883c4 0:b608b9236435 b1
6 # |
6 # |
7 # | o 3:4b57d2520816 1:44592833ba9f
7 # | o 3:4b57d2520816 1:44592833ba9f
8 # | |
8 # | |
9 # | | o 2:063f31070f65
9 # | | o 2:063f31070f65
10 # | |/
10 # | |/
11 # | o 1:44592833ba9f
11 # | o 1:44592833ba9f
12 # |/
12 # |/
13 # o 0:b608b9236435
13 # o 0:b608b9236435
14
14
15 $ mkdir b1
15 $ mkdir b1
16 $ cd b1
16 $ cd b1
17 $ hg init
17 $ hg init
18 $ echo foo > foo
18 $ echo foo > foo
19 $ echo zero > a
19 $ echo zero > a
20 $ hg init sub
20 $ hg init sub
21 $ echo suba > sub/suba
21 $ echo suba > sub/suba
22 $ hg --cwd sub ci -Am addsuba
22 $ hg --cwd sub ci -Am addsuba
23 adding suba
23 adding suba
24 $ echo 'sub = sub' > .hgsub
24 $ echo 'sub = sub' > .hgsub
25 $ hg ci -qAm0
25 $ hg ci -qAm0
26 $ echo one > a ; hg ci -m1
26 $ echo one > a ; hg ci -m1
27 $ echo two > a ; hg ci -m2
27 $ echo two > a ; hg ci -m2
28 $ hg up -q 1
28 $ hg up -q 1
29 $ echo three > a ; hg ci -qm3
29 $ echo three > a ; hg ci -qm3
30 $ hg up -q 0
30 $ hg up -q 0
31 $ hg branch -q b1
31 $ hg branch -q b1
32 $ echo four > a ; hg ci -qm4
32 $ echo four > a ; hg ci -qm4
33 $ echo five > a ; hg ci -qm5
33 $ echo five > a ; hg ci -qm5
34
34
35 Initial repo state:
35 Initial repo state:
36
36
37 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
37 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
38 @ 5:ff252e8273df b1
38 @ 5:ff252e8273df b1
39 |
39 |
40 o 4:d047485b3896 0:60829823a42a b1
40 o 4:d047485b3896 0:60829823a42a b1
41 |
41 |
42 | o 3:6efa171f091b 1:0786582aa4b1
42 | o 3:6efa171f091b 1:0786582aa4b1
43 | |
43 | |
44 | | o 2:bd10386d478c
44 | | o 2:bd10386d478c
45 | |/
45 | |/
46 | o 1:0786582aa4b1
46 | o 1:0786582aa4b1
47 |/
47 |/
48 o 0:60829823a42a
48 o 0:60829823a42a
49
49
50
50
51 Make sure update doesn't assume b1 is a repository if invoked from outside:
51 Make sure update doesn't assume b1 is a repository if invoked from outside:
52
52
53 $ cd ..
53 $ cd ..
54 $ hg update b1
54 $ hg update b1
55 abort: no repository found in '$TESTTMP' (.hg not found)!
55 abort: no repository found in '$TESTTMP' (.hg not found)!
56 [255]
56 [255]
57 $ cd b1
57 $ cd b1
58
58
59 Test helper functions:
59 Test helper functions:
60
60
61 $ revtest () {
61 $ revtest () {
62 > msg=$1
62 > msg=$1
63 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
63 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
64 > startrev=$3
64 > startrev=$3
65 > targetrev=$4
65 > targetrev=$4
66 > opt=$5
66 > opt=$5
67 > hg up -qC $startrev
67 > hg up -qC $startrev
68 > test $dirtyflag = dirty && echo dirty > foo
68 > test $dirtyflag = dirty && echo dirty > foo
69 > test $dirtyflag = dirtysub && echo dirty > sub/suba
69 > test $dirtyflag = dirtysub && echo dirty > sub/suba
70 > hg up $opt $targetrev
70 > hg up $opt $targetrev
71 > hg parent --template 'parent={rev}\n'
71 > hg parent --template 'parent={rev}\n'
72 > hg stat -S
72 > hg stat -S
73 > }
73 > }
74
74
75 $ norevtest () {
75 $ norevtest () {
76 > msg=$1
76 > msg=$1
77 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
77 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
78 > startrev=$3
78 > startrev=$3
79 > opt=$4
79 > opt=$4
80 > hg up -qC $startrev
80 > hg up -qC $startrev
81 > test $dirtyflag = dirty && echo dirty > foo
81 > test $dirtyflag = dirty && echo dirty > foo
82 > test $dirtyflag = dirtysub && echo dirty > sub/suba
82 > test $dirtyflag = dirtysub && echo dirty > sub/suba
83 > hg up $opt
83 > hg up $opt
84 > hg parent --template 'parent={rev}\n'
84 > hg parent --template 'parent={rev}\n'
85 > hg stat -S
85 > hg stat -S
86 > }
86 > }
87
87
88 Test cases are documented in a table in the update function of merge.py.
88 Test cases are documented in a table in the update function of merge.py.
89 Cases are run as shown in that table, row by row.
89 Cases are run as shown in that table, row by row.
90
90
91 $ norevtest 'none clean linear' clean 4
91 $ norevtest 'none clean linear' clean 4
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 parent=5
93 parent=5
94
94
95 $ norevtest 'none clean same' clean 2
95 $ norevtest 'none clean same' clean 2
96 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
96 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 1 other heads for branch "default"
97 1 other heads for branch "default"
98 parent=2
98 parent=2
99
99
100
100
101 $ revtest 'none clean linear' clean 1 2
101 $ revtest 'none clean linear' clean 1 2
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 parent=2
103 parent=2
104
104
105 $ revtest 'none clean same' clean 2 3
105 $ revtest 'none clean same' clean 2 3
106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 parent=3
107 parent=3
108
108
109 $ revtest 'none clean cross' clean 3 4
109 $ revtest 'none clean cross' clean 3 4
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 parent=4
111 parent=4
112
112
113
113
114 $ revtest 'none dirty linear' dirty 1 2
114 $ revtest 'none dirty linear' dirty 1 2
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 parent=2
116 parent=2
117 M foo
117 M foo
118
118
119 $ revtest 'none dirtysub linear' dirtysub 1 2
119 $ revtest 'none dirtysub linear' dirtysub 1 2
120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 parent=2
121 parent=2
122 M sub/suba
122 M sub/suba
123
123
124 $ revtest 'none dirty same' dirty 2 3
124 $ revtest 'none dirty same' dirty 2 3
125 abort: uncommitted changes
125 abort: uncommitted changes
126 (commit or update --clean to discard changes)
126 (commit or update --clean to discard changes)
127 parent=2
127 parent=2
128 M foo
128 M foo
129
129
130 $ revtest 'none dirtysub same' dirtysub 2 3
130 $ revtest 'none dirtysub same' dirtysub 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 sub/suba
134 M sub/suba
135
135
136 $ revtest 'none dirty cross' dirty 3 4
136 $ revtest 'none dirty cross' dirty 3 4
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=3
139 parent=3
140 M foo
140 M foo
141
141
142 $ norevtest 'none dirty cross' dirty 2
142 $ norevtest 'none dirty cross' dirty 2
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144 1 other heads for branch "default"
144 1 other heads for branch "default"
145 parent=2
145 parent=2
146 M foo
146 M foo
147
147
148 $ revtest 'none dirtysub cross' dirtysub 3 4
148 $ revtest 'none dirtysub cross' dirtysub 3 4
149 abort: uncommitted changes
149 abort: uncommitted changes
150 (commit or update --clean to discard changes)
150 (commit or update --clean to discard changes)
151 parent=3
151 parent=3
152 M sub/suba
152 M sub/suba
153
153
154 $ revtest '-C dirty linear' dirty 1 2 -C
154 $ revtest '-C dirty linear' dirty 1 2 -C
155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 parent=2
156 parent=2
157
157
158 $ revtest '-c dirty linear' dirty 1 2 -c
158 $ revtest '-c dirty linear' dirty 1 2 -c
159 abort: uncommitted changes
159 abort: uncommitted changes
160 parent=1
160 parent=1
161 M foo
161 M foo
162
162
163 $ revtest '-c dirtysub linear' dirtysub 1 2 -c
163 $ revtest '-c dirtysub linear' dirtysub 1 2 -c
164 abort: uncommitted changes in subrepository 'sub'
164 abort: uncommitted changes in subrepository 'sub'
165 parent=1
165 parent=1
166 M sub/suba
166 M sub/suba
167
167
168 $ norevtest '-c clean same' clean 2 -c
168 $ norevtest '-c clean same' clean 2 -c
169 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 1 other heads for branch "default"
170 1 other heads for branch "default"
171 parent=2
171 parent=2
172
172
173 $ revtest '-cC dirty linear' dirty 1 2 -cC
173 $ revtest '-cC dirty linear' dirty 1 2 -cC
174 abort: cannot specify both -c/--check and -C/--clean
174 abort: cannot specify both -c/--check and -C/--clean
175 parent=1
175 parent=1
176 M foo
176 M foo
177
177
178 $ cd ..
178 $ cd ..
179
179
180 Test updating with closed head
180 Test updating with closed head
181 ---------------------------------------------------------------------
181 ---------------------------------------------------------------------
182
182
183 $ hg clone -U -q b1 closed-heads
183 $ hg clone -U -q b1 closed-heads
184 $ cd closed-heads
184 $ cd closed-heads
185
185
186 Test updating if at least one non-closed branch head exists
186 Test updating if at least one non-closed branch head exists
187
187
188 if on the closed branch head:
188 if on the closed branch head:
189 - update to "."
189 - update to "."
190 - "updated to a closed branch head ...." message is displayed
190 - "updated to a closed branch head ...." message is displayed
191 - "N other heads for ...." message is displayed
191 - "N other heads for ...." message is displayed
192
192
193 $ hg update -q -C 3
193 $ hg update -q -C 3
194 $ hg commit --close-branch -m 6
194 $ hg commit --close-branch -m 6
195 $ norevtest "on closed branch head" clean 6
195 $ norevtest "on closed branch head" clean 6
196 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 no open descendant heads on branch "default", updating to a closed head
197 no open descendant heads on branch "default", updating to a closed head
198 (committing will reopen the head, use `hg heads .` to see 1 other heads)
198 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
199 parent=6
199 parent=6
200
200
201 if descendant non-closed branch head exists, and it is only one branch head:
201 if descendant non-closed branch head exists, and it is only one branch head:
202 - update to it, even if its revision is less than closed one
202 - update to it, even if its revision is less than closed one
203 - "N other heads for ...." message isn't displayed
203 - "N other heads for ...." message isn't displayed
204
204
205 $ norevtest "non-closed 2 should be chosen" clean 1
205 $ norevtest "non-closed 2 should be chosen" clean 1
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 parent=2
207 parent=2
208
208
209 if all descendant branch heads are closed, but there is another branch head:
209 if all descendant branch heads are closed, but there is another branch head:
210 - update to the tipmost descendant head
210 - update to the tipmost descendant head
211 - "updated to a closed branch head ...." message is displayed
211 - "updated to a closed branch head ...." message is displayed
212 - "N other heads for ...." message is displayed
212 - "N other heads for ...." message is displayed
213
213
214 $ norevtest "all descendant branch heads are closed" clean 3
214 $ norevtest "all descendant branch heads are closed" clean 3
215 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 no open descendant heads on branch "default", updating to a closed head
216 no open descendant heads on branch "default", updating to a closed head
217 (committing will reopen the head, use `hg heads .` to see 1 other heads)
217 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
218 parent=6
218 parent=6
219
219
220 Test updating if all branch heads are closed
220 Test updating if all branch heads are closed
221
221
222 if on the closed branch head:
222 if on the closed branch head:
223 - update to "."
223 - update to "."
224 - "updated to a closed branch head ...." message is displayed
224 - "updated to a closed branch head ...." message is displayed
225 - "all heads of branch ...." message is displayed
225 - "all heads of branch ...." message is displayed
226
226
227 $ hg update -q -C 2
227 $ hg update -q -C 2
228 $ hg commit --close-branch -m 7
228 $ hg commit --close-branch -m 7
229 $ norevtest "all heads of branch default are closed" clean 6
229 $ norevtest "all heads of branch default are closed" clean 6
230 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 no open descendant heads on branch "default", updating to a closed head
231 no open descendant heads on branch "default", updating to a closed head
232 (committing will reopen branch "default")
232 (committing will reopen branch "default")
233 parent=6
233 parent=6
234
234
235 if not on the closed branch head:
235 if not on the closed branch head:
236 - update to the tipmost descendant (closed) head
236 - update to the tipmost descendant (closed) head
237 - "updated to a closed branch head ...." message is displayed
237 - "updated to a closed branch head ...." message is displayed
238 - "all heads of branch ...." message is displayed
238 - "all heads of branch ...." message is displayed
239
239
240 $ norevtest "all heads of branch default are closed" clean 1
240 $ norevtest "all heads of branch default are closed" clean 1
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 no open descendant heads on branch "default", updating to a closed head
242 no open descendant heads on branch "default", updating to a closed head
243 (committing will reopen branch "default")
243 (committing will reopen branch "default")
244 parent=7
244 parent=7
245
245
246 $ cd ..
246 $ cd ..
247
247
248 Test updating if "default" branch doesn't exist and no revision is
248 Test updating if "default" branch doesn't exist and no revision is
249 checked out (= "default" is used as current branch)
249 checked out (= "default" is used as current branch)
250
250
251 $ hg init no-default-branch
251 $ hg init no-default-branch
252 $ cd no-default-branch
252 $ cd no-default-branch
253
253
254 $ hg branch foobar
254 $ hg branch foobar
255 marked working directory as branch foobar
255 marked working directory as branch foobar
256 (branches are permanent and global, did you want a bookmark?)
256 (branches are permanent and global, did you want a bookmark?)
257 $ echo a > a
257 $ echo a > a
258 $ hg commit -m "#0" -A
258 $ hg commit -m "#0" -A
259 adding a
259 adding a
260 $ echo 1 >> a
260 $ echo 1 >> a
261 $ hg commit -m "#1"
261 $ hg commit -m "#1"
262 $ hg update -q 0
262 $ hg update -q 0
263 $ echo 3 >> a
263 $ echo 3 >> a
264 $ hg commit -m "#2"
264 $ hg commit -m "#2"
265 created new head
265 created new head
266 $ hg commit --close-branch -m "#3"
266 $ hg commit --close-branch -m "#3"
267
267
268 if there is at least one non-closed branch head:
268 if there is at least one non-closed branch head:
269 - update to the tipmost branch head
269 - update to the tipmost branch head
270
270
271 $ norevtest "non-closed 1 should be chosen" clean null
271 $ norevtest "non-closed 1 should be chosen" clean null
272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 parent=1
273 parent=1
274
274
275 if all branch heads are closed
275 if all branch heads are closed
276 - update to "tip"
276 - update to "tip"
277 - "updated to a closed branch head ...." message is displayed
277 - "updated to a closed branch head ...." message is displayed
278 - "all heads for branch "XXXX" are closed" message is displayed
278 - "all heads for branch "XXXX" are closed" message is displayed
279
279
280 $ hg update -q -C 1
280 $ hg update -q -C 1
281 $ hg commit --close-branch -m "#4"
281 $ hg commit --close-branch -m "#4"
282
282
283 $ norevtest "all branches are closed" clean null
283 $ norevtest "all branches are closed" clean null
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 no open descendant heads on branch "foobar", updating to a closed head
285 no open descendant heads on branch "foobar", updating to a closed head
286 (committing will reopen branch "foobar")
286 (committing will reopen branch "foobar")
287 parent=4
287 parent=4
288
288
289 $ cd ../b1
289 $ cd ../b1
290
290
291 Test obsolescence behavior
291 Test obsolescence behavior
292 ---------------------------------------------------------------------
292 ---------------------------------------------------------------------
293
293
294 successors should be taken in account when checking head destination
294 successors should be taken in account when checking head destination
295
295
296 $ cat << EOF >> $HGRCPATH
296 $ cat << EOF >> $HGRCPATH
297 > [ui]
297 > [ui]
298 > logtemplate={rev}:{node|short} {desc|firstline}
298 > logtemplate={rev}:{node|short} {desc|firstline}
299 > [experimental]
299 > [experimental]
300 > evolution=createmarkers
300 > evolution=createmarkers
301 > EOF
301 > EOF
302
302
303 Test no-argument update to a successor of an obsoleted changeset
303 Test no-argument update to a successor of an obsoleted changeset
304
304
305 $ hg log -G
305 $ hg log -G
306 o 5:ff252e8273df 5
306 o 5:ff252e8273df 5
307 |
307 |
308 o 4:d047485b3896 4
308 o 4:d047485b3896 4
309 |
309 |
310 | o 3:6efa171f091b 3
310 | o 3:6efa171f091b 3
311 | |
311 | |
312 | | o 2:bd10386d478c 2
312 | | o 2:bd10386d478c 2
313 | |/
313 | |/
314 | @ 1:0786582aa4b1 1
314 | @ 1:0786582aa4b1 1
315 |/
315 |/
316 o 0:60829823a42a 0
316 o 0:60829823a42a 0
317
317
318 $ hg book bm -r 3
318 $ hg book bm -r 3
319 $ hg status
319 $ hg status
320 M foo
320 M foo
321
321
322 We add simple obsolescence marker between 3 and 4 (indirect successors)
322 We add simple obsolescence marker between 3 and 4 (indirect successors)
323
323
324 $ hg id --debug -i -r 3
324 $ hg id --debug -i -r 3
325 6efa171f091b00a3c35edc15d48c52a498929953
325 6efa171f091b00a3c35edc15d48c52a498929953
326 $ hg id --debug -i -r 4
326 $ hg id --debug -i -r 4
327 d047485b3896813b2a624e86201983520f003206
327 d047485b3896813b2a624e86201983520f003206
328 $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
328 $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
329 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
329 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
330
330
331 Test that 5 is detected as a valid destination from 3 and also accepts moving
331 Test that 5 is detected as a valid destination from 3 and also accepts moving
332 the bookmark (issue4015)
332 the bookmark (issue4015)
333
333
334 $ hg up --quiet --hidden 3
334 $ hg up --quiet --hidden 3
335 $ hg up 5
335 $ hg up 5
336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 $ hg book bm
337 $ hg book bm
338 moving bookmark 'bm' forward from 6efa171f091b
338 moving bookmark 'bm' forward from 6efa171f091b
339 $ hg bookmarks
339 $ hg bookmarks
340 * bm 5:ff252e8273df
340 * bm 5:ff252e8273df
341
341
342 Test that 4 is detected as the no-argument destination from 3 and also moves
342 Test that 4 is detected as the no-argument destination from 3 and also moves
343 the bookmark with it
343 the bookmark with it
344 $ hg up --quiet 0 # we should be able to update to 3 directly
344 $ hg up --quiet 0 # we should be able to update to 3 directly
345 $ hg up --quiet --hidden 3 # but not implemented yet.
345 $ hg up --quiet --hidden 3 # but not implemented yet.
346 $ hg book -f bm
346 $ hg book -f bm
347 $ hg up
347 $ hg up
348 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 updating bookmark bm
349 updating bookmark bm
350 $ hg book
350 $ hg book
351 * bm 4:d047485b3896
351 * bm 4:d047485b3896
352
352
353 Test that 5 is detected as a valid destination from 1
353 Test that 5 is detected as a valid destination from 1
354 $ hg up --quiet 0 # we should be able to update to 3 directly
354 $ hg up --quiet 0 # we should be able to update to 3 directly
355 $ hg up --quiet --hidden 3 # but not implemented yet.
355 $ hg up --quiet --hidden 3 # but not implemented yet.
356 $ hg up 5
356 $ hg up 5
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358
358
359 Test that 5 is not detected as a valid destination from 2
359 Test that 5 is not detected as a valid destination from 2
360 $ hg up --quiet 0
360 $ hg up --quiet 0
361 $ hg up --quiet 2
361 $ hg up --quiet 2
362 $ hg up 5
362 $ hg up 5
363 abort: uncommitted changes
363 abort: uncommitted changes
364 (commit or update --clean to discard changes)
364 (commit or update --clean to discard changes)
365 [255]
365 [255]
366
366
367 Test that we don't crash when updating from a pruned changeset (i.e. has no
367 Test that we don't crash when updating from a pruned changeset (i.e. has no
368 successors). Behavior should probably be that we update to the first
368 successors). Behavior should probably be that we update to the first
369 non-obsolete parent but that will be decided later.
369 non-obsolete parent but that will be decided later.
370 $ hg id --debug -r 2
370 $ hg id --debug -r 2
371 bd10386d478cd5a9faf2e604114c8e6da62d3889
371 bd10386d478cd5a9faf2e604114c8e6da62d3889
372 $ hg up --quiet 0
372 $ hg up --quiet 0
373 $ hg up --quiet 2
373 $ hg up --quiet 2
374 $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
374 $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
375 $ hg up
375 $ hg up
376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377
377
378 Test experimental revset support
378 Test experimental revset support
379
379
380 $ hg log -r '_destupdate()'
380 $ hg log -r '_destupdate()'
381 2:bd10386d478c 2 (no-eol)
381 2:bd10386d478c 2 (no-eol)
382
382
383 Test that boolean flags allow --no-flag specification to override [defaults]
383 Test that boolean flags allow --no-flag specification to override [defaults]
384 $ cat >> $HGRCPATH <<EOF
384 $ cat >> $HGRCPATH <<EOF
385 > [defaults]
385 > [defaults]
386 > update = --check
386 > update = --check
387 > EOF
387 > EOF
388 $ hg co 2
388 $ hg co 2
389 abort: uncommitted changes
389 abort: uncommitted changes
390 [255]
390 [255]
391 $ hg co --no-check 2
391 $ hg co --no-check 2
392 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 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