##// END OF EJS Templates
update: fix bare --clean to work on new branch (issue5003) (BC)...
liscju -
r29284:1c716700 default
parent child Browse files
Show More
@@ -1,433 +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
99 if clean:
100 currentbranch = repo['.'].branch()
101
98 if currentbranch in repo.branchmap():
102 if currentbranch in repo.branchmap():
99 heads = repo.branchheads(currentbranch)
103 heads = repo.branchheads(currentbranch)
100 if heads:
104 if heads:
101 node = repo.revs('max(.::(%ln))', heads).first()
105 node = repo.revs('max(.::(%ln))', heads).first()
102 if bookmarks.isactivewdirparent(repo):
106 if bookmarks.isactivewdirparent(repo):
103 movemark = repo['.'].node()
107 movemark = repo['.'].node()
104 elif currentbranch == 'default' and not wc.p1():
108 elif currentbranch == 'default' and not wc.p1():
105 # "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
106 # update to the tipmost non-closed branch head
110 # update to the tipmost non-closed branch head
107 node = repo.revs('max(head() and not closed())').first()
111 node = repo.revs('max(head() and not closed())').first()
108 else:
112 else:
109 node = repo['.'].node()
113 node = repo['.'].node()
110 return node, movemark, None
114 return node, movemark, None
111
115
112 def _destupdatebranchfallback(repo, clean, check):
116 def _destupdatebranchfallback(repo, clean, check):
113 """decide on an update destination from closed heads in current branch"""
117 """decide on an update destination from closed heads in current branch"""
114 wc = repo[None]
118 wc = repo[None]
115 currentbranch = wc.branch()
119 currentbranch = wc.branch()
116 movemark = None
120 movemark = None
117 if currentbranch in repo.branchmap():
121 if currentbranch in repo.branchmap():
118 # here, all descendant branch heads are closed
122 # here, all descendant branch heads are closed
119 heads = repo.branchheads(currentbranch, closed=True)
123 heads = repo.branchheads(currentbranch, closed=True)
120 assert heads, "any branch has at least one head"
124 assert heads, "any branch has at least one head"
121 node = repo.revs('max(.::(%ln))', heads).first()
125 node = repo.revs('max(.::(%ln))', heads).first()
122 assert node is not None, ("any revision has at least "
126 assert node is not None, ("any revision has at least "
123 "one descendant branch head")
127 "one descendant branch head")
124 if bookmarks.isactivewdirparent(repo):
128 if bookmarks.isactivewdirparent(repo):
125 movemark = repo['.'].node()
129 movemark = repo['.'].node()
126 else:
130 else:
127 # here, no "default" branch, and all branches are closed
131 # here, no "default" branch, and all branches are closed
128 node = repo.lookup('tip')
132 node = repo.lookup('tip')
129 assert node is not None, "'tip' exists even in empty repository"
133 assert node is not None, "'tip' exists even in empty repository"
130 return node, movemark, None
134 return node, movemark, None
131
135
132 # order in which each step should be evalutated
136 # order in which each step should be evalutated
133 # steps are run until one finds a destination
137 # steps are run until one finds a destination
134 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
138 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
135 # mapping to ease extension overriding steps.
139 # mapping to ease extension overriding steps.
136 destupdatestepmap = {'evolution': _destupdateobs,
140 destupdatestepmap = {'evolution': _destupdateobs,
137 'bookmark': _destupdatebook,
141 'bookmark': _destupdatebook,
138 'branch': _destupdatebranch,
142 'branch': _destupdatebranch,
139 'branchfallback': _destupdatebranchfallback,
143 'branchfallback': _destupdatebranchfallback,
140 }
144 }
141
145
142 def destupdate(repo, clean=False, check=False):
146 def destupdate(repo, clean=False, check=False):
143 """destination for bare update operation
147 """destination for bare update operation
144
148
145 return (rev, movemark, activemark)
149 return (rev, movemark, activemark)
146
150
147 - rev: the revision to update to,
151 - rev: the revision to update to,
148 - movemark: node to move the active bookmark from
152 - movemark: node to move the active bookmark from
149 (cf bookmark.calculate update),
153 (cf bookmark.calculate update),
150 - activemark: a bookmark to activate at the end of the update.
154 - activemark: a bookmark to activate at the end of the update.
151 """
155 """
152 node = movemark = activemark = None
156 node = movemark = activemark = None
153
157
154 for step in destupdatesteps:
158 for step in destupdatesteps:
155 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
159 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
156 if node is not None:
160 if node is not None:
157 break
161 break
158 rev = repo[node].rev()
162 rev = repo[node].rev()
159
163
160 _destupdatevalidate(repo, rev, clean, check)
164 _destupdatevalidate(repo, rev, clean, check)
161
165
162 return rev, movemark, activemark
166 return rev, movemark, activemark
163
167
164 msgdestmerge = {
168 msgdestmerge = {
165 # too many matching divergent bookmark
169 # too many matching divergent bookmark
166 'toomanybookmarks':
170 'toomanybookmarks':
167 {'merge':
171 {'merge':
168 (_("multiple matching bookmarks to merge -"
172 (_("multiple matching bookmarks to merge -"
169 " please merge with an explicit rev or bookmark"),
173 " please merge with an explicit rev or bookmark"),
170 _("run 'hg heads' to see all heads")),
174 _("run 'hg heads' to see all heads")),
171 'rebase':
175 'rebase':
172 (_("multiple matching bookmarks to rebase -"
176 (_("multiple matching bookmarks to rebase -"
173 " please rebase to an explicit rev or bookmark"),
177 " please rebase to an explicit rev or bookmark"),
174 _("run 'hg heads' to see all heads")),
178 _("run 'hg heads' to see all heads")),
175 },
179 },
176 # no other matching divergent bookmark
180 # no other matching divergent bookmark
177 'nootherbookmarks':
181 'nootherbookmarks':
178 {'merge':
182 {'merge':
179 (_("no matching bookmark to merge - "
183 (_("no matching bookmark to merge - "
180 "please merge with an explicit rev or bookmark"),
184 "please merge with an explicit rev or bookmark"),
181 _("run 'hg heads' to see all heads")),
185 _("run 'hg heads' to see all heads")),
182 'rebase':
186 'rebase':
183 (_("no matching bookmark to rebase - "
187 (_("no matching bookmark to rebase - "
184 "please rebase to an explicit rev or bookmark"),
188 "please rebase to an explicit rev or bookmark"),
185 _("run 'hg heads' to see all heads")),
189 _("run 'hg heads' to see all heads")),
186 },
190 },
187 # branch have too many unbookmarked heads, no obvious destination
191 # branch have too many unbookmarked heads, no obvious destination
188 'toomanyheads':
192 'toomanyheads':
189 {'merge':
193 {'merge':
190 (_("branch '%s' has %d heads - please merge with an explicit rev"),
194 (_("branch '%s' has %d heads - please merge with an explicit rev"),
191 _("run 'hg heads .' to see heads")),
195 _("run 'hg heads .' to see heads")),
192 'rebase':
196 'rebase':
193 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
197 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
194 _("run 'hg heads .' to see heads")),
198 _("run 'hg heads .' to see heads")),
195 },
199 },
196 # branch have no other unbookmarked heads
200 # branch have no other unbookmarked heads
197 'bookmarkedheads':
201 'bookmarkedheads':
198 {'merge':
202 {'merge':
199 (_("heads are bookmarked - please merge with an explicit rev"),
203 (_("heads are bookmarked - please merge with an explicit rev"),
200 _("run 'hg heads' to see all heads")),
204 _("run 'hg heads' to see all heads")),
201 'rebase':
205 'rebase':
202 (_("heads are bookmarked - please rebase to an explicit rev"),
206 (_("heads are bookmarked - please rebase to an explicit rev"),
203 _("run 'hg heads' to see all heads")),
207 _("run 'hg heads' to see all heads")),
204 },
208 },
205 # branch have just a single heads, but there is other branches
209 # branch have just a single heads, but there is other branches
206 'nootherbranchheads':
210 'nootherbranchheads':
207 {'merge':
211 {'merge':
208 (_("branch '%s' has one head - please merge with an explicit rev"),
212 (_("branch '%s' has one head - please merge with an explicit rev"),
209 _("run 'hg heads' to see all heads")),
213 _("run 'hg heads' to see all heads")),
210 'rebase':
214 'rebase':
211 (_("branch '%s' has one head - please rebase to an explicit rev"),
215 (_("branch '%s' has one head - please rebase to an explicit rev"),
212 _("run 'hg heads' to see all heads")),
216 _("run 'hg heads' to see all heads")),
213 },
217 },
214 # repository have a single head
218 # repository have a single head
215 'nootherheads':
219 'nootherheads':
216 {'merge':
220 {'merge':
217 (_('nothing to merge'),
221 (_('nothing to merge'),
218 None),
222 None),
219 'rebase':
223 'rebase':
220 (_('nothing to rebase'),
224 (_('nothing to rebase'),
221 None),
225 None),
222 },
226 },
223 # repository have a single head and we are not on it
227 # repository have a single head and we are not on it
224 'nootherheadsbehind':
228 'nootherheadsbehind':
225 {'merge':
229 {'merge':
226 (_('nothing to merge'),
230 (_('nothing to merge'),
227 _("use 'hg update' instead")),
231 _("use 'hg update' instead")),
228 'rebase':
232 'rebase':
229 (_('nothing to rebase'),
233 (_('nothing to rebase'),
230 _("use 'hg update' instead")),
234 _("use 'hg update' instead")),
231 },
235 },
232 # We are not on a head
236 # We are not on a head
233 'notatheads':
237 'notatheads':
234 {'merge':
238 {'merge':
235 (_('working directory not at a head revision'),
239 (_('working directory not at a head revision'),
236 _("use 'hg update' or merge with an explicit revision")),
240 _("use 'hg update' or merge with an explicit revision")),
237 'rebase':
241 'rebase':
238 (_('working directory not at a head revision'),
242 (_('working directory not at a head revision'),
239 _("use 'hg update' or rebase to an explicit revision"))
243 _("use 'hg update' or rebase to an explicit revision"))
240 },
244 },
241 'emptysourceset':
245 'emptysourceset':
242 {'merge':
246 {'merge':
243 (_('source set is empty'),
247 (_('source set is empty'),
244 None),
248 None),
245 'rebase':
249 'rebase':
246 (_('source set is empty'),
250 (_('source set is empty'),
247 None),
251 None),
248 },
252 },
249 'multiplebranchessourceset':
253 'multiplebranchessourceset':
250 {'merge':
254 {'merge':
251 (_('source set is rooted in multiple branches'),
255 (_('source set is rooted in multiple branches'),
252 None),
256 None),
253 'rebase':
257 'rebase':
254 (_('rebaseset is rooted in multiple named branches'),
258 (_('rebaseset is rooted in multiple named branches'),
255 _('specify an explicit destination with --dest')),
259 _('specify an explicit destination with --dest')),
256 },
260 },
257 }
261 }
258
262
259 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
263 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
260 """find merge destination in the active bookmark case"""
264 """find merge destination in the active bookmark case"""
261 node = None
265 node = None
262 bmheads = repo.bookmarkheads(repo._activebookmark)
266 bmheads = repo.bookmarkheads(repo._activebookmark)
263 curhead = repo[repo._activebookmark].node()
267 curhead = repo[repo._activebookmark].node()
264 if len(bmheads) == 2:
268 if len(bmheads) == 2:
265 if curhead == bmheads[0]:
269 if curhead == bmheads[0]:
266 node = bmheads[1]
270 node = bmheads[1]
267 else:
271 else:
268 node = bmheads[0]
272 node = bmheads[0]
269 elif len(bmheads) > 2:
273 elif len(bmheads) > 2:
270 msg, hint = msgdestmerge['toomanybookmarks'][action]
274 msg, hint = msgdestmerge['toomanybookmarks'][action]
271 raise error.ManyMergeDestAbort(msg, hint=hint)
275 raise error.ManyMergeDestAbort(msg, hint=hint)
272 elif len(bmheads) <= 1:
276 elif len(bmheads) <= 1:
273 msg, hint = msgdestmerge['nootherbookmarks'][action]
277 msg, hint = msgdestmerge['nootherbookmarks'][action]
274 raise error.NoMergeDestAbort(msg, hint=hint)
278 raise error.NoMergeDestAbort(msg, hint=hint)
275 assert node is not None
279 assert node is not None
276 return node
280 return node
277
281
278 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
282 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
279 destspace=None):
283 destspace=None):
280 """find merge destination based on branch heads"""
284 """find merge destination based on branch heads"""
281 node = None
285 node = None
282
286
283 if sourceset is None:
287 if sourceset is None:
284 sourceset = [repo[repo.dirstate.p1()].rev()]
288 sourceset = [repo[repo.dirstate.p1()].rev()]
285 branch = repo.dirstate.branch()
289 branch = repo.dirstate.branch()
286 elif not sourceset:
290 elif not sourceset:
287 msg, hint = msgdestmerge['emptysourceset'][action]
291 msg, hint = msgdestmerge['emptysourceset'][action]
288 raise error.NoMergeDestAbort(msg, hint=hint)
292 raise error.NoMergeDestAbort(msg, hint=hint)
289 else:
293 else:
290 branch = None
294 branch = None
291 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
295 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
292 if branch is not None and ctx.branch() != branch:
296 if branch is not None and ctx.branch() != branch:
293 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
297 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
294 raise error.ManyMergeDestAbort(msg, hint=hint)
298 raise error.ManyMergeDestAbort(msg, hint=hint)
295 branch = ctx.branch()
299 branch = ctx.branch()
296
300
297 bheads = repo.branchheads(branch)
301 bheads = repo.branchheads(branch)
298 onhead = repo.revs('%ld and %ln', sourceset, bheads)
302 onhead = repo.revs('%ld and %ln', sourceset, bheads)
299 if onheadcheck and not onhead:
303 if onheadcheck and not onhead:
300 # Case A: working copy if not on a head. (merge only)
304 # Case A: working copy if not on a head. (merge only)
301 #
305 #
302 # 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'
303 if len(repo.heads()) <= 1:
307 if len(repo.heads()) <= 1:
304 msg, hint = msgdestmerge['nootherheadsbehind'][action]
308 msg, hint = msgdestmerge['nootherheadsbehind'][action]
305 else:
309 else:
306 msg, hint = msgdestmerge['notatheads'][action]
310 msg, hint = msgdestmerge['notatheads'][action]
307 raise error.Abort(msg, hint=hint)
311 raise error.Abort(msg, hint=hint)
308 # remove heads descendants of source from the set
312 # remove heads descendants of source from the set
309 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
313 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
310 # filters out bookmarked heads
314 # filters out bookmarked heads
311 nbhs = list(repo.revs('%ld - bookmark()', bheads))
315 nbhs = list(repo.revs('%ld - bookmark()', bheads))
312
316
313 if destspace is not None:
317 if destspace is not None:
314 # restrict search space
318 # restrict search space
315 # used in the 'hg pull --rebase' case, see issue 5214.
319 # used in the 'hg pull --rebase' case, see issue 5214.
316 nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
320 nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
317
321
318 if len(nbhs) > 1:
322 if len(nbhs) > 1:
319 # Case B: There is more than 1 other anonymous heads
323 # Case B: There is more than 1 other anonymous heads
320 #
324 #
321 # 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
322 # ambiguous. We abort asking the user to pick as explicit destination
326 # ambiguous. We abort asking the user to pick as explicit destination
323 # instead.
327 # instead.
324 msg, hint = msgdestmerge['toomanyheads'][action]
328 msg, hint = msgdestmerge['toomanyheads'][action]
325 msg %= (branch, len(bheads) + 1)
329 msg %= (branch, len(bheads) + 1)
326 raise error.ManyMergeDestAbort(msg, hint=hint)
330 raise error.ManyMergeDestAbort(msg, hint=hint)
327 elif not nbhs:
331 elif not nbhs:
328 # Case B: There is no other anonymous heads
332 # Case B: There is no other anonymous heads
329 #
333 #
330 # This means that there is no natural candidate to merge with.
334 # This means that there is no natural candidate to merge with.
331 # We abort, with various messages for various cases.
335 # We abort, with various messages for various cases.
332 if bheads:
336 if bheads:
333 msg, hint = msgdestmerge['bookmarkedheads'][action]
337 msg, hint = msgdestmerge['bookmarkedheads'][action]
334 elif len(repo.heads()) > 1:
338 elif len(repo.heads()) > 1:
335 msg, hint = msgdestmerge['nootherbranchheads'][action]
339 msg, hint = msgdestmerge['nootherbranchheads'][action]
336 msg %= branch
340 msg %= branch
337 elif not onhead:
341 elif not onhead:
338 # if 'onheadcheck == False' (rebase case),
342 # if 'onheadcheck == False' (rebase case),
339 # this was not caught in Case A.
343 # this was not caught in Case A.
340 msg, hint = msgdestmerge['nootherheadsbehind'][action]
344 msg, hint = msgdestmerge['nootherheadsbehind'][action]
341 else:
345 else:
342 msg, hint = msgdestmerge['nootherheads'][action]
346 msg, hint = msgdestmerge['nootherheads'][action]
343 raise error.NoMergeDestAbort(msg, hint=hint)
347 raise error.NoMergeDestAbort(msg, hint=hint)
344 else:
348 else:
345 node = nbhs[0]
349 node = nbhs[0]
346 assert node is not None
350 assert node is not None
347 return node
351 return node
348
352
349 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
353 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
350 destspace=None):
354 destspace=None):
351 """return the default destination for a merge
355 """return the default destination for a merge
352
356
353 (or raise exception about why it can't pick one)
357 (or raise exception about why it can't pick one)
354
358
355 :action: the action being performed, controls emitted error message
359 :action: the action being performed, controls emitted error message
356 """
360 """
357 # 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
358 # issue5214 for details
362 # issue5214 for details
359 if repo._activebookmark:
363 if repo._activebookmark:
360 node = _destmergebook(repo, action=action, sourceset=sourceset,
364 node = _destmergebook(repo, action=action, sourceset=sourceset,
361 destspace=destspace)
365 destspace=destspace)
362 else:
366 else:
363 node = _destmergebranch(repo, action=action, sourceset=sourceset,
367 node = _destmergebranch(repo, action=action, sourceset=sourceset,
364 onheadcheck=onheadcheck, destspace=destspace)
368 onheadcheck=onheadcheck, destspace=destspace)
365 return repo[node].rev()
369 return repo[node].rev()
366
370
367 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
371 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
368
372
369 def desthistedit(ui, repo):
373 def desthistedit(ui, repo):
370 """Default base revision to edit for `hg histedit`."""
374 """Default base revision to edit for `hg histedit`."""
371 # Avoid cycle: scmutil -> revset -> destutil
375 # Avoid cycle: scmutil -> revset -> destutil
372 from . import scmutil
376 from . import scmutil
373
377
374 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
378 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
375 if default:
379 if default:
376 revs = scmutil.revrange(repo, [default])
380 revs = scmutil.revrange(repo, [default])
377 if revs:
381 if revs:
378 # 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
379 # take the first revision. So do this manually.
383 # take the first revision. So do this manually.
380 revs.sort()
384 revs.sort()
381 return revs.first()
385 return revs.first()
382
386
383 return None
387 return None
384
388
385 def _statusotherbook(ui, repo):
389 def _statusotherbook(ui, repo):
386 bmheads = repo.bookmarkheads(repo._activebookmark)
390 bmheads = repo.bookmarkheads(repo._activebookmark)
387 curhead = repo[repo._activebookmark].node()
391 curhead = repo[repo._activebookmark].node()
388 if repo.revs('%n and parents()', curhead):
392 if repo.revs('%n and parents()', curhead):
389 # we are on the active bookmark
393 # we are on the active bookmark
390 bmheads = [b for b in bmheads if curhead != b]
394 bmheads = [b for b in bmheads if curhead != b]
391 if bmheads:
395 if bmheads:
392 msg = _('%i other divergent bookmarks for "%s"\n')
396 msg = _('%i other divergent bookmarks for "%s"\n')
393 ui.status(msg % (len(bmheads), repo._activebookmark))
397 ui.status(msg % (len(bmheads), repo._activebookmark))
394
398
395 def _statusotherbranchheads(ui, repo):
399 def _statusotherbranchheads(ui, repo):
396 currentbranch = repo.dirstate.branch()
400 currentbranch = repo.dirstate.branch()
397 allheads = repo.branchheads(currentbranch, closed=True)
401 allheads = repo.branchheads(currentbranch, closed=True)
398 heads = repo.branchheads(currentbranch)
402 heads = repo.branchheads(currentbranch)
399 if repo.revs('%ln and parents()', allheads):
403 if repo.revs('%ln and parents()', allheads):
400 # we are on a head, even though it might be closed
404 # we are on a head, even though it might be closed
401 #
405 #
402 # on closed otherheads
406 # on closed otherheads
403 # ========= ==========
407 # ========= ==========
404 # o 0 all heads for current branch are closed
408 # o 0 all heads for current branch are closed
405 # N only descendant branch heads are closed
409 # N only descendant branch heads are closed
406 # x 0 there is only one non-closed branch head
410 # x 0 there is only one non-closed branch head
407 # N there are some non-closed branch heads
411 # N there are some non-closed branch heads
408 # ========= ==========
412 # ========= ==========
409 otherheads = repo.revs('%ln - parents()', heads)
413 otherheads = repo.revs('%ln - parents()', heads)
410 if repo['.'].closesbranch():
414 if repo['.'].closesbranch():
411 ui.warn(_('no open descendant heads on branch "%s", '
415 ui.warn(_('no open descendant heads on branch "%s", '
412 'updating to a closed head\n') %
416 'updating to a closed head\n') %
413 (currentbranch))
417 (currentbranch))
414 if otherheads:
418 if otherheads:
415 ui.warn(_('(committing will reopen the head, '
419 ui.warn(_('(committing will reopen the head, '
416 'use `hg heads .` to see %i other heads)\n') %
420 'use `hg heads .` to see %i other heads)\n') %
417 (len(otherheads)))
421 (len(otherheads)))
418 else:
422 else:
419 ui.warn(_('(committing will reopen branch "%s")\n') %
423 ui.warn(_('(committing will reopen branch "%s")\n') %
420 (currentbranch))
424 (currentbranch))
421 elif otherheads:
425 elif otherheads:
422 ui.status(_('%i other heads for branch "%s"\n') %
426 ui.status(_('%i other heads for branch "%s"\n') %
423 (len(otherheads), currentbranch))
427 (len(otherheads), currentbranch))
424
428
425 def statusotherdests(ui, repo):
429 def statusotherdests(ui, repo):
426 """Print message about other head"""
430 """Print message about other head"""
427 # XXX we should probably include a hint:
431 # XXX we should probably include a hint:
428 # - about what to do
432 # - about what to do
429 # - how to see such heads
433 # - how to see such heads
430 if repo._activebookmark:
434 if repo._activebookmark:
431 _statusotherbook(ui, repo)
435 _statusotherbook(ui, repo)
432 else:
436 else:
433 _statusotherbranchheads(ui, repo)
437 _statusotherbranchheads(ui, repo)
@@ -1,465 +1,534 b''
1 $ branchcache=.hg/cache/branch2
1 $ branchcache=.hg/cache/branch2
2
2
3 $ listbranchcaches() {
3 $ listbranchcaches() {
4 > for f in .hg/cache/branch2*;
4 > for f in .hg/cache/branch2*;
5 > do echo === $f ===;
5 > do echo === $f ===;
6 > cat $f;
6 > cat $f;
7 > done;
7 > done;
8 > }
8 > }
9 $ purgebranchcaches() {
9 $ purgebranchcaches() {
10 > rm .hg/cache/branch2*
10 > rm .hg/cache/branch2*
11 > }
11 > }
12
12
13 $ hg init t
13 $ hg init t
14 $ cd t
14 $ cd t
15
15
16 $ hg branches
16 $ hg branches
17 $ echo foo > a
17 $ echo foo > a
18 $ hg add a
18 $ hg add a
19 $ hg ci -m "initial"
19 $ hg ci -m "initial"
20 $ hg branch foo
20 $ hg branch foo
21 marked working directory as branch foo
21 marked working directory as branch foo
22 (branches are permanent and global, did you want a bookmark?)
22 (branches are permanent and global, did you want a bookmark?)
23 $ hg branch
23 $ hg branch
24 foo
24 foo
25 $ hg ci -m "add branch name"
25 $ hg ci -m "add branch name"
26 $ hg branch bar
26 $ hg branch bar
27 marked working directory as branch bar
27 marked working directory as branch bar
28 $ hg ci -m "change branch name"
28 $ hg ci -m "change branch name"
29
29
30 Branch shadowing:
30 Branch shadowing:
31
31
32 $ hg branch default
32 $ hg branch default
33 abort: a branch of the same name already exists
33 abort: a branch of the same name already exists
34 (use 'hg update' to switch to it)
34 (use 'hg update' to switch to it)
35 [255]
35 [255]
36
36
37 $ hg branch -f default
37 $ hg branch -f default
38 marked working directory as branch default
38 marked working directory as branch default
39
39
40 $ hg ci -m "clear branch name"
40 $ hg ci -m "clear branch name"
41 created new head
41 created new head
42
42
43 There should be only one default branch head
43 There should be only one default branch head
44
44
45 $ hg heads .
45 $ hg heads .
46 changeset: 3:1c28f494dae6
46 changeset: 3:1c28f494dae6
47 tag: tip
47 tag: tip
48 user: test
48 user: test
49 date: Thu Jan 01 00:00:00 1970 +0000
49 date: Thu Jan 01 00:00:00 1970 +0000
50 summary: clear branch name
50 summary: clear branch name
51
51
52 Merging and branches
52 Merging and branches
53
53
54 $ hg co foo
54 $ hg co foo
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 $ hg branch
56 $ hg branch
57 foo
57 foo
58
58
59 set existing branch name fails unless force - setting existing parent branch works without force:
59 set existing branch name fails unless force - setting existing parent branch works without force:
60
60
61 $ hg branch bar
61 $ hg branch bar
62 abort: a branch of the same name already exists
62 abort: a branch of the same name already exists
63 (use 'hg update' to switch to it)
63 (use 'hg update' to switch to it)
64 [255]
64 [255]
65
65
66 $ hg branch -f bar
66 $ hg branch -f bar
67 marked working directory as branch bar
67 marked working directory as branch bar
68
68
69 $ hg branch foo
69 $ hg branch foo
70 marked working directory as branch foo
70 marked working directory as branch foo
71
71
72 $ echo bleah > a
72 $ echo bleah > a
73 $ hg ci -m "modify a branch"
73 $ hg ci -m "modify a branch"
74
74
75 $ hg merge default
75 $ hg merge default
76 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 (branch merge, don't forget to commit)
77 (branch merge, don't forget to commit)
78
78
79 $ hg branch
79 $ hg branch
80 foo
80 foo
81
81
82 set existing branch name where branch head is ancestor:
82 set existing branch name where branch head is ancestor:
83
83
84 $ hg branch bar
84 $ hg branch bar
85 abort: a branch of the same name already exists
85 abort: a branch of the same name already exists
86 (use 'hg update' to switch to it)
86 (use 'hg update' to switch to it)
87 [255]
87 [255]
88
88
89 set (other) parent branch as branch name
89 set (other) parent branch as branch name
90
90
91 $ hg branch default
91 $ hg branch default
92 marked working directory as branch default
92 marked working directory as branch default
93
93
94 set (first) parent branch as branch name
94 set (first) parent branch as branch name
95
95
96 $ hg branch foo
96 $ hg branch foo
97 marked working directory as branch foo
97 marked working directory as branch foo
98
98
99 $ hg ci -m "merge"
99 $ hg ci -m "merge"
100
100
101 $ hg log -G -T '{rev}:{node|short} {branch} {desc}\n'
101 $ hg log -G -T '{rev}:{node|short} {branch} {desc}\n'
102 @ 5:530046499edf foo merge
102 @ 5:530046499edf foo merge
103 |\
103 |\
104 | o 4:adf1a74a7f7b foo modify a branch
104 | o 4:adf1a74a7f7b foo modify a branch
105 | |
105 | |
106 o | 3:1c28f494dae6 default clear branch name
106 o | 3:1c28f494dae6 default clear branch name
107 | |
107 | |
108 o | 2:c21617b13b22 bar change branch name
108 o | 2:c21617b13b22 bar change branch name
109 |/
109 |/
110 o 1:6c0e42da283a foo add branch name
110 o 1:6c0e42da283a foo add branch name
111 |
111 |
112 o 0:db01e8ea3388 default initial
112 o 0:db01e8ea3388 default initial
113
113
114 $ hg branches
114 $ hg branches
115 foo 5:530046499edf
115 foo 5:530046499edf
116 default 3:1c28f494dae6 (inactive)
116 default 3:1c28f494dae6 (inactive)
117 bar 2:c21617b13b22 (inactive)
117 bar 2:c21617b13b22 (inactive)
118
118
119 $ hg branches -q
119 $ hg branches -q
120 foo
120 foo
121 default
121 default
122 bar
122 bar
123
123
124 Test for invalid branch cache:
124 Test for invalid branch cache:
125
125
126 $ hg rollback
126 $ hg rollback
127 repository tip rolled back to revision 4 (undo commit)
127 repository tip rolled back to revision 4 (undo commit)
128 working directory now based on revisions 4 and 3
128 working directory now based on revisions 4 and 3
129
129
130 $ cp ${branchcache}-served .hg/bc-invalid
130 $ cp ${branchcache}-served .hg/bc-invalid
131
131
132 $ hg log -r foo
132 $ hg log -r foo
133 changeset: 4:adf1a74a7f7b
133 changeset: 4:adf1a74a7f7b
134 branch: foo
134 branch: foo
135 tag: tip
135 tag: tip
136 parent: 1:6c0e42da283a
136 parent: 1:6c0e42da283a
137 user: test
137 user: test
138 date: Thu Jan 01 00:00:00 1970 +0000
138 date: Thu Jan 01 00:00:00 1970 +0000
139 summary: modify a branch
139 summary: modify a branch
140
140
141 $ cp .hg/bc-invalid $branchcache
141 $ cp .hg/bc-invalid $branchcache
142
142
143 $ hg --debug log -r foo
143 $ hg --debug log -r foo
144 changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6
144 changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6
145 branch: foo
145 branch: foo
146 tag: tip
146 tag: tip
147 phase: draft
147 phase: draft
148 parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8
148 parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8
149 parent: -1:0000000000000000000000000000000000000000
149 parent: -1:0000000000000000000000000000000000000000
150 manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe
150 manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe
151 user: test
151 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
152 date: Thu Jan 01 00:00:00 1970 +0000
153 files: a
153 files: a
154 extra: branch=foo
154 extra: branch=foo
155 description:
155 description:
156 modify a branch
156 modify a branch
157
157
158
158
159 $ purgebranchcaches
159 $ purgebranchcaches
160 $ echo corrupted > $branchcache
160 $ echo corrupted > $branchcache
161
161
162 $ hg log -qr foo
162 $ hg log -qr foo
163 4:adf1a74a7f7b
163 4:adf1a74a7f7b
164
164
165 $ listbranchcaches
165 $ listbranchcaches
166 === .hg/cache/branch2 ===
166 === .hg/cache/branch2 ===
167 corrupted
167 corrupted
168 === .hg/cache/branch2-served ===
168 === .hg/cache/branch2-served ===
169 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
169 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
170 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
170 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
171 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
171 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
172 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
172 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
173
173
174 Push should update the branch cache:
174 Push should update the branch cache:
175
175
176 $ hg init ../target
176 $ hg init ../target
177
177
178 Pushing just rev 0:
178 Pushing just rev 0:
179
179
180 $ hg push -qr 0 ../target
180 $ hg push -qr 0 ../target
181
181
182 $ (cd ../target/; listbranchcaches)
182 $ (cd ../target/; listbranchcaches)
183 === .hg/cache/branch2-base ===
183 === .hg/cache/branch2-base ===
184 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
184 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
185 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 o default
185 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 o default
186
186
187 Pushing everything:
187 Pushing everything:
188
188
189 $ hg push -qf ../target
189 $ hg push -qf ../target
190
190
191 $ (cd ../target/; listbranchcaches)
191 $ (cd ../target/; listbranchcaches)
192 === .hg/cache/branch2-base ===
192 === .hg/cache/branch2-base ===
193 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
193 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
194 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
194 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
195 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
195 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
196 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
196 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
197
197
198 Update with no arguments: tipmost revision of the current branch:
198 Update with no arguments: tipmost revision of the current branch:
199
199
200 $ hg up -q -C 0
200 $ hg up -q -C 0
201 $ hg up -q
201 $ hg up -q
202 $ hg id
202 $ hg id
203 1c28f494dae6
203 1c28f494dae6
204
204
205 $ hg up -q 1
205 $ hg up -q 1
206 $ hg up -q
206 $ hg up -q
207 $ hg id
207 $ hg id
208 adf1a74a7f7b (foo) tip
208 adf1a74a7f7b (foo) tip
209
209
210 $ hg branch foobar
210 $ hg branch foobar
211 marked working directory as branch foobar
211 marked working directory as branch foobar
212
212
213 $ hg up
213 $ hg up
214 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
215
215
216 Fast-forward merge:
216 Fast-forward merge:
217
217
218 $ hg branch ff
218 $ hg branch ff
219 marked working directory as branch ff
219 marked working directory as branch ff
220
220
221 $ echo ff > ff
221 $ echo ff > ff
222 $ hg ci -Am'fast forward'
222 $ hg ci -Am'fast forward'
223 adding ff
223 adding ff
224
224
225 $ hg up foo
225 $ hg up foo
226 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
226 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
227
227
228 $ hg merge ff
228 $ hg merge ff
229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 (branch merge, don't forget to commit)
230 (branch merge, don't forget to commit)
231
231
232 $ hg branch
232 $ hg branch
233 foo
233 foo
234 $ hg commit -m'Merge ff into foo'
234 $ hg commit -m'Merge ff into foo'
235 $ hg parents
235 $ hg parents
236 changeset: 6:185ffbfefa30
236 changeset: 6:185ffbfefa30
237 branch: foo
237 branch: foo
238 tag: tip
238 tag: tip
239 parent: 4:adf1a74a7f7b
239 parent: 4:adf1a74a7f7b
240 parent: 5:1a3c27dc5e11
240 parent: 5:1a3c27dc5e11
241 user: test
241 user: test
242 date: Thu Jan 01 00:00:00 1970 +0000
242 date: Thu Jan 01 00:00:00 1970 +0000
243 summary: Merge ff into foo
243 summary: Merge ff into foo
244
244
245 $ hg manifest
245 $ hg manifest
246 a
246 a
247 ff
247 ff
248
248
249
249
250 Test merging, add 3 default heads and one test head:
250 Test merging, add 3 default heads and one test head:
251
251
252 $ cd ..
252 $ cd ..
253 $ hg init merges
253 $ hg init merges
254 $ cd merges
254 $ cd merges
255 $ echo a > a
255 $ echo a > a
256 $ hg ci -Ama
256 $ hg ci -Ama
257 adding a
257 adding a
258
258
259 $ echo b > b
259 $ echo b > b
260 $ hg ci -Amb
260 $ hg ci -Amb
261 adding b
261 adding b
262
262
263 $ hg up 0
263 $ hg up 0
264 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
264 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
265 $ echo c > c
265 $ echo c > c
266 $ hg ci -Amc
266 $ hg ci -Amc
267 adding c
267 adding c
268 created new head
268 created new head
269
269
270 $ hg up 0
270 $ hg up 0
271 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
271 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
272 $ echo d > d
272 $ echo d > d
273 $ hg ci -Amd
273 $ hg ci -Amd
274 adding d
274 adding d
275 created new head
275 created new head
276
276
277 $ hg up 0
277 $ hg up 0
278 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
278 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
279 $ hg branch test
279 $ hg branch test
280 marked working directory as branch test
280 marked working directory as branch test
281 (branches are permanent and global, did you want a bookmark?)
281 (branches are permanent and global, did you want a bookmark?)
282 $ echo e >> e
282 $ echo e >> e
283 $ hg ci -Ame
283 $ hg ci -Ame
284 adding e
284 adding e
285
285
286 $ hg log
286 $ hg log
287 changeset: 4:3a1e01ed1df4
287 changeset: 4:3a1e01ed1df4
288 branch: test
288 branch: test
289 tag: tip
289 tag: tip
290 parent: 0:cb9a9f314b8b
290 parent: 0:cb9a9f314b8b
291 user: test
291 user: test
292 date: Thu Jan 01 00:00:00 1970 +0000
292 date: Thu Jan 01 00:00:00 1970 +0000
293 summary: e
293 summary: e
294
294
295 changeset: 3:980f7dc84c29
295 changeset: 3:980f7dc84c29
296 parent: 0:cb9a9f314b8b
296 parent: 0:cb9a9f314b8b
297 user: test
297 user: test
298 date: Thu Jan 01 00:00:00 1970 +0000
298 date: Thu Jan 01 00:00:00 1970 +0000
299 summary: d
299 summary: d
300
300
301 changeset: 2:d36c0562f908
301 changeset: 2:d36c0562f908
302 parent: 0:cb9a9f314b8b
302 parent: 0:cb9a9f314b8b
303 user: test
303 user: test
304 date: Thu Jan 01 00:00:00 1970 +0000
304 date: Thu Jan 01 00:00:00 1970 +0000
305 summary: c
305 summary: c
306
306
307 changeset: 1:d2ae7f538514
307 changeset: 1:d2ae7f538514
308 user: test
308 user: test
309 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
310 summary: b
310 summary: b
311
311
312 changeset: 0:cb9a9f314b8b
312 changeset: 0:cb9a9f314b8b
313 user: test
313 user: test
314 date: Thu Jan 01 00:00:00 1970 +0000
314 date: Thu Jan 01 00:00:00 1970 +0000
315 summary: a
315 summary: a
316
316
317 Implicit merge with test branch as parent:
317 Implicit merge with test branch as parent:
318
318
319 $ hg merge
319 $ hg merge
320 abort: branch 'test' has one head - please merge with an explicit rev
320 abort: branch 'test' has one head - please merge with an explicit rev
321 (run 'hg heads' to see all heads)
321 (run 'hg heads' to see all heads)
322 [255]
322 [255]
323 $ hg up -C default
323 $ hg up -C default
324 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
324 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
325
325
326 Implicit merge with default branch as parent:
326 Implicit merge with default branch as parent:
327
327
328 $ hg merge
328 $ hg merge
329 abort: branch 'default' has 3 heads - please merge with an explicit rev
329 abort: branch 'default' has 3 heads - please merge with an explicit rev
330 (run 'hg heads .' to see heads)
330 (run 'hg heads .' to see heads)
331 [255]
331 [255]
332
332
333 3 branch heads, explicit merge required:
333 3 branch heads, explicit merge required:
334
334
335 $ hg merge 2
335 $ hg merge 2
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 (branch merge, don't forget to commit)
337 (branch merge, don't forget to commit)
338 $ hg ci -m merge
338 $ hg ci -m merge
339
339
340 2 branch heads, implicit merge works:
340 2 branch heads, implicit merge works:
341
341
342 $ hg merge
342 $ hg merge
343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
344 (branch merge, don't forget to commit)
344 (branch merge, don't forget to commit)
345
345
346 $ cd ..
346 $ cd ..
347
347
348 We expect that bare update on new branch, updates to parent
348 We expect that bare update on new branch, updates to parent
349
349
350 $ hg init bareupdateonnewbranch
350 $ hg init bareupdateonnewbranch
351 $ cd bareupdateonnewbranch
351 $ cd bareupdateonnewbranch
352 $ hg update
352 $ hg update
353 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
353 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
354 $ touch a
354 $ touch a
355 $ hg commit -A -m "a"
355 $ hg commit -A -m "a"
356 adding a
356 adding a
357 $ touch b
357 $ touch b
358 $ hg commit -A -m "b"
358 $ hg commit -A -m "b"
359 adding b
359 adding b
360 $ touch c
360 $ touch c
361 $ hg commit -A -m "c"
361 $ hg commit -A -m "c"
362 adding c
362 adding c
363 $ hg update -r 1
363 $ hg update -r 1
364 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
364 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
365 $ hg log -G
365 $ hg log -G
366 o changeset: 2:991a3460af53
366 o changeset: 2:991a3460af53
367 | tag: tip
367 | tag: tip
368 | user: test
368 | user: test
369 | date: Thu Jan 01 00:00:00 1970 +0000
369 | date: Thu Jan 01 00:00:00 1970 +0000
370 | summary: c
370 | summary: c
371 |
371 |
372 @ changeset: 1:0e067c57feba
372 @ changeset: 1:0e067c57feba
373 | user: test
373 | user: test
374 | date: Thu Jan 01 00:00:00 1970 +0000
374 | date: Thu Jan 01 00:00:00 1970 +0000
375 | summary: b
375 | summary: b
376 |
376 |
377 o changeset: 0:3903775176ed
377 o changeset: 0:3903775176ed
378 user: test
378 user: test
379 date: Thu Jan 01 00:00:00 1970 +0000
379 date: Thu Jan 01 00:00:00 1970 +0000
380 summary: a
380 summary: a
381
381
382 $ hg branch dev
382 $ hg branch dev
383 marked working directory as branch dev
383 marked working directory as branch dev
384 (branches are permanent and global, did you want a bookmark?)
384 (branches are permanent and global, did you want a bookmark?)
385 $ hg update
385 $ hg update
386 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 $ hg summary
387 $ hg summary
388 parent: 1:0e067c57feba
388 parent: 1:0e067c57feba
389 b
389 b
390 branch: dev
390 branch: dev
391 commit: (new branch)
391 commit: (new branch)
392 update: (current)
392 update: (current)
393 phases: 3 draft
393 phases: 3 draft
394
394
395 $ cd ..
395 $ cd ..
396
396
397 We need special handling for repositories with no "default" branch because
397 We need special handling for repositories with no "default" branch because
398 "null" revision belongs to non-existent "default" branch.
398 "null" revision belongs to non-existent "default" branch.
399
399
400 $ hg init nodefault
400 $ hg init nodefault
401 $ cd nodefault
401 $ cd nodefault
402 $ hg branch -q foo
402 $ hg branch -q foo
403 $ touch 0
403 $ touch 0
404 $ hg ci -Aqm0
404 $ hg ci -Aqm0
405 $ touch 1
405 $ touch 1
406 $ hg ci -Aqm1
406 $ hg ci -Aqm1
407 $ hg update -qr0
407 $ hg update -qr0
408 $ hg branch -q bar
408 $ hg branch -q bar
409 $ touch 2
409 $ touch 2
410 $ hg ci -Aqm2
410 $ hg ci -Aqm2
411 $ hg update -qr0
411 $ hg update -qr0
412 $ hg branch -q baz
412 $ hg branch -q baz
413 $ touch 3
413 $ touch 3
414 $ hg ci -Aqm3
414 $ hg ci -Aqm3
415 $ hg ci --close-branch -m 'close baz'
415 $ hg ci --close-branch -m 'close baz'
416 $ hg update -q null
416 $ hg update -q null
417 $ hg log -GT'{rev} {branch}\n'
417 $ hg log -GT'{rev} {branch}\n'
418 _ 4 baz
418 _ 4 baz
419 |
419 |
420 o 3 baz
420 o 3 baz
421 |
421 |
422 | o 2 bar
422 | o 2 bar
423 |/
423 |/
424 | o 1 foo
424 | o 1 foo
425 |/
425 |/
426 o 0 foo
426 o 0 foo
427
427
428
428
429 a) updating from "null" should bring us to the tip-most branch head as
429 a) updating from "null" should bring us to the tip-most branch head as
430 there is no "default" branch:
430 there is no "default" branch:
431
431
432 $ hg update -q null
432 $ hg update -q null
433 $ hg id -bn
433 $ hg id -bn
434 -1 default
434 -1 default
435 $ hg update
435 $ hg update
436 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 $ hg id -bn
437 $ hg id -bn
438 2 bar
438 2 bar
439
439
440 b) but if we are at uncommitted "default" branch, we should stick to the
440 b) but if we are at uncommitted "default" branch, we should stick to the
441 current revision:
441 current revision:
442
442
443 $ hg update -q 0
443 $ hg update -q 0
444 $ hg branch default
444 $ hg branch default
445 marked working directory as branch default
445 marked working directory as branch default
446 $ hg id -bn
446 $ hg id -bn
447 0 default
447 0 default
448 $ hg update
448 $ hg update
449 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 $ hg id -bn
450 $ hg id -bn
451 0 default
451 0 default
452
452
453 c) also, if we have uncommitted branch at "null", we should stick to it:
453 c) also, if we have uncommitted branch at "null", we should stick to it:
454
454
455 $ hg update -q null
455 $ hg update -q null
456 $ hg branch new
456 $ hg branch new
457 marked working directory as branch new
457 marked working directory as branch new
458 $ hg id -bn
458 $ hg id -bn
459 -1 new
459 -1 new
460 $ hg update
460 $ hg update
461 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ hg id -bn
462 $ hg id -bn
463 -1 new
463 -1 new
464
464
465 $ cd ..
465 $ cd ..
466
467 We expect that update --clean discard changes in working directory,
468 and updates to the head of parent branch.
469
470 $ hg init updatebareclean
471 $ cd updatebareclean
472 $ hg update --clean
473 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 $ touch a
475 $ hg commit -A -m "a"
476 adding a
477 $ touch b
478 $ hg commit -A -m "b"
479 adding b
480 $ touch c
481 $ hg commit -A -m "c"
482 adding c
483 $ hg log
484 changeset: 2:991a3460af53
485 tag: tip
486 user: test
487 date: Thu Jan 01 00:00:00 1970 +0000
488 summary: c
489
490 changeset: 1:0e067c57feba
491 user: test
492 date: Thu Jan 01 00:00:00 1970 +0000
493 summary: b
494
495 changeset: 0:3903775176ed
496 user: test
497 date: Thu Jan 01 00:00:00 1970 +0000
498 summary: a
499
500 $ hg update -r 1
501 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
502 $ hg branch new-branch
503 marked working directory as branch new-branch
504 (branches are permanent and global, did you want a bookmark?)
505 $ echo "aa" >> a
506 $ hg update --clean
507 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 $ hg status
509 $ hg branch
510 default
511 $ hg parent
512 changeset: 2:991a3460af53
513 tag: tip
514 user: test
515 date: Thu Jan 01 00:00:00 1970 +0000
516 summary: c
517
518 We expect that update --clean on non existing parent discards a new branch
519 and updates to the tipmost non-closed branch head
520
521 $ hg update null
522 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
523 $ hg branch newbranch
524 marked working directory as branch newbranch
525 (branches are permanent and global, did you want a bookmark?)
526 $ hg update -C
527 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 $ hg summary
529 parent: 2:991a3460af53 tip
530 c
531 branch: default
532 commit: (clean)
533 update: (current)
534 phases: 3 draft
General Comments 0
You need to be logged in to leave comments. Login now