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