##// END OF EJS Templates
update: resurrect bare update from null parent to tip-most branch head...
Yuya Nishihara -
r28924:d9539959 default
parent child Browse files
Show More
@@ -1,418 +1,422 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 if currentbranch in repo.branchmap():
98 if currentbranch in repo.branchmap():
99 heads = repo.branchheads(currentbranch)
99 heads = repo.branchheads(currentbranch)
100 if heads:
100 if heads:
101 node = repo.revs('max(.::(%ln))', heads).first()
101 node = repo.revs('max(.::(%ln))', heads).first()
102 if bookmarks.isactivewdirparent(repo):
102 if bookmarks.isactivewdirparent(repo):
103 movemark = repo['.'].node()
103 movemark = repo['.'].node()
104 elif currentbranch == 'default' and not wc.p1():
105 # "null" parent belongs to "default" branch, but it doesn't exist, so
106 # update to the tipmost non-closed branch head
107 node = repo.revs('max(head() and not closed())').first()
104 else:
108 else:
105 node = repo['.'].node()
109 node = repo['.'].node()
106 return node, movemark, None
110 return node, movemark, None
107
111
108 def _destupdatebranchfallback(repo, clean, check):
112 def _destupdatebranchfallback(repo, clean, check):
109 """decide on an update destination from closed heads in current branch"""
113 """decide on an update destination from closed heads in current branch"""
110 wc = repo[None]
114 wc = repo[None]
111 currentbranch = wc.branch()
115 currentbranch = wc.branch()
112 movemark = None
116 movemark = None
113 if currentbranch in repo.branchmap():
117 if currentbranch in repo.branchmap():
114 # here, all descendant branch heads are closed
118 # here, all descendant branch heads are closed
115 heads = repo.branchheads(currentbranch, closed=True)
119 heads = repo.branchheads(currentbranch, closed=True)
116 assert heads, "any branch has at least one head"
120 assert heads, "any branch has at least one head"
117 node = repo.revs('max(.::(%ln))', heads).first()
121 node = repo.revs('max(.::(%ln))', heads).first()
118 assert node is not None, ("any revision has at least "
122 assert node is not None, ("any revision has at least "
119 "one descendant branch head")
123 "one descendant branch head")
120 if bookmarks.isactivewdirparent(repo):
124 if bookmarks.isactivewdirparent(repo):
121 movemark = repo['.'].node()
125 movemark = repo['.'].node()
122 else:
126 else:
123 # here, no "default" branch, and all branches are closed
127 # here, no "default" branch, and all branches are closed
124 node = repo.lookup('tip')
128 node = repo.lookup('tip')
125 assert node is not None, "'tip' exists even in empty repository"
129 assert node is not None, "'tip' exists even in empty repository"
126 return node, movemark, None
130 return node, movemark, None
127
131
128 # order in which each step should be evalutated
132 # order in which each step should be evalutated
129 # steps are run until one finds a destination
133 # steps are run until one finds a destination
130 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
134 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
131 # mapping to ease extension overriding steps.
135 # mapping to ease extension overriding steps.
132 destupdatestepmap = {'evolution': _destupdateobs,
136 destupdatestepmap = {'evolution': _destupdateobs,
133 'bookmark': _destupdatebook,
137 'bookmark': _destupdatebook,
134 'branch': _destupdatebranch,
138 'branch': _destupdatebranch,
135 'branchfallback': _destupdatebranchfallback,
139 'branchfallback': _destupdatebranchfallback,
136 }
140 }
137
141
138 def destupdate(repo, clean=False, check=False):
142 def destupdate(repo, clean=False, check=False):
139 """destination for bare update operation
143 """destination for bare update operation
140
144
141 return (rev, movemark, activemark)
145 return (rev, movemark, activemark)
142
146
143 - rev: the revision to update to,
147 - rev: the revision to update to,
144 - movemark: node to move the active bookmark from
148 - movemark: node to move the active bookmark from
145 (cf bookmark.calculate update),
149 (cf bookmark.calculate update),
146 - activemark: a bookmark to activate at the end of the update.
150 - activemark: a bookmark to activate at the end of the update.
147 """
151 """
148 node = movemark = activemark = None
152 node = movemark = activemark = None
149
153
150 for step in destupdatesteps:
154 for step in destupdatesteps:
151 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
155 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
152 if node is not None:
156 if node is not None:
153 break
157 break
154 rev = repo[node].rev()
158 rev = repo[node].rev()
155
159
156 _destupdatevalidate(repo, rev, clean, check)
160 _destupdatevalidate(repo, rev, clean, check)
157
161
158 return rev, movemark, activemark
162 return rev, movemark, activemark
159
163
160 msgdestmerge = {
164 msgdestmerge = {
161 # too many matching divergent bookmark
165 # too many matching divergent bookmark
162 'toomanybookmarks':
166 'toomanybookmarks':
163 {'merge':
167 {'merge':
164 (_("multiple matching bookmarks to merge -"
168 (_("multiple matching bookmarks to merge -"
165 " please merge with an explicit rev or bookmark"),
169 " please merge with an explicit rev or bookmark"),
166 _("run 'hg heads' to see all heads")),
170 _("run 'hg heads' to see all heads")),
167 'rebase':
171 'rebase':
168 (_("multiple matching bookmarks to rebase -"
172 (_("multiple matching bookmarks to rebase -"
169 " please rebase to an explicit rev or bookmark"),
173 " please rebase to an explicit rev or bookmark"),
170 _("run 'hg heads' to see all heads")),
174 _("run 'hg heads' to see all heads")),
171 },
175 },
172 # no other matching divergent bookmark
176 # no other matching divergent bookmark
173 'nootherbookmarks':
177 'nootherbookmarks':
174 {'merge':
178 {'merge':
175 (_("no matching bookmark to merge - "
179 (_("no matching bookmark to merge - "
176 "please merge with an explicit rev or bookmark"),
180 "please merge with an explicit rev or bookmark"),
177 _("run 'hg heads' to see all heads")),
181 _("run 'hg heads' to see all heads")),
178 'rebase':
182 'rebase':
179 (_("no matching bookmark to rebase - "
183 (_("no matching bookmark to rebase - "
180 "please rebase to an explicit rev or bookmark"),
184 "please rebase to an explicit rev or bookmark"),
181 _("run 'hg heads' to see all heads")),
185 _("run 'hg heads' to see all heads")),
182 },
186 },
183 # branch have too many unbookmarked heads, no obvious destination
187 # branch have too many unbookmarked heads, no obvious destination
184 'toomanyheads':
188 'toomanyheads':
185 {'merge':
189 {'merge':
186 (_("branch '%s' has %d heads - please merge with an explicit rev"),
190 (_("branch '%s' has %d heads - please merge with an explicit rev"),
187 _("run 'hg heads .' to see heads")),
191 _("run 'hg heads .' to see heads")),
188 'rebase':
192 'rebase':
189 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
193 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
190 _("run 'hg heads .' to see heads")),
194 _("run 'hg heads .' to see heads")),
191 },
195 },
192 # branch have no other unbookmarked heads
196 # branch have no other unbookmarked heads
193 'bookmarkedheads':
197 'bookmarkedheads':
194 {'merge':
198 {'merge':
195 (_("heads are bookmarked - please merge with an explicit rev"),
199 (_("heads are bookmarked - please merge with an explicit rev"),
196 _("run 'hg heads' to see all heads")),
200 _("run 'hg heads' to see all heads")),
197 'rebase':
201 'rebase':
198 (_("heads are bookmarked - please rebase to an explicit rev"),
202 (_("heads are bookmarked - please rebase to an explicit rev"),
199 _("run 'hg heads' to see all heads")),
203 _("run 'hg heads' to see all heads")),
200 },
204 },
201 # branch have just a single heads, but there is other branches
205 # branch have just a single heads, but there is other branches
202 'nootherbranchheads':
206 'nootherbranchheads':
203 {'merge':
207 {'merge':
204 (_("branch '%s' has one head - please merge with an explicit rev"),
208 (_("branch '%s' has one head - please merge with an explicit rev"),
205 _("run 'hg heads' to see all heads")),
209 _("run 'hg heads' to see all heads")),
206 'rebase':
210 'rebase':
207 (_("branch '%s' has one head - please rebase to an explicit rev"),
211 (_("branch '%s' has one head - please rebase to an explicit rev"),
208 _("run 'hg heads' to see all heads")),
212 _("run 'hg heads' to see all heads")),
209 },
213 },
210 # repository have a single head
214 # repository have a single head
211 'nootherheads':
215 'nootherheads':
212 {'merge':
216 {'merge':
213 (_('nothing to merge'),
217 (_('nothing to merge'),
214 None),
218 None),
215 'rebase':
219 'rebase':
216 (_('nothing to rebase'),
220 (_('nothing to rebase'),
217 None),
221 None),
218 },
222 },
219 # repository have a single head and we are not on it
223 # repository have a single head and we are not on it
220 'nootherheadsbehind':
224 'nootherheadsbehind':
221 {'merge':
225 {'merge':
222 (_('nothing to merge'),
226 (_('nothing to merge'),
223 _("use 'hg update' instead")),
227 _("use 'hg update' instead")),
224 'rebase':
228 'rebase':
225 (_('nothing to rebase'),
229 (_('nothing to rebase'),
226 _("use 'hg update' instead")),
230 _("use 'hg update' instead")),
227 },
231 },
228 # We are not on a head
232 # We are not on a head
229 'notatheads':
233 'notatheads':
230 {'merge':
234 {'merge':
231 (_('working directory not at a head revision'),
235 (_('working directory not at a head revision'),
232 _("use 'hg update' or merge with an explicit revision")),
236 _("use 'hg update' or merge with an explicit revision")),
233 'rebase':
237 'rebase':
234 (_('working directory not at a head revision'),
238 (_('working directory not at a head revision'),
235 _("use 'hg update' or rebase to an explicit revision"))
239 _("use 'hg update' or rebase to an explicit revision"))
236 },
240 },
237 'emptysourceset':
241 'emptysourceset':
238 {'merge':
242 {'merge':
239 (_('source set is empty'),
243 (_('source set is empty'),
240 None),
244 None),
241 'rebase':
245 'rebase':
242 (_('source set is empty'),
246 (_('source set is empty'),
243 None),
247 None),
244 },
248 },
245 'multiplebranchessourceset':
249 'multiplebranchessourceset':
246 {'merge':
250 {'merge':
247 (_('source set is rooted in multiple branches'),
251 (_('source set is rooted in multiple branches'),
248 None),
252 None),
249 'rebase':
253 'rebase':
250 (_('rebaseset is rooted in multiple named branches'),
254 (_('rebaseset is rooted in multiple named branches'),
251 _('specify an explicit destination with --dest')),
255 _('specify an explicit destination with --dest')),
252 },
256 },
253 }
257 }
254
258
255 def _destmergebook(repo, action='merge', sourceset=None):
259 def _destmergebook(repo, action='merge', sourceset=None):
256 """find merge destination in the active bookmark case"""
260 """find merge destination in the active bookmark case"""
257 node = None
261 node = None
258 bmheads = repo.bookmarkheads(repo._activebookmark)
262 bmheads = repo.bookmarkheads(repo._activebookmark)
259 curhead = repo[repo._activebookmark].node()
263 curhead = repo[repo._activebookmark].node()
260 if len(bmheads) == 2:
264 if len(bmheads) == 2:
261 if curhead == bmheads[0]:
265 if curhead == bmheads[0]:
262 node = bmheads[1]
266 node = bmheads[1]
263 else:
267 else:
264 node = bmheads[0]
268 node = bmheads[0]
265 elif len(bmheads) > 2:
269 elif len(bmheads) > 2:
266 msg, hint = msgdestmerge['toomanybookmarks'][action]
270 msg, hint = msgdestmerge['toomanybookmarks'][action]
267 raise error.ManyMergeDestAbort(msg, hint=hint)
271 raise error.ManyMergeDestAbort(msg, hint=hint)
268 elif len(bmheads) <= 1:
272 elif len(bmheads) <= 1:
269 msg, hint = msgdestmerge['nootherbookmarks'][action]
273 msg, hint = msgdestmerge['nootherbookmarks'][action]
270 raise error.NoMergeDestAbort(msg, hint=hint)
274 raise error.NoMergeDestAbort(msg, hint=hint)
271 assert node is not None
275 assert node is not None
272 return node
276 return node
273
277
274 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
278 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
275 """find merge destination based on branch heads"""
279 """find merge destination based on branch heads"""
276 node = None
280 node = None
277
281
278 if sourceset is None:
282 if sourceset is None:
279 sourceset = [repo[repo.dirstate.p1()].rev()]
283 sourceset = [repo[repo.dirstate.p1()].rev()]
280 branch = repo.dirstate.branch()
284 branch = repo.dirstate.branch()
281 elif not sourceset:
285 elif not sourceset:
282 msg, hint = msgdestmerge['emptysourceset'][action]
286 msg, hint = msgdestmerge['emptysourceset'][action]
283 raise error.NoMergeDestAbort(msg, hint=hint)
287 raise error.NoMergeDestAbort(msg, hint=hint)
284 else:
288 else:
285 branch = None
289 branch = None
286 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
290 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
287 if branch is not None and ctx.branch() != branch:
291 if branch is not None and ctx.branch() != branch:
288 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
292 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
289 raise error.ManyMergeDestAbort(msg, hint=hint)
293 raise error.ManyMergeDestAbort(msg, hint=hint)
290 branch = ctx.branch()
294 branch = ctx.branch()
291
295
292 bheads = repo.branchheads(branch)
296 bheads = repo.branchheads(branch)
293 onhead = repo.revs('%ld and %ln', sourceset, bheads)
297 onhead = repo.revs('%ld and %ln', sourceset, bheads)
294 if onheadcheck and not onhead:
298 if onheadcheck and not onhead:
295 # Case A: working copy if not on a head. (merge only)
299 # Case A: working copy if not on a head. (merge only)
296 #
300 #
297 # This is probably a user mistake We bailout pointing at 'hg update'
301 # This is probably a user mistake We bailout pointing at 'hg update'
298 if len(repo.heads()) <= 1:
302 if len(repo.heads()) <= 1:
299 msg, hint = msgdestmerge['nootherheadsbehind'][action]
303 msg, hint = msgdestmerge['nootherheadsbehind'][action]
300 else:
304 else:
301 msg, hint = msgdestmerge['notatheads'][action]
305 msg, hint = msgdestmerge['notatheads'][action]
302 raise error.Abort(msg, hint=hint)
306 raise error.Abort(msg, hint=hint)
303 # remove heads descendants of source from the set
307 # remove heads descendants of source from the set
304 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
308 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
305 # filters out bookmarked heads
309 # filters out bookmarked heads
306 nbhs = list(repo.revs('%ld - bookmark()', bheads))
310 nbhs = list(repo.revs('%ld - bookmark()', bheads))
307 if len(nbhs) > 1:
311 if len(nbhs) > 1:
308 # Case B: There is more than 1 other anonymous heads
312 # Case B: There is more than 1 other anonymous heads
309 #
313 #
310 # This means that there will be more than 1 candidate. This is
314 # This means that there will be more than 1 candidate. This is
311 # ambiguous. We abort asking the user to pick as explicit destination
315 # ambiguous. We abort asking the user to pick as explicit destination
312 # instead.
316 # instead.
313 msg, hint = msgdestmerge['toomanyheads'][action]
317 msg, hint = msgdestmerge['toomanyheads'][action]
314 msg %= (branch, len(bheads) + 1)
318 msg %= (branch, len(bheads) + 1)
315 raise error.ManyMergeDestAbort(msg, hint=hint)
319 raise error.ManyMergeDestAbort(msg, hint=hint)
316 elif not nbhs:
320 elif not nbhs:
317 # Case B: There is no other anonymous heads
321 # Case B: There is no other anonymous heads
318 #
322 #
319 # This means that there is no natural candidate to merge with.
323 # This means that there is no natural candidate to merge with.
320 # We abort, with various messages for various cases.
324 # We abort, with various messages for various cases.
321 if bheads:
325 if bheads:
322 msg, hint = msgdestmerge['bookmarkedheads'][action]
326 msg, hint = msgdestmerge['bookmarkedheads'][action]
323 elif len(repo.heads()) > 1:
327 elif len(repo.heads()) > 1:
324 msg, hint = msgdestmerge['nootherbranchheads'][action]
328 msg, hint = msgdestmerge['nootherbranchheads'][action]
325 msg %= branch
329 msg %= branch
326 elif not onhead:
330 elif not onhead:
327 # if 'onheadcheck == False' (rebase case),
331 # if 'onheadcheck == False' (rebase case),
328 # this was not caught in Case A.
332 # this was not caught in Case A.
329 msg, hint = msgdestmerge['nootherheadsbehind'][action]
333 msg, hint = msgdestmerge['nootherheadsbehind'][action]
330 else:
334 else:
331 msg, hint = msgdestmerge['nootherheads'][action]
335 msg, hint = msgdestmerge['nootherheads'][action]
332 raise error.NoMergeDestAbort(msg, hint=hint)
336 raise error.NoMergeDestAbort(msg, hint=hint)
333 else:
337 else:
334 node = nbhs[0]
338 node = nbhs[0]
335 assert node is not None
339 assert node is not None
336 return node
340 return node
337
341
338 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
342 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
339 """return the default destination for a merge
343 """return the default destination for a merge
340
344
341 (or raise exception about why it can't pick one)
345 (or raise exception about why it can't pick one)
342
346
343 :action: the action being performed, controls emitted error message
347 :action: the action being performed, controls emitted error message
344 """
348 """
345 if repo._activebookmark:
349 if repo._activebookmark:
346 node = _destmergebook(repo, action=action, sourceset=sourceset)
350 node = _destmergebook(repo, action=action, sourceset=sourceset)
347 else:
351 else:
348 node = _destmergebranch(repo, action=action, sourceset=sourceset,
352 node = _destmergebranch(repo, action=action, sourceset=sourceset,
349 onheadcheck=onheadcheck)
353 onheadcheck=onheadcheck)
350 return repo[node].rev()
354 return repo[node].rev()
351
355
352 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
356 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
353
357
354 def desthistedit(ui, repo):
358 def desthistedit(ui, repo):
355 """Default base revision to edit for `hg histedit`."""
359 """Default base revision to edit for `hg histedit`."""
356 # Avoid cycle: scmutil -> revset -> destutil
360 # Avoid cycle: scmutil -> revset -> destutil
357 from . import scmutil
361 from . import scmutil
358
362
359 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
363 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
360 if default:
364 if default:
361 revs = scmutil.revrange(repo, [default])
365 revs = scmutil.revrange(repo, [default])
362 if revs:
366 if revs:
363 # The revset supplied by the user may not be in ascending order nor
367 # The revset supplied by the user may not be in ascending order nor
364 # take the first revision. So do this manually.
368 # take the first revision. So do this manually.
365 revs.sort()
369 revs.sort()
366 return revs.first()
370 return revs.first()
367
371
368 return None
372 return None
369
373
370 def _statusotherbook(ui, repo):
374 def _statusotherbook(ui, repo):
371 bmheads = repo.bookmarkheads(repo._activebookmark)
375 bmheads = repo.bookmarkheads(repo._activebookmark)
372 curhead = repo[repo._activebookmark].node()
376 curhead = repo[repo._activebookmark].node()
373 if repo.revs('%n and parents()', curhead):
377 if repo.revs('%n and parents()', curhead):
374 # we are on the active bookmark
378 # we are on the active bookmark
375 bmheads = [b for b in bmheads if curhead != b]
379 bmheads = [b for b in bmheads if curhead != b]
376 if bmheads:
380 if bmheads:
377 msg = _('%i other divergent bookmarks for "%s"\n')
381 msg = _('%i other divergent bookmarks for "%s"\n')
378 ui.status(msg % (len(bmheads), repo._activebookmark))
382 ui.status(msg % (len(bmheads), repo._activebookmark))
379
383
380 def _statusotherbranchheads(ui, repo):
384 def _statusotherbranchheads(ui, repo):
381 currentbranch = repo.dirstate.branch()
385 currentbranch = repo.dirstate.branch()
382 allheads = repo.branchheads(currentbranch, closed=True)
386 allheads = repo.branchheads(currentbranch, closed=True)
383 heads = repo.branchheads(currentbranch)
387 heads = repo.branchheads(currentbranch)
384 if repo.revs('%ln and parents()', allheads):
388 if repo.revs('%ln and parents()', allheads):
385 # we are on a head, even though it might be closed
389 # we are on a head, even though it might be closed
386 #
390 #
387 # on closed otherheads
391 # on closed otherheads
388 # ========= ==========
392 # ========= ==========
389 # o 0 all heads for current branch are closed
393 # o 0 all heads for current branch are closed
390 # N only descendant branch heads are closed
394 # N only descendant branch heads are closed
391 # x 0 there is only one non-closed branch head
395 # x 0 there is only one non-closed branch head
392 # N there are some non-closed branch heads
396 # N there are some non-closed branch heads
393 # ========= ==========
397 # ========= ==========
394 otherheads = repo.revs('%ln - parents()', heads)
398 otherheads = repo.revs('%ln - parents()', heads)
395 if repo['.'].closesbranch():
399 if repo['.'].closesbranch():
396 ui.warn(_('no open descendant heads on branch "%s", '
400 ui.warn(_('no open descendant heads on branch "%s", '
397 'updating to a closed head\n') %
401 'updating to a closed head\n') %
398 (currentbranch))
402 (currentbranch))
399 if otherheads:
403 if otherheads:
400 ui.warn(_('(committing will reopen the head, '
404 ui.warn(_('(committing will reopen the head, '
401 'use `hg heads .` to see %i other heads)\n') %
405 'use `hg heads .` to see %i other heads)\n') %
402 (len(otherheads)))
406 (len(otherheads)))
403 else:
407 else:
404 ui.warn(_('(committing will reopen branch "%s")\n') %
408 ui.warn(_('(committing will reopen branch "%s")\n') %
405 (currentbranch))
409 (currentbranch))
406 elif otherheads:
410 elif otherheads:
407 ui.status(_('%i other heads for branch "%s"\n') %
411 ui.status(_('%i other heads for branch "%s"\n') %
408 (len(otherheads), currentbranch))
412 (len(otherheads), currentbranch))
409
413
410 def statusotherdests(ui, repo):
414 def statusotherdests(ui, repo):
411 """Print message about other head"""
415 """Print message about other head"""
412 # XXX we should probably include a hint:
416 # XXX we should probably include a hint:
413 # - about what to do
417 # - about what to do
414 # - how to see such heads
418 # - how to see such heads
415 if repo._activebookmark:
419 if repo._activebookmark:
416 _statusotherbook(ui, repo)
420 _statusotherbook(ui, repo)
417 else:
421 else:
418 _statusotherbranchheads(ui, repo)
422 _statusotherbranchheads(ui, repo)
@@ -1,393 +1,465 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
395 $ cd ..
396
397 We need special handling for repositories with no "default" branch because
398 "null" revision belongs to non-existent "default" branch.
399
400 $ hg init nodefault
401 $ cd nodefault
402 $ hg branch -q foo
403 $ touch 0
404 $ hg ci -Aqm0
405 $ touch 1
406 $ hg ci -Aqm1
407 $ hg update -qr0
408 $ hg branch -q bar
409 $ touch 2
410 $ hg ci -Aqm2
411 $ hg update -qr0
412 $ hg branch -q baz
413 $ touch 3
414 $ hg ci -Aqm3
415 $ hg ci --close-branch -m 'close baz'
416 $ hg update -q null
417 $ hg log -GT'{rev} {branch}\n'
418 _ 4 baz
419 |
420 o 3 baz
421 |
422 | o 2 bar
423 |/
424 | o 1 foo
425 |/
426 o 0 foo
427
428
429 a) updating from "null" should bring us to the tip-most branch head as
430 there is no "default" branch:
431
432 $ hg update -q null
433 $ hg id -bn
434 -1 default
435 $ hg update
436 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 $ hg id -bn
438 2 bar
439
440 b) but if we are at uncommitted "default" branch, we should stick to the
441 current revision:
442
443 $ hg update -q 0
444 $ hg branch default
445 marked working directory as branch default
446 $ hg id -bn
447 0 default
448 $ hg update
449 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 $ hg id -bn
451 0 default
452
453 c) also, if we have uncommitted branch at "null", we should stick to it:
454
455 $ hg update -q null
456 $ hg branch new
457 marked working directory as branch new
458 $ hg id -bn
459 -1 new
460 $ hg update
461 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ hg id -bn
463 -1 new
464
465 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now