##// END OF EJS Templates
destutil: add new local variable to increase readability...
FUJIWARA Katsunori -
r28233:9da2283d default
parent child Browse files
Show More
@@ -1,376 +1,376 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 wc = repo[None]
92 wc = repo[None]
93 movemark = node = None
93 movemark = node = None
94 try:
94 try:
95 node = repo.revs('max(.::(head() and branch(%s)))'
95 node = repo.revs('max(.::(head() and branch(%s)))'
96 , wc.branch()).first()
96 , wc.branch()).first()
97 if bookmarks.isactivewdirparent(repo):
97 if bookmarks.isactivewdirparent(repo):
98 movemark = repo['.'].node()
98 movemark = repo['.'].node()
99 except error.RepoLookupError:
99 except error.RepoLookupError:
100 if wc.branch() == 'default': # no default branch!
100 if wc.branch() == 'default': # no default branch!
101 node = repo.lookup('tip') # update to tip
101 node = repo.lookup('tip') # update to tip
102 else:
102 else:
103 raise error.Abort(_("branch %s not found") % wc.branch())
103 raise error.Abort(_("branch %s not found") % wc.branch())
104 return node, movemark, None
104 return node, movemark, None
105
105
106 # order in which each step should be evalutated
106 # order in which each step should be evalutated
107 # steps are run until one finds a destination
107 # steps are run until one finds a destination
108 destupdatesteps = ['evolution', 'bookmark', 'branch']
108 destupdatesteps = ['evolution', 'bookmark', 'branch']
109 # mapping to ease extension overriding steps.
109 # mapping to ease extension overriding steps.
110 destupdatestepmap = {'evolution': _destupdateobs,
110 destupdatestepmap = {'evolution': _destupdateobs,
111 'bookmark': _destupdatebook,
111 'bookmark': _destupdatebook,
112 'branch': _destupdatebranch,
112 'branch': _destupdatebranch,
113 }
113 }
114
114
115 def destupdate(repo, clean=False, check=False):
115 def destupdate(repo, clean=False, check=False):
116 """destination for bare update operation
116 """destination for bare update operation
117
117
118 return (rev, movemark, activemark)
118 return (rev, movemark, activemark)
119
119
120 - rev: the revision to update to,
120 - rev: the revision to update to,
121 - movemark: node to move the active bookmark from
121 - movemark: node to move the active bookmark from
122 (cf bookmark.calculate update),
122 (cf bookmark.calculate update),
123 - activemark: a bookmark to activate at the end of the update.
123 - activemark: a bookmark to activate at the end of the update.
124 """
124 """
125 node = movemark = activemark = None
125 node = movemark = activemark = None
126
126
127 for step in destupdatesteps:
127 for step in destupdatesteps:
128 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
128 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
129 if node is not None:
129 if node is not None:
130 break
130 break
131 rev = repo[node].rev()
131 rev = repo[node].rev()
132
132
133 _destupdatevalidate(repo, rev, clean, check)
133 _destupdatevalidate(repo, rev, clean, check)
134
134
135 return rev, movemark, activemark
135 return rev, movemark, activemark
136
136
137 msgdestmerge = {
137 msgdestmerge = {
138 # too many matching divergent bookmark
138 # too many matching divergent bookmark
139 'toomanybookmarks':
139 'toomanybookmarks':
140 {'merge':
140 {'merge':
141 (_("multiple matching bookmarks to merge -"
141 (_("multiple matching bookmarks to merge -"
142 " please merge with an explicit rev or bookmark"),
142 " please merge with an explicit rev or bookmark"),
143 _("run 'hg heads' to see all heads")),
143 _("run 'hg heads' to see all heads")),
144 'rebase':
144 'rebase':
145 (_("multiple matching bookmarks to rebase -"
145 (_("multiple matching bookmarks to rebase -"
146 " please rebase to an explicit rev or bookmark"),
146 " please rebase to an explicit rev or bookmark"),
147 _("run 'hg heads' to see all heads")),
147 _("run 'hg heads' to see all heads")),
148 },
148 },
149 # no other matching divergent bookmark
149 # no other matching divergent bookmark
150 'nootherbookmarks':
150 'nootherbookmarks':
151 {'merge':
151 {'merge':
152 (_("no matching bookmark to merge - "
152 (_("no matching bookmark to merge - "
153 "please merge with an explicit rev or bookmark"),
153 "please merge with an explicit rev or bookmark"),
154 _("run 'hg heads' to see all heads")),
154 _("run 'hg heads' to see all heads")),
155 'rebase':
155 'rebase':
156 (_("no matching bookmark to rebase - "
156 (_("no matching bookmark to rebase - "
157 "please rebase to an explicit rev or bookmark"),
157 "please rebase to an explicit rev or bookmark"),
158 _("run 'hg heads' to see all heads")),
158 _("run 'hg heads' to see all heads")),
159 },
159 },
160 # branch have too many unbookmarked heads, no obvious destination
160 # branch have too many unbookmarked heads, no obvious destination
161 'toomanyheads':
161 'toomanyheads':
162 {'merge':
162 {'merge':
163 (_("branch '%s' has %d heads - please merge with an explicit rev"),
163 (_("branch '%s' has %d heads - please merge with an explicit rev"),
164 _("run 'hg heads .' to see heads")),
164 _("run 'hg heads .' to see heads")),
165 'rebase':
165 'rebase':
166 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
166 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
167 _("run 'hg heads .' to see heads")),
167 _("run 'hg heads .' to see heads")),
168 },
168 },
169 # branch have no other unbookmarked heads
169 # branch have no other unbookmarked heads
170 'bookmarkedheads':
170 'bookmarkedheads':
171 {'merge':
171 {'merge':
172 (_("heads are bookmarked - please merge with an explicit rev"),
172 (_("heads are bookmarked - please merge with an explicit rev"),
173 _("run 'hg heads' to see all heads")),
173 _("run 'hg heads' to see all heads")),
174 'rebase':
174 'rebase':
175 (_("heads are bookmarked - please rebase to an explicit rev"),
175 (_("heads are bookmarked - please rebase to an explicit rev"),
176 _("run 'hg heads' to see all heads")),
176 _("run 'hg heads' to see all heads")),
177 },
177 },
178 # branch have just a single heads, but there is other branches
178 # branch have just a single heads, but there is other branches
179 'nootherbranchheads':
179 'nootherbranchheads':
180 {'merge':
180 {'merge':
181 (_("branch '%s' has one head - please merge with an explicit rev"),
181 (_("branch '%s' has one head - please merge with an explicit rev"),
182 _("run 'hg heads' to see all heads")),
182 _("run 'hg heads' to see all heads")),
183 'rebase':
183 'rebase':
184 (_("branch '%s' has one head - please rebase to an explicit rev"),
184 (_("branch '%s' has one head - please rebase to an explicit rev"),
185 _("run 'hg heads' to see all heads")),
185 _("run 'hg heads' to see all heads")),
186 },
186 },
187 # repository have a single head
187 # repository have a single head
188 'nootherheads':
188 'nootherheads':
189 {'merge':
189 {'merge':
190 (_('nothing to merge'),
190 (_('nothing to merge'),
191 None),
191 None),
192 'rebase':
192 'rebase':
193 (_('nothing to rebase'),
193 (_('nothing to rebase'),
194 None),
194 None),
195 },
195 },
196 # repository have a single head and we are not on it
196 # repository have a single head and we are not on it
197 'nootherheadsbehind':
197 'nootherheadsbehind':
198 {'merge':
198 {'merge':
199 (_('nothing to merge'),
199 (_('nothing to merge'),
200 _("use 'hg update' instead")),
200 _("use 'hg update' instead")),
201 'rebase':
201 'rebase':
202 (_('nothing to rebase'),
202 (_('nothing to rebase'),
203 _("use 'hg update' instead")),
203 _("use 'hg update' instead")),
204 },
204 },
205 # We are not on a head
205 # We are not on a head
206 'notatheads':
206 'notatheads':
207 {'merge':
207 {'merge':
208 (_('working directory not at a head revision'),
208 (_('working directory not at a head revision'),
209 _("use 'hg update' or merge with an explicit revision")),
209 _("use 'hg update' or merge with an explicit revision")),
210 'rebase':
210 'rebase':
211 (_('working directory not at a head revision'),
211 (_('working directory not at a head revision'),
212 _("use 'hg update' or rebase to an explicit revision"))
212 _("use 'hg update' or rebase to an explicit revision"))
213 },
213 },
214 'emptysourceset':
214 'emptysourceset':
215 {'merge':
215 {'merge':
216 (_('source set is empty'),
216 (_('source set is empty'),
217 None),
217 None),
218 'rebase':
218 'rebase':
219 (_('source set is empty'),
219 (_('source set is empty'),
220 None),
220 None),
221 },
221 },
222 'multiplebranchessourceset':
222 'multiplebranchessourceset':
223 {'merge':
223 {'merge':
224 (_('source set is rooted in multiple branches'),
224 (_('source set is rooted in multiple branches'),
225 None),
225 None),
226 'rebase':
226 'rebase':
227 (_('rebaseset is rooted in multiple named branches'),
227 (_('rebaseset is rooted in multiple named branches'),
228 _('specify an explicit destination with --dest')),
228 _('specify an explicit destination with --dest')),
229 },
229 },
230 }
230 }
231
231
232 def _destmergebook(repo, action='merge', sourceset=None):
232 def _destmergebook(repo, action='merge', sourceset=None):
233 """find merge destination in the active bookmark case"""
233 """find merge destination in the active bookmark case"""
234 node = None
234 node = None
235 bmheads = repo.bookmarkheads(repo._activebookmark)
235 bmheads = repo.bookmarkheads(repo._activebookmark)
236 curhead = repo[repo._activebookmark].node()
236 curhead = repo[repo._activebookmark].node()
237 if len(bmheads) == 2:
237 if len(bmheads) == 2:
238 if curhead == bmheads[0]:
238 if curhead == bmheads[0]:
239 node = bmheads[1]
239 node = bmheads[1]
240 else:
240 else:
241 node = bmheads[0]
241 node = bmheads[0]
242 elif len(bmheads) > 2:
242 elif len(bmheads) > 2:
243 msg, hint = msgdestmerge['toomanybookmarks'][action]
243 msg, hint = msgdestmerge['toomanybookmarks'][action]
244 raise error.ManyMergeDestAbort(msg, hint=hint)
244 raise error.ManyMergeDestAbort(msg, hint=hint)
245 elif len(bmheads) <= 1:
245 elif len(bmheads) <= 1:
246 msg, hint = msgdestmerge['nootherbookmarks'][action]
246 msg, hint = msgdestmerge['nootherbookmarks'][action]
247 raise error.NoMergeDestAbort(msg, hint=hint)
247 raise error.NoMergeDestAbort(msg, hint=hint)
248 assert node is not None
248 assert node is not None
249 return node
249 return node
250
250
251 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
251 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
252 """find merge destination based on branch heads"""
252 """find merge destination based on branch heads"""
253 node = None
253 node = None
254
254
255 if sourceset is None:
255 if sourceset is None:
256 sourceset = [repo[repo.dirstate.p1()].rev()]
256 sourceset = [repo[repo.dirstate.p1()].rev()]
257 branch = repo.dirstate.branch()
257 branch = repo.dirstate.branch()
258 elif not sourceset:
258 elif not sourceset:
259 msg, hint = msgdestmerge['emptysourceset'][action]
259 msg, hint = msgdestmerge['emptysourceset'][action]
260 raise error.NoMergeDestAbort(msg, hint=hint)
260 raise error.NoMergeDestAbort(msg, hint=hint)
261 else:
261 else:
262 branch = None
262 branch = None
263 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
263 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
264 if branch is not None and ctx.branch() != branch:
264 if branch is not None and ctx.branch() != branch:
265 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
265 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
266 raise error.ManyMergeDestAbort(msg, hint=hint)
266 raise error.ManyMergeDestAbort(msg, hint=hint)
267 branch = ctx.branch()
267 branch = ctx.branch()
268
268
269 bheads = repo.branchheads(branch)
269 bheads = repo.branchheads(branch)
270 onhead = repo.revs('%ld and %ln', sourceset, bheads)
270 onhead = repo.revs('%ld and %ln', sourceset, bheads)
271 if onheadcheck and not onhead:
271 if onheadcheck and not onhead:
272 # Case A: working copy if not on a head. (merge only)
272 # Case A: working copy if not on a head. (merge only)
273 #
273 #
274 # This is probably a user mistake We bailout pointing at 'hg update'
274 # This is probably a user mistake We bailout pointing at 'hg update'
275 if len(repo.heads()) <= 1:
275 if len(repo.heads()) <= 1:
276 msg, hint = msgdestmerge['nootherheadsbehind'][action]
276 msg, hint = msgdestmerge['nootherheadsbehind'][action]
277 else:
277 else:
278 msg, hint = msgdestmerge['notatheads'][action]
278 msg, hint = msgdestmerge['notatheads'][action]
279 raise error.Abort(msg, hint=hint)
279 raise error.Abort(msg, hint=hint)
280 # remove heads descendants of source from the set
280 # remove heads descendants of source from the set
281 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
281 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
282 # filters out bookmarked heads
282 # filters out bookmarked heads
283 nbhs = list(repo.revs('%ld - bookmark()', bheads))
283 nbhs = list(repo.revs('%ld - bookmark()', bheads))
284 if len(nbhs) > 1:
284 if len(nbhs) > 1:
285 # Case B: There is more than 1 other anonymous heads
285 # Case B: There is more than 1 other anonymous heads
286 #
286 #
287 # This means that there will be more than 1 candidate. This is
287 # This means that there will be more than 1 candidate. This is
288 # ambiguous. We abort asking the user to pick as explicit destination
288 # ambiguous. We abort asking the user to pick as explicit destination
289 # instead.
289 # instead.
290 msg, hint = msgdestmerge['toomanyheads'][action]
290 msg, hint = msgdestmerge['toomanyheads'][action]
291 msg %= (branch, len(bheads) + 1)
291 msg %= (branch, len(bheads) + 1)
292 raise error.ManyMergeDestAbort(msg, hint=hint)
292 raise error.ManyMergeDestAbort(msg, hint=hint)
293 elif not nbhs:
293 elif not nbhs:
294 # Case B: There is no other anonymous heads
294 # Case B: There is no other anonymous heads
295 #
295 #
296 # This means that there is no natural candidate to merge with.
296 # This means that there is no natural candidate to merge with.
297 # We abort, with various messages for various cases.
297 # We abort, with various messages for various cases.
298 if bheads:
298 if bheads:
299 msg, hint = msgdestmerge['bookmarkedheads'][action]
299 msg, hint = msgdestmerge['bookmarkedheads'][action]
300 elif len(repo.heads()) > 1:
300 elif len(repo.heads()) > 1:
301 msg, hint = msgdestmerge['nootherbranchheads'][action]
301 msg, hint = msgdestmerge['nootherbranchheads'][action]
302 msg %= branch
302 msg %= branch
303 elif not onhead:
303 elif not onhead:
304 # if 'onheadcheck == False' (rebase case),
304 # if 'onheadcheck == False' (rebase case),
305 # this was not caught in Case A.
305 # this was not caught in Case A.
306 msg, hint = msgdestmerge['nootherheadsbehind'][action]
306 msg, hint = msgdestmerge['nootherheadsbehind'][action]
307 else:
307 else:
308 msg, hint = msgdestmerge['nootherheads'][action]
308 msg, hint = msgdestmerge['nootherheads'][action]
309 raise error.NoMergeDestAbort(msg, hint=hint)
309 raise error.NoMergeDestAbort(msg, hint=hint)
310 else:
310 else:
311 node = nbhs[0]
311 node = nbhs[0]
312 assert node is not None
312 assert node is not None
313 return node
313 return node
314
314
315 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
315 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
316 """return the default destination for a merge
316 """return the default destination for a merge
317
317
318 (or raise exception about why it can't pick one)
318 (or raise exception about why it can't pick one)
319
319
320 :action: the action being performed, controls emitted error message
320 :action: the action being performed, controls emitted error message
321 """
321 """
322 if repo._activebookmark:
322 if repo._activebookmark:
323 node = _destmergebook(repo, action=action, sourceset=sourceset)
323 node = _destmergebook(repo, action=action, sourceset=sourceset)
324 else:
324 else:
325 node = _destmergebranch(repo, action=action, sourceset=sourceset,
325 node = _destmergebranch(repo, action=action, sourceset=sourceset,
326 onheadcheck=onheadcheck)
326 onheadcheck=onheadcheck)
327 return repo[node].rev()
327 return repo[node].rev()
328
328
329 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
329 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
330
330
331 def desthistedit(ui, repo):
331 def desthistedit(ui, repo):
332 """Default base revision to edit for `hg histedit`."""
332 """Default base revision to edit for `hg histedit`."""
333 # Avoid cycle: scmutil -> revset -> destutil
333 # Avoid cycle: scmutil -> revset -> destutil
334 from . import scmutil
334 from . import scmutil
335
335
336 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
336 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
337 if default:
337 if default:
338 revs = scmutil.revrange(repo, [default])
338 revs = scmutil.revrange(repo, [default])
339 if revs:
339 if revs:
340 # The revset supplied by the user may not be in ascending order nor
340 # The revset supplied by the user may not be in ascending order nor
341 # take the first revision. So do this manually.
341 # take the first revision. So do this manually.
342 revs.sort()
342 revs.sort()
343 return revs.first()
343 return revs.first()
344
344
345 return None
345 return None
346
346
347 def _statusotherbook(ui, repo):
347 def _statusotherbook(ui, repo):
348 bmheads = repo.bookmarkheads(repo._activebookmark)
348 bmheads = repo.bookmarkheads(repo._activebookmark)
349 curhead = repo[repo._activebookmark].node()
349 curhead = repo[repo._activebookmark].node()
350 if repo.revs('%n and parents()', curhead):
350 if repo.revs('%n and parents()', curhead):
351 # we are on the active bookmark
351 # we are on the active bookmark
352 bmheads = [b for b in bmheads if curhead != b]
352 bmheads = [b for b in bmheads if curhead != b]
353 if bmheads:
353 if bmheads:
354 msg = _('%i other divergent bookmarks for "%s"\n')
354 msg = _('%i other divergent bookmarks for "%s"\n')
355 ui.status(msg % (len(bmheads), repo._activebookmark))
355 ui.status(msg % (len(bmheads), repo._activebookmark))
356
356
357 def _statusotherbranchheads(ui, repo):
357 def _statusotherbranchheads(ui, repo):
358 currentbranch = repo.dirstate.branch()
358 currentbranch = repo.dirstate.branch()
359 heads = repo.branchheads(currentbranch)
359 heads = repo.branchheads(currentbranch)
360 l = len(heads)
360 l = len(heads)
361 if repo.revs('%ln and parents()', heads):
361 if repo.revs('%ln and parents()', heads):
362 # we are on a head
362 # we are on a head
363 heads = repo.revs('%ln - parents()', heads)
363 otherheads = repo.revs('%ln - parents()', heads)
364 if heads and l != len(heads):
364 if otherheads and l != len(otherheads):
365 ui.status(_('%i other heads for branch "%s"\n') %
365 ui.status(_('%i other heads for branch "%s"\n') %
366 (len(heads), currentbranch))
366 (len(otherheads), currentbranch))
367
367
368 def statusotherdests(ui, repo):
368 def statusotherdests(ui, repo):
369 """Print message about other head"""
369 """Print message about other head"""
370 # XXX we should probably include a hint:
370 # XXX we should probably include a hint:
371 # - about what to do
371 # - about what to do
372 # - how to see such heads
372 # - how to see such heads
373 if repo._activebookmark:
373 if repo._activebookmark:
374 _statusotherbook(ui, repo)
374 _statusotherbook(ui, repo)
375 else:
375 else:
376 _statusotherbranchheads(ui, repo)
376 _statusotherbranchheads(ui, repo)
General Comments 0
You need to be logged in to leave comments. Login now