##// END OF EJS Templates
push: added clear warning message when pushing closed branches(issue6080)...
Taapas Agrawal -
r42389:5997eabc default
parent child Browse files
Show More
@@ -1,529 +1,538 b''
1 # discovery.py - protocol changeset discovery functions
1 # discovery.py - protocol changeset discovery functions
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
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 import functools
10 import functools
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 hex,
14 hex,
15 nullid,
15 nullid,
16 short,
16 short,
17 )
17 )
18
18
19 from . import (
19 from . import (
20 bookmarks,
20 bookmarks,
21 branchmap,
21 branchmap,
22 error,
22 error,
23 phases,
23 phases,
24 scmutil,
24 scmutil,
25 setdiscovery,
25 setdiscovery,
26 treediscovery,
26 treediscovery,
27 util,
27 util,
28 )
28 )
29
29
30 def findcommonincoming(repo, remote, heads=None, force=False, ancestorsof=None):
30 def findcommonincoming(repo, remote, heads=None, force=False, ancestorsof=None):
31 """Return a tuple (common, anyincoming, heads) used to identify the common
31 """Return a tuple (common, anyincoming, heads) used to identify the common
32 subset of nodes between repo and remote.
32 subset of nodes between repo and remote.
33
33
34 "common" is a list of (at least) the heads of the common subset.
34 "common" is a list of (at least) the heads of the common subset.
35 "anyincoming" is testable as a boolean indicating if any nodes are missing
35 "anyincoming" is testable as a boolean indicating if any nodes are missing
36 locally. If remote does not support getbundle, this actually is a list of
36 locally. If remote does not support getbundle, this actually is a list of
37 roots of the nodes that would be incoming, to be supplied to
37 roots of the nodes that would be incoming, to be supplied to
38 changegroupsubset. No code except for pull should be relying on this fact
38 changegroupsubset. No code except for pull should be relying on this fact
39 any longer.
39 any longer.
40 "heads" is either the supplied heads, or else the remote's heads.
40 "heads" is either the supplied heads, or else the remote's heads.
41 "ancestorsof" if not None, restrict the discovery to a subset defined by
41 "ancestorsof" if not None, restrict the discovery to a subset defined by
42 these nodes. Changeset outside of this set won't be considered (and
42 these nodes. Changeset outside of this set won't be considered (and
43 won't appears in "common")
43 won't appears in "common")
44
44
45 If you pass heads and they are all known locally, the response lists just
45 If you pass heads and they are all known locally, the response lists just
46 these heads in "common" and in "heads".
46 these heads in "common" and in "heads".
47
47
48 Please use findcommonoutgoing to compute the set of outgoing nodes to give
48 Please use findcommonoutgoing to compute the set of outgoing nodes to give
49 extensions a good hook into outgoing.
49 extensions a good hook into outgoing.
50 """
50 """
51
51
52 if not remote.capable('getbundle'):
52 if not remote.capable('getbundle'):
53 return treediscovery.findcommonincoming(repo, remote, heads, force)
53 return treediscovery.findcommonincoming(repo, remote, heads, force)
54
54
55 if heads:
55 if heads:
56 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
56 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
57 if all(knownnode(h) for h in heads):
57 if all(knownnode(h) for h in heads):
58 return (heads, False, heads)
58 return (heads, False, heads)
59
59
60 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
60 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
61 abortwhenunrelated=not force,
61 abortwhenunrelated=not force,
62 ancestorsof=ancestorsof)
62 ancestorsof=ancestorsof)
63 common, anyinc, srvheads = res
63 common, anyinc, srvheads = res
64 return (list(common), anyinc, heads or list(srvheads))
64 return (list(common), anyinc, heads or list(srvheads))
65
65
66 class outgoing(object):
66 class outgoing(object):
67 '''Represents the set of nodes present in a local repo but not in a
67 '''Represents the set of nodes present in a local repo but not in a
68 (possibly) remote one.
68 (possibly) remote one.
69
69
70 Members:
70 Members:
71
71
72 missing is a list of all nodes present in local but not in remote.
72 missing is a list of all nodes present in local but not in remote.
73 common is a list of all nodes shared between the two repos.
73 common is a list of all nodes shared between the two repos.
74 excluded is the list of missing changeset that shouldn't be sent remotely.
74 excluded is the list of missing changeset that shouldn't be sent remotely.
75 missingheads is the list of heads of missing.
75 missingheads is the list of heads of missing.
76 commonheads is the list of heads of common.
76 commonheads is the list of heads of common.
77
77
78 The sets are computed on demand from the heads, unless provided upfront
78 The sets are computed on demand from the heads, unless provided upfront
79 by discovery.'''
79 by discovery.'''
80
80
81 def __init__(self, repo, commonheads=None, missingheads=None,
81 def __init__(self, repo, commonheads=None, missingheads=None,
82 missingroots=None):
82 missingroots=None):
83 # at least one of them must not be set
83 # at least one of them must not be set
84 assert None in (commonheads, missingroots)
84 assert None in (commonheads, missingroots)
85 cl = repo.changelog
85 cl = repo.changelog
86 if missingheads is None:
86 if missingheads is None:
87 missingheads = cl.heads()
87 missingheads = cl.heads()
88 if missingroots:
88 if missingroots:
89 discbases = []
89 discbases = []
90 for n in missingroots:
90 for n in missingroots:
91 discbases.extend([p for p in cl.parents(n) if p != nullid])
91 discbases.extend([p for p in cl.parents(n) if p != nullid])
92 # TODO remove call to nodesbetween.
92 # TODO remove call to nodesbetween.
93 # TODO populate attributes on outgoing instance instead of setting
93 # TODO populate attributes on outgoing instance instead of setting
94 # discbases.
94 # discbases.
95 csets, roots, heads = cl.nodesbetween(missingroots, missingheads)
95 csets, roots, heads = cl.nodesbetween(missingroots, missingheads)
96 included = set(csets)
96 included = set(csets)
97 missingheads = heads
97 missingheads = heads
98 commonheads = [n for n in discbases if n not in included]
98 commonheads = [n for n in discbases if n not in included]
99 elif not commonheads:
99 elif not commonheads:
100 commonheads = [nullid]
100 commonheads = [nullid]
101 self.commonheads = commonheads
101 self.commonheads = commonheads
102 self.missingheads = missingheads
102 self.missingheads = missingheads
103 self._revlog = cl
103 self._revlog = cl
104 self._common = None
104 self._common = None
105 self._missing = None
105 self._missing = None
106 self.excluded = []
106 self.excluded = []
107
107
108 def _computecommonmissing(self):
108 def _computecommonmissing(self):
109 sets = self._revlog.findcommonmissing(self.commonheads,
109 sets = self._revlog.findcommonmissing(self.commonheads,
110 self.missingheads)
110 self.missingheads)
111 self._common, self._missing = sets
111 self._common, self._missing = sets
112
112
113 @util.propertycache
113 @util.propertycache
114 def common(self):
114 def common(self):
115 if self._common is None:
115 if self._common is None:
116 self._computecommonmissing()
116 self._computecommonmissing()
117 return self._common
117 return self._common
118
118
119 @util.propertycache
119 @util.propertycache
120 def missing(self):
120 def missing(self):
121 if self._missing is None:
121 if self._missing is None:
122 self._computecommonmissing()
122 self._computecommonmissing()
123 return self._missing
123 return self._missing
124
124
125 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
125 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
126 commoninc=None, portable=False):
126 commoninc=None, portable=False):
127 '''Return an outgoing instance to identify the nodes present in repo but
127 '''Return an outgoing instance to identify the nodes present in repo but
128 not in other.
128 not in other.
129
129
130 If onlyheads is given, only nodes ancestral to nodes in onlyheads
130 If onlyheads is given, only nodes ancestral to nodes in onlyheads
131 (inclusive) are included. If you already know the local repo's heads,
131 (inclusive) are included. If you already know the local repo's heads,
132 passing them in onlyheads is faster than letting them be recomputed here.
132 passing them in onlyheads is faster than letting them be recomputed here.
133
133
134 If commoninc is given, it must be the result of a prior call to
134 If commoninc is given, it must be the result of a prior call to
135 findcommonincoming(repo, other, force) to avoid recomputing it here.
135 findcommonincoming(repo, other, force) to avoid recomputing it here.
136
136
137 If portable is given, compute more conservative common and missingheads,
137 If portable is given, compute more conservative common and missingheads,
138 to make bundles created from the instance more portable.'''
138 to make bundles created from the instance more portable.'''
139 # declare an empty outgoing object to be filled later
139 # declare an empty outgoing object to be filled later
140 og = outgoing(repo, None, None)
140 og = outgoing(repo, None, None)
141
141
142 # get common set if not provided
142 # get common set if not provided
143 if commoninc is None:
143 if commoninc is None:
144 commoninc = findcommonincoming(repo, other, force=force,
144 commoninc = findcommonincoming(repo, other, force=force,
145 ancestorsof=onlyheads)
145 ancestorsof=onlyheads)
146 og.commonheads, _any, _hds = commoninc
146 og.commonheads, _any, _hds = commoninc
147
147
148 # compute outgoing
148 # compute outgoing
149 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
149 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
150 if not mayexclude:
150 if not mayexclude:
151 og.missingheads = onlyheads or repo.heads()
151 og.missingheads = onlyheads or repo.heads()
152 elif onlyheads is None:
152 elif onlyheads is None:
153 # use visible heads as it should be cached
153 # use visible heads as it should be cached
154 og.missingheads = repo.filtered("served").heads()
154 og.missingheads = repo.filtered("served").heads()
155 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
155 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
156 else:
156 else:
157 # compute common, missing and exclude secret stuff
157 # compute common, missing and exclude secret stuff
158 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
158 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
159 og._common, allmissing = sets
159 og._common, allmissing = sets
160 og._missing = missing = []
160 og._missing = missing = []
161 og.excluded = excluded = []
161 og.excluded = excluded = []
162 for node in allmissing:
162 for node in allmissing:
163 ctx = repo[node]
163 ctx = repo[node]
164 if ctx.phase() >= phases.secret or ctx.extinct():
164 if ctx.phase() >= phases.secret or ctx.extinct():
165 excluded.append(node)
165 excluded.append(node)
166 else:
166 else:
167 missing.append(node)
167 missing.append(node)
168 if len(missing) == len(allmissing):
168 if len(missing) == len(allmissing):
169 missingheads = onlyheads
169 missingheads = onlyheads
170 else: # update missing heads
170 else: # update missing heads
171 missingheads = phases.newheads(repo, onlyheads, excluded)
171 missingheads = phases.newheads(repo, onlyheads, excluded)
172 og.missingheads = missingheads
172 og.missingheads = missingheads
173 if portable:
173 if portable:
174 # recompute common and missingheads as if -r<rev> had been given for
174 # recompute common and missingheads as if -r<rev> had been given for
175 # each head of missing, and --base <rev> for each head of the proper
175 # each head of missing, and --base <rev> for each head of the proper
176 # ancestors of missing
176 # ancestors of missing
177 og._computecommonmissing()
177 og._computecommonmissing()
178 cl = repo.changelog
178 cl = repo.changelog
179 missingrevs = set(cl.rev(n) for n in og._missing)
179 missingrevs = set(cl.rev(n) for n in og._missing)
180 og._common = set(cl.ancestors(missingrevs)) - missingrevs
180 og._common = set(cl.ancestors(missingrevs)) - missingrevs
181 commonheads = set(og.commonheads)
181 commonheads = set(og.commonheads)
182 og.missingheads = [h for h in og.missingheads if h not in commonheads]
182 og.missingheads = [h for h in og.missingheads if h not in commonheads]
183
183
184 return og
184 return og
185
185
186 def _headssummary(pushop):
186 def _headssummary(pushop):
187 """compute a summary of branch and heads status before and after push
187 """compute a summary of branch and heads status before and after push
188
188
189 return {'branch': ([remoteheads], [newheads],
189 return {'branch': ([remoteheads], [newheads],
190 [unsyncedheads], [discardedheads])} mapping
190 [unsyncedheads], [discardedheads])} mapping
191
191
192 - branch: the branch name,
192 - branch: the branch name,
193 - remoteheads: the list of remote heads known locally
193 - remoteheads: the list of remote heads known locally
194 None if the branch is new,
194 None if the branch is new,
195 - newheads: the new remote heads (known locally) with outgoing pushed,
195 - newheads: the new remote heads (known locally) with outgoing pushed,
196 - unsyncedheads: the list of remote heads unknown locally,
196 - unsyncedheads: the list of remote heads unknown locally,
197 - discardedheads: the list of heads made obsolete by the push.
197 - discardedheads: the list of heads made obsolete by the push.
198 """
198 """
199 repo = pushop.repo.unfiltered()
199 repo = pushop.repo.unfiltered()
200 remote = pushop.remote
200 remote = pushop.remote
201 outgoing = pushop.outgoing
201 outgoing = pushop.outgoing
202 cl = repo.changelog
202 cl = repo.changelog
203 headssum = {}
203 headssum = {}
204 missingctx = set()
204 missingctx = set()
205 # A. Create set of branches involved in the push.
205 # A. Create set of branches involved in the push.
206 branches = set()
206 branches = set()
207 for n in outgoing.missing:
207 for n in outgoing.missing:
208 ctx = repo[n]
208 ctx = repo[n]
209 missingctx.add(ctx)
209 missingctx.add(ctx)
210 branches.add(ctx.branch())
210 branches.add(ctx.branch())
211
211
212 with remote.commandexecutor() as e:
212 with remote.commandexecutor() as e:
213 remotemap = e.callcommand('branchmap', {}).result()
213 remotemap = e.callcommand('branchmap', {}).result()
214
214
215 knownnode = cl.hasnode # do not use nodemap until it is filtered
215 knownnode = cl.hasnode # do not use nodemap until it is filtered
216 # A. register remote heads of branches which are in outgoing set
216 # A. register remote heads of branches which are in outgoing set
217 for branch, heads in remotemap.iteritems():
217 for branch, heads in remotemap.iteritems():
218 # don't add head info about branches which we don't have locally
218 # don't add head info about branches which we don't have locally
219 if branch not in branches:
219 if branch not in branches:
220 continue
220 continue
221 known = []
221 known = []
222 unsynced = []
222 unsynced = []
223 for h in heads:
223 for h in heads:
224 if knownnode(h):
224 if knownnode(h):
225 known.append(h)
225 known.append(h)
226 else:
226 else:
227 unsynced.append(h)
227 unsynced.append(h)
228 headssum[branch] = (known, list(known), unsynced)
228 headssum[branch] = (known, list(known), unsynced)
229
229
230 # B. add new branch data
230 # B. add new branch data
231 for branch in branches:
231 for branch in branches:
232 if branch not in headssum:
232 if branch not in headssum:
233 headssum[branch] = (None, [], [])
233 headssum[branch] = (None, [], [])
234
234
235 # C. Update newmap with outgoing changes.
235 # C. Update newmap with outgoing changes.
236 # This will possibly add new heads and remove existing ones.
236 # This will possibly add new heads and remove existing ones.
237 newmap = branchmap.remotebranchcache((branch, heads[1])
237 newmap = branchmap.remotebranchcache((branch, heads[1])
238 for branch, heads in headssum.iteritems()
238 for branch, heads in headssum.iteritems()
239 if heads[0] is not None)
239 if heads[0] is not None)
240 newmap.update(repo, (ctx.rev() for ctx in missingctx))
240 newmap.update(repo, (ctx.rev() for ctx in missingctx))
241 for branch, newheads in newmap.iteritems():
241 for branch, newheads in newmap.iteritems():
242 headssum[branch][1][:] = newheads
242 headssum[branch][1][:] = newheads
243 for branch, items in headssum.iteritems():
243 for branch, items in headssum.iteritems():
244 for l in items:
244 for l in items:
245 if l is not None:
245 if l is not None:
246 l.sort()
246 l.sort()
247 headssum[branch] = items + ([],)
247 headssum[branch] = items + ([],)
248
248
249 # If there are no obsstore, no post processing are needed.
249 # If there are no obsstore, no post processing are needed.
250 if repo.obsstore:
250 if repo.obsstore:
251 torev = repo.changelog.rev
251 torev = repo.changelog.rev
252 futureheads = set(torev(h) for h in outgoing.missingheads)
252 futureheads = set(torev(h) for h in outgoing.missingheads)
253 futureheads |= set(torev(h) for h in outgoing.commonheads)
253 futureheads |= set(torev(h) for h in outgoing.commonheads)
254 allfuturecommon = repo.changelog.ancestors(futureheads, inclusive=True)
254 allfuturecommon = repo.changelog.ancestors(futureheads, inclusive=True)
255 for branch, heads in sorted(headssum.iteritems()):
255 for branch, heads in sorted(headssum.iteritems()):
256 remoteheads, newheads, unsyncedheads, placeholder = heads
256 remoteheads, newheads, unsyncedheads, placeholder = heads
257 result = _postprocessobsolete(pushop, allfuturecommon, newheads)
257 result = _postprocessobsolete(pushop, allfuturecommon, newheads)
258 headssum[branch] = (remoteheads, sorted(result[0]), unsyncedheads,
258 headssum[branch] = (remoteheads, sorted(result[0]), unsyncedheads,
259 sorted(result[1]))
259 sorted(result[1]))
260 return headssum
260 return headssum
261
261
262 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
262 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
263 """Compute branchmapsummary for repo without branchmap support"""
263 """Compute branchmapsummary for repo without branchmap support"""
264
264
265 # 1-4b. old servers: Check for new topological heads.
265 # 1-4b. old servers: Check for new topological heads.
266 # Construct {old,new}map with branch = None (topological branch).
266 # Construct {old,new}map with branch = None (topological branch).
267 # (code based on update)
267 # (code based on update)
268 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
268 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
269 oldheads = sorted(h for h in remoteheads if knownnode(h))
269 oldheads = sorted(h for h in remoteheads if knownnode(h))
270 # all nodes in outgoing.missing are children of either:
270 # all nodes in outgoing.missing are children of either:
271 # - an element of oldheads
271 # - an element of oldheads
272 # - another element of outgoing.missing
272 # - another element of outgoing.missing
273 # - nullrev
273 # - nullrev
274 # This explains why the new head are very simple to compute.
274 # This explains why the new head are very simple to compute.
275 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
275 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
276 newheads = sorted(c.node() for c in r)
276 newheads = sorted(c.node() for c in r)
277 # set some unsynced head to issue the "unsynced changes" warning
277 # set some unsynced head to issue the "unsynced changes" warning
278 if inc:
278 if inc:
279 unsynced = [None]
279 unsynced = [None]
280 else:
280 else:
281 unsynced = []
281 unsynced = []
282 return {None: (oldheads, newheads, unsynced, [])}
282 return {None: (oldheads, newheads, unsynced, [])}
283
283
284 def _nowarnheads(pushop):
284 def _nowarnheads(pushop):
285 # Compute newly pushed bookmarks. We don't warn about bookmarked heads.
285 # Compute newly pushed bookmarks. We don't warn about bookmarked heads.
286 repo = pushop.repo.unfiltered()
286 repo = pushop.repo.unfiltered()
287 remote = pushop.remote
287 remote = pushop.remote
288 localbookmarks = repo._bookmarks
288 localbookmarks = repo._bookmarks
289
289
290 with remote.commandexecutor() as e:
290 with remote.commandexecutor() as e:
291 remotebookmarks = e.callcommand('listkeys', {
291 remotebookmarks = e.callcommand('listkeys', {
292 'namespace': 'bookmarks',
292 'namespace': 'bookmarks',
293 }).result()
293 }).result()
294
294
295 bookmarkedheads = set()
295 bookmarkedheads = set()
296
296
297 # internal config: bookmarks.pushing
297 # internal config: bookmarks.pushing
298 newbookmarks = [localbookmarks.expandname(b)
298 newbookmarks = [localbookmarks.expandname(b)
299 for b in pushop.ui.configlist('bookmarks', 'pushing')]
299 for b in pushop.ui.configlist('bookmarks', 'pushing')]
300
300
301 for bm in localbookmarks:
301 for bm in localbookmarks:
302 rnode = remotebookmarks.get(bm)
302 rnode = remotebookmarks.get(bm)
303 if rnode and rnode in repo:
303 if rnode and rnode in repo:
304 lctx, rctx = localbookmarks.changectx(bm), repo[rnode]
304 lctx, rctx = localbookmarks.changectx(bm), repo[rnode]
305 if bookmarks.validdest(repo, rctx, lctx):
305 if bookmarks.validdest(repo, rctx, lctx):
306 bookmarkedheads.add(lctx.node())
306 bookmarkedheads.add(lctx.node())
307 else:
307 else:
308 if bm in newbookmarks and bm not in remotebookmarks:
308 if bm in newbookmarks and bm not in remotebookmarks:
309 bookmarkedheads.add(localbookmarks[bm])
309 bookmarkedheads.add(localbookmarks[bm])
310
310
311 return bookmarkedheads
311 return bookmarkedheads
312
312
313 def checkheads(pushop):
313 def checkheads(pushop):
314 """Check that a push won't add any outgoing head
314 """Check that a push won't add any outgoing head
315
315
316 raise Abort error and display ui message as needed.
316 raise Abort error and display ui message as needed.
317 """
317 """
318
318
319 repo = pushop.repo.unfiltered()
319 repo = pushop.repo.unfiltered()
320 remote = pushop.remote
320 remote = pushop.remote
321 outgoing = pushop.outgoing
321 outgoing = pushop.outgoing
322 remoteheads = pushop.remoteheads
322 remoteheads = pushop.remoteheads
323 newbranch = pushop.newbranch
323 newbranch = pushop.newbranch
324 inc = bool(pushop.incoming)
324 inc = bool(pushop.incoming)
325
325
326 # Check for each named branch if we're creating new remote heads.
326 # Check for each named branch if we're creating new remote heads.
327 # To be a remote head after push, node must be either:
327 # To be a remote head after push, node must be either:
328 # - unknown locally
328 # - unknown locally
329 # - a local outgoing head descended from update
329 # - a local outgoing head descended from update
330 # - a remote head that's known locally and not
330 # - a remote head that's known locally and not
331 # ancestral to an outgoing head
331 # ancestral to an outgoing head
332 if remoteheads == [nullid]:
332 if remoteheads == [nullid]:
333 # remote is empty, nothing to check.
333 # remote is empty, nothing to check.
334 return
334 return
335
335
336 if remote.capable('branchmap'):
336 if remote.capable('branchmap'):
337 headssum = _headssummary(pushop)
337 headssum = _headssummary(pushop)
338 else:
338 else:
339 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
339 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
340 pushop.pushbranchmap = headssum
340 pushop.pushbranchmap = headssum
341 newbranches = [branch for branch, heads in headssum.iteritems()
341 newbranches = [branch for branch, heads in headssum.iteritems()
342 if heads[0] is None]
342 if heads[0] is None]
343 # Makes a set of closed branches
344 closedbranches = set()
345 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
346 if isclosed:
347 closedbranches.add(tag)
348 closedbranches = (closedbranches & set(newbranches))
343 # 1. Check for new branches on the remote.
349 # 1. Check for new branches on the remote.
344 if newbranches and not newbranch: # new branch requires --new-branch
350 if newbranches and not newbranch: # new branch requires --new-branch
345 branchnames = ', '.join(sorted(newbranches))
351 branchnames = ', '.join(sorted(newbranches))
346 raise error.Abort(_("push creates new remote branches: %s!")
352 if closedbranches:
347 % branchnames,
353 errmsg = (_("push creates new remote branches: %s (%d closed)!")
348 hint=_("use 'hg push --new-branch' to create"
354 % (branchnames, len(closedbranches)))
349 " new remote branches"))
355 else:
356 errmsg = (_("push creates new remote branches: %s!")% branchnames)
357 hint=_("use 'hg push --new-branch' to create new remote branches")
358 raise error.Abort(errmsg, hint=hint)
350
359
351 # 2. Find heads that we need not warn about
360 # 2. Find heads that we need not warn about
352 nowarnheads = _nowarnheads(pushop)
361 nowarnheads = _nowarnheads(pushop)
353
362
354 # 3. Check for new heads.
363 # 3. Check for new heads.
355 # If there are more heads after the push than before, a suitable
364 # If there are more heads after the push than before, a suitable
356 # error message, depending on unsynced status, is displayed.
365 # error message, depending on unsynced status, is displayed.
357 errormsg = None
366 errormsg = None
358 for branch, heads in sorted(headssum.iteritems()):
367 for branch, heads in sorted(headssum.iteritems()):
359 remoteheads, newheads, unsyncedheads, discardedheads = heads
368 remoteheads, newheads, unsyncedheads, discardedheads = heads
360 # add unsynced data
369 # add unsynced data
361 if remoteheads is None:
370 if remoteheads is None:
362 oldhs = set()
371 oldhs = set()
363 else:
372 else:
364 oldhs = set(remoteheads)
373 oldhs = set(remoteheads)
365 oldhs.update(unsyncedheads)
374 oldhs.update(unsyncedheads)
366 dhs = None # delta heads, the new heads on branch
375 dhs = None # delta heads, the new heads on branch
367 newhs = set(newheads)
376 newhs = set(newheads)
368 newhs.update(unsyncedheads)
377 newhs.update(unsyncedheads)
369 if unsyncedheads:
378 if unsyncedheads:
370 if None in unsyncedheads:
379 if None in unsyncedheads:
371 # old remote, no heads data
380 # old remote, no heads data
372 heads = None
381 heads = None
373 else:
382 else:
374 heads = scmutil.nodesummaries(repo, unsyncedheads)
383 heads = scmutil.nodesummaries(repo, unsyncedheads)
375 if heads is None:
384 if heads is None:
376 repo.ui.status(_("remote has heads that are "
385 repo.ui.status(_("remote has heads that are "
377 "not known locally\n"))
386 "not known locally\n"))
378 elif branch is None:
387 elif branch is None:
379 repo.ui.status(_("remote has heads that are "
388 repo.ui.status(_("remote has heads that are "
380 "not known locally: %s\n") % heads)
389 "not known locally: %s\n") % heads)
381 else:
390 else:
382 repo.ui.status(_("remote has heads on branch '%s' that are "
391 repo.ui.status(_("remote has heads on branch '%s' that are "
383 "not known locally: %s\n") % (branch, heads))
392 "not known locally: %s\n") % (branch, heads))
384 if remoteheads is None:
393 if remoteheads is None:
385 if len(newhs) > 1:
394 if len(newhs) > 1:
386 dhs = list(newhs)
395 dhs = list(newhs)
387 if errormsg is None:
396 if errormsg is None:
388 errormsg = (_("push creates new branch '%s' "
397 errormsg = (_("push creates new branch '%s' "
389 "with multiple heads") % (branch))
398 "with multiple heads") % (branch))
390 hint = _("merge or"
399 hint = _("merge or"
391 " see 'hg help push' for details about"
400 " see 'hg help push' for details about"
392 " pushing new heads")
401 " pushing new heads")
393 elif len(newhs) > len(oldhs):
402 elif len(newhs) > len(oldhs):
394 # remove bookmarked or existing remote heads from the new heads list
403 # remove bookmarked or existing remote heads from the new heads list
395 dhs = sorted(newhs - nowarnheads - oldhs)
404 dhs = sorted(newhs - nowarnheads - oldhs)
396 if dhs:
405 if dhs:
397 if errormsg is None:
406 if errormsg is None:
398 if branch not in ('default', None):
407 if branch not in ('default', None):
399 errormsg = _("push creates new remote head %s "
408 errormsg = _("push creates new remote head %s "
400 "on branch '%s'!") % (short(dhs[0]), branch)
409 "on branch '%s'!") % (short(dhs[0]), branch)
401 elif repo[dhs[0]].bookmarks():
410 elif repo[dhs[0]].bookmarks():
402 errormsg = _("push creates new remote head %s "
411 errormsg = _("push creates new remote head %s "
403 "with bookmark '%s'!") % (
412 "with bookmark '%s'!") % (
404 short(dhs[0]), repo[dhs[0]].bookmarks()[0])
413 short(dhs[0]), repo[dhs[0]].bookmarks()[0])
405 else:
414 else:
406 errormsg = _("push creates new remote head %s!"
415 errormsg = _("push creates new remote head %s!"
407 ) % short(dhs[0])
416 ) % short(dhs[0])
408 if unsyncedheads:
417 if unsyncedheads:
409 hint = _("pull and merge or"
418 hint = _("pull and merge or"
410 " see 'hg help push' for details about"
419 " see 'hg help push' for details about"
411 " pushing new heads")
420 " pushing new heads")
412 else:
421 else:
413 hint = _("merge or"
422 hint = _("merge or"
414 " see 'hg help push' for details about"
423 " see 'hg help push' for details about"
415 " pushing new heads")
424 " pushing new heads")
416 if branch is None:
425 if branch is None:
417 repo.ui.note(_("new remote heads:\n"))
426 repo.ui.note(_("new remote heads:\n"))
418 else:
427 else:
419 repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
428 repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
420 for h in dhs:
429 for h in dhs:
421 repo.ui.note((" %s\n") % short(h))
430 repo.ui.note((" %s\n") % short(h))
422 if errormsg:
431 if errormsg:
423 raise error.Abort(errormsg, hint=hint)
432 raise error.Abort(errormsg, hint=hint)
424
433
425 def _postprocessobsolete(pushop, futurecommon, candidate_newhs):
434 def _postprocessobsolete(pushop, futurecommon, candidate_newhs):
426 """post process the list of new heads with obsolescence information
435 """post process the list of new heads with obsolescence information
427
436
428 Exists as a sub-function to contain the complexity and allow extensions to
437 Exists as a sub-function to contain the complexity and allow extensions to
429 experiment with smarter logic.
438 experiment with smarter logic.
430
439
431 Returns (newheads, discarded_heads) tuple
440 Returns (newheads, discarded_heads) tuple
432 """
441 """
433 # known issue
442 # known issue
434 #
443 #
435 # * We "silently" skip processing on all changeset unknown locally
444 # * We "silently" skip processing on all changeset unknown locally
436 #
445 #
437 # * if <nh> is public on the remote, it won't be affected by obsolete
446 # * if <nh> is public on the remote, it won't be affected by obsolete
438 # marker and a new is created
447 # marker and a new is created
439
448
440 # define various utilities and containers
449 # define various utilities and containers
441 repo = pushop.repo
450 repo = pushop.repo
442 unfi = repo.unfiltered()
451 unfi = repo.unfiltered()
443 tonode = unfi.changelog.node
452 tonode = unfi.changelog.node
444 torev = unfi.changelog.nodemap.get
453 torev = unfi.changelog.nodemap.get
445 public = phases.public
454 public = phases.public
446 getphase = unfi._phasecache.phase
455 getphase = unfi._phasecache.phase
447 ispublic = (lambda r: getphase(unfi, r) == public)
456 ispublic = (lambda r: getphase(unfi, r) == public)
448 ispushed = (lambda n: torev(n) in futurecommon)
457 ispushed = (lambda n: torev(n) in futurecommon)
449 hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, ispushed)
458 hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, ispushed)
450 successorsmarkers = unfi.obsstore.successors
459 successorsmarkers = unfi.obsstore.successors
451 newhs = set() # final set of new heads
460 newhs = set() # final set of new heads
452 discarded = set() # new head of fully replaced branch
461 discarded = set() # new head of fully replaced branch
453
462
454 localcandidate = set() # candidate heads known locally
463 localcandidate = set() # candidate heads known locally
455 unknownheads = set() # candidate heads unknown locally
464 unknownheads = set() # candidate heads unknown locally
456 for h in candidate_newhs:
465 for h in candidate_newhs:
457 if h in unfi:
466 if h in unfi:
458 localcandidate.add(h)
467 localcandidate.add(h)
459 else:
468 else:
460 if successorsmarkers.get(h) is not None:
469 if successorsmarkers.get(h) is not None:
461 msg = ('checkheads: remote head unknown locally has'
470 msg = ('checkheads: remote head unknown locally has'
462 ' local marker: %s\n')
471 ' local marker: %s\n')
463 repo.ui.debug(msg % hex(h))
472 repo.ui.debug(msg % hex(h))
464 unknownheads.add(h)
473 unknownheads.add(h)
465
474
466 # fast path the simple case
475 # fast path the simple case
467 if len(localcandidate) == 1:
476 if len(localcandidate) == 1:
468 return unknownheads | set(candidate_newhs), set()
477 return unknownheads | set(candidate_newhs), set()
469
478
470 # actually process branch replacement
479 # actually process branch replacement
471 while localcandidate:
480 while localcandidate:
472 nh = localcandidate.pop()
481 nh = localcandidate.pop()
473 # run this check early to skip the evaluation of the whole branch
482 # run this check early to skip the evaluation of the whole branch
474 if (torev(nh) in futurecommon or ispublic(torev(nh))):
483 if (torev(nh) in futurecommon or ispublic(torev(nh))):
475 newhs.add(nh)
484 newhs.add(nh)
476 continue
485 continue
477
486
478 # Get all revs/nodes on the branch exclusive to this head
487 # Get all revs/nodes on the branch exclusive to this head
479 # (already filtered heads are "ignored"))
488 # (already filtered heads are "ignored"))
480 branchrevs = unfi.revs('only(%n, (%ln+%ln))',
489 branchrevs = unfi.revs('only(%n, (%ln+%ln))',
481 nh, localcandidate, newhs)
490 nh, localcandidate, newhs)
482 branchnodes = [tonode(r) for r in branchrevs]
491 branchnodes = [tonode(r) for r in branchrevs]
483
492
484 # The branch won't be hidden on the remote if
493 # The branch won't be hidden on the remote if
485 # * any part of it is public,
494 # * any part of it is public,
486 # * any part of it is considered part of the result by previous logic,
495 # * any part of it is considered part of the result by previous logic,
487 # * if we have no markers to push to obsolete it.
496 # * if we have no markers to push to obsolete it.
488 if (any(ispublic(r) for r in branchrevs)
497 if (any(ispublic(r) for r in branchrevs)
489 or any(torev(n) in futurecommon for n in branchnodes)
498 or any(torev(n) in futurecommon for n in branchnodes)
490 or any(not hasoutmarker(n) for n in branchnodes)):
499 or any(not hasoutmarker(n) for n in branchnodes)):
491 newhs.add(nh)
500 newhs.add(nh)
492 else:
501 else:
493 # note: there is a corner case if there is a merge in the branch.
502 # note: there is a corner case if there is a merge in the branch.
494 # we might end up with -more- heads. However, these heads are not
503 # we might end up with -more- heads. However, these heads are not
495 # "added" by the push, but more by the "removal" on the remote so I
504 # "added" by the push, but more by the "removal" on the remote so I
496 # think is a okay to ignore them,
505 # think is a okay to ignore them,
497 discarded.add(nh)
506 discarded.add(nh)
498 newhs |= unknownheads
507 newhs |= unknownheads
499 return newhs, discarded
508 return newhs, discarded
500
509
501 def pushingmarkerfor(obsstore, ispushed, node):
510 def pushingmarkerfor(obsstore, ispushed, node):
502 """true if some markers are to be pushed for node
511 """true if some markers are to be pushed for node
503
512
504 We cannot just look in to the pushed obsmarkers from the pushop because
513 We cannot just look in to the pushed obsmarkers from the pushop because
505 discovery might have filtered relevant markers. In addition listing all
514 discovery might have filtered relevant markers. In addition listing all
506 markers relevant to all changesets in the pushed set would be too expensive
515 markers relevant to all changesets in the pushed set would be too expensive
507 (O(len(repo)))
516 (O(len(repo)))
508
517
509 (note: There are cache opportunity in this function. but it would requires
518 (note: There are cache opportunity in this function. but it would requires
510 a two dimensional stack.)
519 a two dimensional stack.)
511 """
520 """
512 successorsmarkers = obsstore.successors
521 successorsmarkers = obsstore.successors
513 stack = [node]
522 stack = [node]
514 seen = set(stack)
523 seen = set(stack)
515 while stack:
524 while stack:
516 current = stack.pop()
525 current = stack.pop()
517 if ispushed(current):
526 if ispushed(current):
518 return True
527 return True
519 markers = successorsmarkers.get(current, ())
528 markers = successorsmarkers.get(current, ())
520 # markers fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents')
529 # markers fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents')
521 for m in markers:
530 for m in markers:
522 nexts = m[1] # successors
531 nexts = m[1] # successors
523 if not nexts: # this is a prune marker
532 if not nexts: # this is a prune marker
524 nexts = m[5] or () # parents
533 nexts = m[5] or () # parents
525 for n in nexts:
534 for n in nexts:
526 if n not in seen:
535 if n not in seen:
527 seen.add(n)
536 seen.add(n)
528 stack.append(n)
537 stack.append(n)
529 return False
538 return False
@@ -1,793 +1,847 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo foo > t1
3 $ echo foo > t1
4 $ hg add t1
4 $ hg add t1
5 $ hg commit -m "1"
5 $ hg commit -m "1"
6
6
7 $ cd ..
7 $ cd ..
8 $ hg clone a b
8 $ hg clone a b
9 updating to branch default
9 updating to branch default
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11
11
12 $ cd a
12 $ cd a
13 $ echo foo > t2
13 $ echo foo > t2
14 $ hg add t2
14 $ hg add t2
15 $ hg commit -m "2"
15 $ hg commit -m "2"
16
16
17 $ cd ../b
17 $ cd ../b
18 $ echo foo > t3
18 $ echo foo > t3
19 $ hg add t3
19 $ hg add t3
20 $ hg commit -m "3"
20 $ hg commit -m "3"
21
21
22 Specifying a revset that evaluates to null will abort
22 Specifying a revset that evaluates to null will abort
23
23
24 $ hg push -r '0 & 1' ../a
24 $ hg push -r '0 & 1' ../a
25 pushing to ../a
25 pushing to ../a
26 abort: specified revisions evaluate to an empty set
26 abort: specified revisions evaluate to an empty set
27 (use different revision arguments)
27 (use different revision arguments)
28 [255]
28 [255]
29
29
30 $ hg push ../a
30 $ hg push ../a
31 pushing to ../a
31 pushing to ../a
32 searching for changes
32 searching for changes
33 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
33 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
34 abort: push creates new remote head 1e108cc5548c!
34 abort: push creates new remote head 1e108cc5548c!
35 (pull and merge or see 'hg help push' for details about pushing new heads)
35 (pull and merge or see 'hg help push' for details about pushing new heads)
36 [255]
36 [255]
37
37
38 $ hg push --debug ../a
38 $ hg push --debug ../a
39 pushing to ../a
39 pushing to ../a
40 query 1; heads
40 query 1; heads
41 searching for changes
41 searching for changes
42 taking quick initial sample
42 taking quick initial sample
43 query 2; still undecided: 1, sample size is: 1
43 query 2; still undecided: 1, sample size is: 1
44 2 total queries in *.????s (glob)
44 2 total queries in *.????s (glob)
45 listing keys for "phases"
45 listing keys for "phases"
46 checking for updated bookmarks
46 checking for updated bookmarks
47 listing keys for "bookmarks"
47 listing keys for "bookmarks"
48 listing keys for "bookmarks"
48 listing keys for "bookmarks"
49 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
49 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
50 new remote heads on branch 'default':
50 new remote heads on branch 'default':
51 1e108cc5548c
51 1e108cc5548c
52 abort: push creates new remote head 1e108cc5548c!
52 abort: push creates new remote head 1e108cc5548c!
53 (pull and merge or see 'hg help push' for details about pushing new heads)
53 (pull and merge or see 'hg help push' for details about pushing new heads)
54 [255]
54 [255]
55
55
56 $ hg pull ../a
56 $ hg pull ../a
57 pulling from ../a
57 pulling from ../a
58 searching for changes
58 searching for changes
59 adding changesets
59 adding changesets
60 adding manifests
60 adding manifests
61 adding file changes
61 adding file changes
62 added 1 changesets with 1 changes to 1 files (+1 heads)
62 added 1 changesets with 1 changes to 1 files (+1 heads)
63 new changesets 1c9246a22a0a
63 new changesets 1c9246a22a0a
64 (run 'hg heads' to see heads, 'hg merge' to merge)
64 (run 'hg heads' to see heads, 'hg merge' to merge)
65
65
66 $ hg push ../a
66 $ hg push ../a
67 pushing to ../a
67 pushing to ../a
68 searching for changes
68 searching for changes
69 abort: push creates new remote head 1e108cc5548c!
69 abort: push creates new remote head 1e108cc5548c!
70 (merge or see 'hg help push' for details about pushing new heads)
70 (merge or see 'hg help push' for details about pushing new heads)
71 [255]
71 [255]
72
72
73 $ hg merge
73 $ hg merge
74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 (branch merge, don't forget to commit)
75 (branch merge, don't forget to commit)
76
76
77 $ hg commit -m "4"
77 $ hg commit -m "4"
78 $ hg push ../a
78 $ hg push ../a
79 pushing to ../a
79 pushing to ../a
80 searching for changes
80 searching for changes
81 adding changesets
81 adding changesets
82 adding manifests
82 adding manifests
83 adding file changes
83 adding file changes
84 added 2 changesets with 1 changes to 1 files
84 added 2 changesets with 1 changes to 1 files
85
85
86 $ cd ..
86 $ cd ..
87
87
88 $ hg init c
88 $ hg init c
89 $ cd c
89 $ cd c
90 $ for i in 0 1 2; do
90 $ for i in 0 1 2; do
91 > echo $i >> foo
91 > echo $i >> foo
92 > hg ci -Am $i
92 > hg ci -Am $i
93 > done
93 > done
94 adding foo
94 adding foo
95 $ cd ..
95 $ cd ..
96
96
97 $ hg clone c d
97 $ hg clone c d
98 updating to branch default
98 updating to branch default
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100
100
101 $ cd d
101 $ cd d
102 $ for i in 0 1; do
102 $ for i in 0 1; do
103 > hg co -C $i
103 > hg co -C $i
104 > echo d-$i >> foo
104 > echo d-$i >> foo
105 > hg ci -m d-$i
105 > hg ci -m d-$i
106 > done
106 > done
107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 created new head
108 created new head
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 created new head
110 created new head
111
111
112 $ HGMERGE=true hg merge 3
112 $ HGMERGE=true hg merge 3
113 merging foo
113 merging foo
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
115 (branch merge, don't forget to commit)
115 (branch merge, don't forget to commit)
116
116
117 $ hg ci -m c-d
117 $ hg ci -m c-d
118
118
119 $ hg push ../c
119 $ hg push ../c
120 pushing to ../c
120 pushing to ../c
121 searching for changes
121 searching for changes
122 abort: push creates new remote head 6346d66eb9f5!
122 abort: push creates new remote head 6346d66eb9f5!
123 (merge or see 'hg help push' for details about pushing new heads)
123 (merge or see 'hg help push' for details about pushing new heads)
124 [255]
124 [255]
125
125
126 $ hg push -r 2 ../c
126 $ hg push -r 2 ../c
127 pushing to ../c
127 pushing to ../c
128 searching for changes
128 searching for changes
129 no changes found
129 no changes found
130 [1]
130 [1]
131
131
132 $ hg push -r 3 ../c
132 $ hg push -r 3 ../c
133 pushing to ../c
133 pushing to ../c
134 searching for changes
134 searching for changes
135 abort: push creates new remote head a5dda829a167!
135 abort: push creates new remote head a5dda829a167!
136 (merge or see 'hg help push' for details about pushing new heads)
136 (merge or see 'hg help push' for details about pushing new heads)
137 [255]
137 [255]
138
138
139 $ hg push -v -r 3 -r 4 ../c
139 $ hg push -v -r 3 -r 4 ../c
140 pushing to ../c
140 pushing to ../c
141 searching for changes
141 searching for changes
142 new remote heads on branch 'default':
142 new remote heads on branch 'default':
143 a5dda829a167
143 a5dda829a167
144 ee8fbc7a0295
144 ee8fbc7a0295
145 abort: push creates new remote head a5dda829a167!
145 abort: push creates new remote head a5dda829a167!
146 (merge or see 'hg help push' for details about pushing new heads)
146 (merge or see 'hg help push' for details about pushing new heads)
147 [255]
147 [255]
148
148
149 $ hg push -v -f -r 3 -r 4 ../c
149 $ hg push -v -f -r 3 -r 4 ../c
150 pushing to ../c
150 pushing to ../c
151 searching for changes
151 searching for changes
152 2 changesets found
152 2 changesets found
153 uncompressed size of bundle content:
153 uncompressed size of bundle content:
154 352 (changelog)
154 352 (changelog)
155 326 (manifests)
155 326 (manifests)
156 25\d foo (re)
156 25\d foo (re)
157 adding changesets
157 adding changesets
158 adding manifests
158 adding manifests
159 adding file changes
159 adding file changes
160 added 2 changesets with 2 changes to 1 files (+2 heads)
160 added 2 changesets with 2 changes to 1 files (+2 heads)
161
161
162 $ hg push -r 5 ../c
162 $ hg push -r 5 ../c
163 pushing to ../c
163 pushing to ../c
164 searching for changes
164 searching for changes
165 adding changesets
165 adding changesets
166 adding manifests
166 adding manifests
167 adding file changes
167 adding file changes
168 added 1 changesets with 1 changes to 1 files (-1 heads)
168 added 1 changesets with 1 changes to 1 files (-1 heads)
169
169
170 $ hg in ../c
170 $ hg in ../c
171 comparing with ../c
171 comparing with ../c
172 searching for changes
172 searching for changes
173 no changes found
173 no changes found
174 [1]
174 [1]
175
175
176
176
177 Issue450: push -r warns about remote head creation even if no heads
177 Issue450: push -r warns about remote head creation even if no heads
178 will be created
178 will be created
179
179
180 $ hg init ../e
180 $ hg init ../e
181 $ hg push -r 0 ../e
181 $ hg push -r 0 ../e
182 pushing to ../e
182 pushing to ../e
183 searching for changes
183 searching for changes
184 adding changesets
184 adding changesets
185 adding manifests
185 adding manifests
186 adding file changes
186 adding file changes
187 added 1 changesets with 1 changes to 1 files
187 added 1 changesets with 1 changes to 1 files
188
188
189 $ hg push -r 1 ../e
189 $ hg push -r 1 ../e
190 pushing to ../e
190 pushing to ../e
191 searching for changes
191 searching for changes
192 adding changesets
192 adding changesets
193 adding manifests
193 adding manifests
194 adding file changes
194 adding file changes
195 added 1 changesets with 1 changes to 1 files
195 added 1 changesets with 1 changes to 1 files
196
196
197 $ cd ..
197 $ cd ..
198
198
199
199
200 Issue736: named branches are not considered for detection of
200 Issue736: named branches are not considered for detection of
201 unmerged heads in "hg push"
201 unmerged heads in "hg push"
202
202
203 $ hg init f
203 $ hg init f
204 $ cd f
204 $ cd f
205 $ hg -q branch a
205 $ hg -q branch a
206 $ echo 0 > foo
206 $ echo 0 > foo
207 $ hg -q ci -Am 0
207 $ hg -q ci -Am 0
208 $ echo 1 > foo
208 $ echo 1 > foo
209 $ hg -q ci -m 1
209 $ hg -q ci -m 1
210 $ hg -q up 0
210 $ hg -q up 0
211 $ echo 2 > foo
211 $ echo 2 > foo
212 $ hg -q ci -m 2
212 $ hg -q ci -m 2
213 $ hg -q up 0
213 $ hg -q up 0
214 $ hg -q branch b
214 $ hg -q branch b
215 $ echo 3 > foo
215 $ echo 3 > foo
216 $ hg -q ci -m 3
216 $ hg -q ci -m 3
217 $ cd ..
217 $ cd ..
218
218
219 $ hg -q clone f g
219 $ hg -q clone f g
220 $ cd g
220 $ cd g
221
221
222 Push on existing branch and new branch:
222 Push on existing branch and new branch:
223
223
224 $ hg -q up 1
224 $ hg -q up 1
225 $ echo 4 > foo
225 $ echo 4 > foo
226 $ hg -q ci -m 4
226 $ hg -q ci -m 4
227 $ hg -q up 0
227 $ hg -q up 0
228 $ echo 5 > foo
228 $ echo 5 > foo
229 $ hg -q branch c
229 $ hg -q branch c
230 $ hg -q ci -m 5
230 $ hg -q ci -m 5
231
231
232 $ hg push ../f
232 $ hg push ../f
233 pushing to ../f
233 pushing to ../f
234 searching for changes
234 searching for changes
235 abort: push creates new remote branches: c!
235 abort: push creates new remote branches: c!
236 (use 'hg push --new-branch' to create new remote branches)
236 (use 'hg push --new-branch' to create new remote branches)
237 [255]
237 [255]
238
238
239 $ hg push -r 4 -r 5 ../f
239 $ hg push -r 4 -r 5 ../f
240 pushing to ../f
240 pushing to ../f
241 searching for changes
241 searching for changes
242 abort: push creates new remote branches: c!
242 abort: push creates new remote branches: c!
243 (use 'hg push --new-branch' to create new remote branches)
243 (use 'hg push --new-branch' to create new remote branches)
244 [255]
244 [255]
245
245
246
246
247 Multiple new branches:
247 Multiple new branches:
248
248
249 $ hg -q branch d
249 $ hg -q branch d
250 $ echo 6 > foo
250 $ echo 6 > foo
251 $ hg -q ci -m 6
251 $ hg -q ci -m 6
252
252
253 $ hg push ../f
253 $ hg push ../f
254 pushing to ../f
254 pushing to ../f
255 searching for changes
255 searching for changes
256 abort: push creates new remote branches: c, d!
256 abort: push creates new remote branches: c, d!
257 (use 'hg push --new-branch' to create new remote branches)
257 (use 'hg push --new-branch' to create new remote branches)
258 [255]
258 [255]
259
259
260 $ hg push -r 4 -r 6 ../f
260 $ hg push -r 4 -r 6 ../f
261 pushing to ../f
261 pushing to ../f
262 searching for changes
262 searching for changes
263 abort: push creates new remote branches: c, d!
263 abort: push creates new remote branches: c, d!
264 (use 'hg push --new-branch' to create new remote branches)
264 (use 'hg push --new-branch' to create new remote branches)
265 [255]
265 [255]
266
266
267 $ cd ../g
267 $ cd ../g
268
268
269
269
270 Fail on multiple head push:
270 Fail on multiple head push:
271
271
272 $ hg -q up 1
272 $ hg -q up 1
273 $ echo 7 > foo
273 $ echo 7 > foo
274 $ hg -q ci -m 7
274 $ hg -q ci -m 7
275
275
276 $ hg push -r 4 -r 7 ../f
276 $ hg push -r 4 -r 7 ../f
277 pushing to ../f
277 pushing to ../f
278 searching for changes
278 searching for changes
279 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
279 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
280 (merge or see 'hg help push' for details about pushing new heads)
280 (merge or see 'hg help push' for details about pushing new heads)
281 [255]
281 [255]
282
282
283 Push replacement head on existing branches:
283 Push replacement head on existing branches:
284
284
285 $ hg -q up 3
285 $ hg -q up 3
286 $ echo 8 > foo
286 $ echo 8 > foo
287 $ hg -q ci -m 8
287 $ hg -q ci -m 8
288
288
289 $ hg push -r 7 -r 8 ../f
289 $ hg push -r 7 -r 8 ../f
290 pushing to ../f
290 pushing to ../f
291 searching for changes
291 searching for changes
292 adding changesets
292 adding changesets
293 adding manifests
293 adding manifests
294 adding file changes
294 adding file changes
295 added 2 changesets with 2 changes to 1 files
295 added 2 changesets with 2 changes to 1 files
296
296
297
297
298 Merge of branch a to other branch b followed by unrelated push
298 Merge of branch a to other branch b followed by unrelated push
299 on branch a:
299 on branch a:
300
300
301 $ hg -q up 7
301 $ hg -q up 7
302 $ HGMERGE=true hg -q merge 8
302 $ HGMERGE=true hg -q merge 8
303 $ hg -q ci -m 9
303 $ hg -q ci -m 9
304 $ hg -q up 8
304 $ hg -q up 8
305 $ echo 10 > foo
305 $ echo 10 > foo
306 $ hg -q ci -m 10
306 $ hg -q ci -m 10
307
307
308 $ hg push -r 9 ../f
308 $ hg push -r 9 ../f
309 pushing to ../f
309 pushing to ../f
310 searching for changes
310 searching for changes
311 adding changesets
311 adding changesets
312 adding manifests
312 adding manifests
313 adding file changes
313 adding file changes
314 added 1 changesets with 1 changes to 1 files (-1 heads)
314 added 1 changesets with 1 changes to 1 files (-1 heads)
315
315
316 $ hg push -r 10 ../f
316 $ hg push -r 10 ../f
317 pushing to ../f
317 pushing to ../f
318 searching for changes
318 searching for changes
319 adding changesets
319 adding changesets
320 adding manifests
320 adding manifests
321 adding file changes
321 adding file changes
322 added 1 changesets with 1 changes to 1 files (+1 heads)
322 added 1 changesets with 1 changes to 1 files (+1 heads)
323
323
324
324
325 Cheating the counting algorithm:
325 Cheating the counting algorithm:
326
326
327 $ hg -q up 9
327 $ hg -q up 9
328 $ HGMERGE=true hg -q merge 2
328 $ HGMERGE=true hg -q merge 2
329 $ hg -q ci -m 11
329 $ hg -q ci -m 11
330 $ hg -q up 1
330 $ hg -q up 1
331 $ echo 12 > foo
331 $ echo 12 > foo
332 $ hg -q ci -m 12
332 $ hg -q ci -m 12
333
333
334 $ hg push -r 11 -r 12 ../f
334 $ hg push -r 11 -r 12 ../f
335 pushing to ../f
335 pushing to ../f
336 searching for changes
336 searching for changes
337 adding changesets
337 adding changesets
338 adding manifests
338 adding manifests
339 adding file changes
339 adding file changes
340 added 2 changesets with 2 changes to 1 files
340 added 2 changesets with 2 changes to 1 files
341
341
342
342
343 Failed push of new named branch:
343 Failed push of new named branch:
344
344
345 $ echo 12 > foo
345 $ echo 12 > foo
346 $ hg -q ci -m 12a
346 $ hg -q ci -m 12a
347 [1]
347 [1]
348 $ hg -q up 11
348 $ hg -q up 11
349 $ echo 13 > foo
349 $ echo 13 > foo
350 $ hg -q branch e
350 $ hg -q branch e
351 $ hg -q ci -m 13d
351 $ hg -q ci -m 13d
352
352
353 $ hg push -r 12 -r 13 ../f
353 $ hg push -r 12 -r 13 ../f
354 pushing to ../f
354 pushing to ../f
355 searching for changes
355 searching for changes
356 abort: push creates new remote branches: e!
356 abort: push creates new remote branches: e!
357 (use 'hg push --new-branch' to create new remote branches)
357 (use 'hg push --new-branch' to create new remote branches)
358 [255]
358 [255]
359
359
360
360
361 Using --new-branch to push new named branch:
361 Using --new-branch to push new named branch:
362
362
363 $ hg push --new-branch -r 12 -r 13 ../f
363 $ hg push --new-branch -r 12 -r 13 ../f
364 pushing to ../f
364 pushing to ../f
365 searching for changes
365 searching for changes
366 adding changesets
366 adding changesets
367 adding manifests
367 adding manifests
368 adding file changes
368 adding file changes
369 added 1 changesets with 1 changes to 1 files
369 added 1 changesets with 1 changes to 1 files
370
370
371 Pushing multi headed new branch:
371 Pushing multi headed new branch:
372
372
373 $ echo 14 > foo
373 $ echo 14 > foo
374 $ hg -q branch f
374 $ hg -q branch f
375 $ hg -q ci -m 14
375 $ hg -q ci -m 14
376 $ echo 15 > foo
376 $ echo 15 > foo
377 $ hg -q ci -m 15
377 $ hg -q ci -m 15
378 $ hg -q up 14
378 $ hg -q up 14
379 $ echo 16 > foo
379 $ echo 16 > foo
380 $ hg -q ci -m 16
380 $ hg -q ci -m 16
381 $ hg push --branch f --new-branch ../f
381 $ hg push --branch f --new-branch ../f
382 pushing to ../f
382 pushing to ../f
383 searching for changes
383 searching for changes
384 abort: push creates new branch 'f' with multiple heads
384 abort: push creates new branch 'f' with multiple heads
385 (merge or see 'hg help push' for details about pushing new heads)
385 (merge or see 'hg help push' for details about pushing new heads)
386 [255]
386 [255]
387 $ hg push --branch f --new-branch --force ../f
387 $ hg push --branch f --new-branch --force ../f
388 pushing to ../f
388 pushing to ../f
389 searching for changes
389 searching for changes
390 adding changesets
390 adding changesets
391 adding manifests
391 adding manifests
392 adding file changes
392 adding file changes
393 added 3 changesets with 3 changes to 1 files (+1 heads)
393 added 3 changesets with 3 changes to 1 files (+1 heads)
394
394
395 Checking prepush logic does not allow silently pushing
395 Checking prepush logic does not allow silently pushing
396 multiple new heads but also doesn't report too many heads:
396 multiple new heads but also doesn't report too many heads:
397
397
398 $ cd ..
398 $ cd ..
399 $ hg init h
399 $ hg init h
400 $ echo init > h/init
400 $ echo init > h/init
401 $ hg -R h ci -Am init
401 $ hg -R h ci -Am init
402 adding init
402 adding init
403 $ echo a > h/a
403 $ echo a > h/a
404 $ hg -R h ci -Am a
404 $ hg -R h ci -Am a
405 adding a
405 adding a
406 $ hg clone h i
406 $ hg clone h i
407 updating to branch default
407 updating to branch default
408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 $ hg -R h up 0
409 $ hg -R h up 0
410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
411 $ echo b > h/b
411 $ echo b > h/b
412 $ hg -R h ci -Am b
412 $ hg -R h ci -Am b
413 adding b
413 adding b
414 created new head
414 created new head
415 $ hg -R i up 0
415 $ hg -R i up 0
416 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
417 $ echo c > i/c
417 $ echo c > i/c
418 $ hg -R i ci -Am c
418 $ hg -R i ci -Am c
419 adding c
419 adding c
420 created new head
420 created new head
421
421
422 $ for i in `"$PYTHON" $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
422 $ for i in `"$PYTHON" $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
423
423
424 $ hg -R i push h
424 $ hg -R i push h
425 pushing to h
425 pushing to h
426 searching for changes
426 searching for changes
427 remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
427 remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
428 abort: push creates new remote head 97bd0c84d346!
428 abort: push creates new remote head 97bd0c84d346!
429 (pull and merge or see 'hg help push' for details about pushing new heads)
429 (pull and merge or see 'hg help push' for details about pushing new heads)
430 [255]
430 [255]
431 $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx
431 $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx
432 $ hg -R i push h
432 $ hg -R i push h
433 pushing to h
433 pushing to h
434 searching for changes
434 searching for changes
435 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others
435 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others
436 abort: push creates new remote head 97bd0c84d346!
436 abort: push creates new remote head 97bd0c84d346!
437 (pull and merge or see 'hg help push' for details about pushing new heads)
437 (pull and merge or see 'hg help push' for details about pushing new heads)
438 [255]
438 [255]
439 $ hg -R i push h -v
439 $ hg -R i push h -v
440 pushing to h
440 pushing to h
441 searching for changes
441 searching for changes
442 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
442 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
443 new remote heads on branch 'default':
443 new remote heads on branch 'default':
444 97bd0c84d346
444 97bd0c84d346
445 abort: push creates new remote head 97bd0c84d346!
445 abort: push creates new remote head 97bd0c84d346!
446 (pull and merge or see 'hg help push' for details about pushing new heads)
446 (pull and merge or see 'hg help push' for details about pushing new heads)
447 [255]
447 [255]
448
448
449
449
450 Check prepush logic with merged branches:
450 Check prepush logic with merged branches:
451
451
452 $ hg init j
452 $ hg init j
453 $ hg -R j branch a
453 $ hg -R j branch a
454 marked working directory as branch a
454 marked working directory as branch a
455 (branches are permanent and global, did you want a bookmark?)
455 (branches are permanent and global, did you want a bookmark?)
456 $ echo init > j/foo
456 $ echo init > j/foo
457 $ hg -R j ci -Am init
457 $ hg -R j ci -Am init
458 adding foo
458 adding foo
459 $ hg clone j k
459 $ hg clone j k
460 updating to branch a
460 updating to branch a
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ echo a1 > j/foo
462 $ echo a1 > j/foo
463 $ hg -R j ci -m a1
463 $ hg -R j ci -m a1
464 $ hg -R k branch b
464 $ hg -R k branch b
465 marked working directory as branch b
465 marked working directory as branch b
466 $ echo b > k/foo
466 $ echo b > k/foo
467 $ hg -R k ci -m b
467 $ hg -R k ci -m b
468 $ hg -R k up 0
468 $ hg -R k up 0
469 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470
470
471 $ hg -R k merge b
471 $ hg -R k merge b
472 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 (branch merge, don't forget to commit)
473 (branch merge, don't forget to commit)
474
474
475 $ hg -R k ci -m merge
475 $ hg -R k ci -m merge
476
476
477 $ hg -R k push -r a j
477 $ hg -R k push -r a j
478 pushing to j
478 pushing to j
479 searching for changes
479 searching for changes
480 abort: push creates new remote branches: b!
480 abort: push creates new remote branches: b!
481 (use 'hg push --new-branch' to create new remote branches)
481 (use 'hg push --new-branch' to create new remote branches)
482 [255]
482 [255]
483
483
484
484
485 Prepush -r should not allow you to sneak in new heads:
485 Prepush -r should not allow you to sneak in new heads:
486
486
487 $ hg init l
487 $ hg init l
488 $ cd l
488 $ cd l
489 $ echo a >> foo
489 $ echo a >> foo
490 $ hg -q add foo
490 $ hg -q add foo
491 $ hg -q branch a
491 $ hg -q branch a
492 $ hg -q ci -ma
492 $ hg -q ci -ma
493 $ hg -q up null
493 $ hg -q up null
494 $ echo a >> foo
494 $ echo a >> foo
495 $ hg -q add foo
495 $ hg -q add foo
496 $ hg -q branch b
496 $ hg -q branch b
497 $ hg -q ci -mb
497 $ hg -q ci -mb
498 $ cd ..
498 $ cd ..
499 $ hg -q clone l m -u a
499 $ hg -q clone l m -u a
500 $ cd m
500 $ cd m
501 $ hg -q merge b
501 $ hg -q merge b
502 $ hg -q ci -mmb
502 $ hg -q ci -mmb
503 $ hg -q up 0
503 $ hg -q up 0
504 $ echo a >> foo
504 $ echo a >> foo
505 $ hg -q ci -ma2
505 $ hg -q ci -ma2
506 $ hg -q up 2
506 $ hg -q up 2
507 $ echo a >> foo
507 $ echo a >> foo
508 $ hg -q branch -f b
508 $ hg -q branch -f b
509 $ hg -q ci -mb2
509 $ hg -q ci -mb2
510 $ hg -q merge 3
510 $ hg -q merge 3
511 $ hg -q ci -mma
511 $ hg -q ci -mma
512
512
513 $ hg push ../l -b b
513 $ hg push ../l -b b
514 pushing to ../l
514 pushing to ../l
515 searching for changes
515 searching for changes
516 abort: push creates new remote head 451211cc22b0 on branch 'a'!
516 abort: push creates new remote head 451211cc22b0 on branch 'a'!
517 (merge or see 'hg help push' for details about pushing new heads)
517 (merge or see 'hg help push' for details about pushing new heads)
518 [255]
518 [255]
519
519
520 $ cd ..
520 $ cd ..
521
521
522
522
523 Check prepush with new branch head on former topo non-head:
523 Check prepush with new branch head on former topo non-head:
524
524
525 $ hg init n
525 $ hg init n
526 $ cd n
526 $ cd n
527 $ hg branch A
527 $ hg branch A
528 marked working directory as branch A
528 marked working directory as branch A
529 (branches are permanent and global, did you want a bookmark?)
529 (branches are permanent and global, did you want a bookmark?)
530 $ echo a >a
530 $ echo a >a
531 $ hg ci -Ama
531 $ hg ci -Ama
532 adding a
532 adding a
533 $ hg branch B
533 $ hg branch B
534 marked working directory as branch B
534 marked working directory as branch B
535 $ echo b >b
535 $ echo b >b
536 $ hg ci -Amb
536 $ hg ci -Amb
537 adding b
537 adding b
538
538
539 b is now branch head of B, and a topological head
539 b is now branch head of B, and a topological head
540 a is now branch head of A, but not a topological head
540 a is now branch head of A, but not a topological head
541
541
542 $ hg clone . inner
542 $ hg clone . inner
543 updating to branch B
543 updating to branch B
544 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
544 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 $ cd inner
545 $ cd inner
546 $ hg up B
546 $ hg up B
547 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
547 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 $ echo b1 >b1
548 $ echo b1 >b1
549 $ hg ci -Amb1
549 $ hg ci -Amb1
550 adding b1
550 adding b1
551
551
552 in the clone b1 is now the head of B
552 in the clone b1 is now the head of B
553
553
554 $ cd ..
554 $ cd ..
555 $ hg up 0
555 $ hg up 0
556 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
557 $ echo a2 >a2
557 $ echo a2 >a2
558 $ hg ci -Ama2
558 $ hg ci -Ama2
559 adding a2
559 adding a2
560
560
561 a2 is now the new branch head of A, and a new topological head
561 a2 is now the new branch head of A, and a new topological head
562 it replaces a former inner branch head, so it should at most warn about
562 it replaces a former inner branch head, so it should at most warn about
563 A, not B
563 A, not B
564
564
565 glog of local:
565 glog of local:
566
566
567 $ hg log -G --template "{rev}: {branches} {desc}\n"
567 $ hg log -G --template "{rev}: {branches} {desc}\n"
568 @ 2: A a2
568 @ 2: A a2
569 |
569 |
570 | o 1: B b
570 | o 1: B b
571 |/
571 |/
572 o 0: A a
572 o 0: A a
573
573
574 glog of remote:
574 glog of remote:
575
575
576 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
576 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
577 @ 2: B b1
577 @ 2: B b1
578 |
578 |
579 o 1: B b
579 o 1: B b
580 |
580 |
581 o 0: A a
581 o 0: A a
582
582
583 outgoing:
583 outgoing:
584
584
585 $ hg out inner --template "{rev}: {branches} {desc}\n"
585 $ hg out inner --template "{rev}: {branches} {desc}\n"
586 comparing with inner
586 comparing with inner
587 searching for changes
587 searching for changes
588 2: A a2
588 2: A a2
589
589
590 $ hg push inner
590 $ hg push inner
591 pushing to inner
591 pushing to inner
592 searching for changes
592 searching for changes
593 adding changesets
593 adding changesets
594 adding manifests
594 adding manifests
595 adding file changes
595 adding file changes
596 added 1 changesets with 1 changes to 1 files (+1 heads)
596 added 1 changesets with 1 changes to 1 files (+1 heads)
597
597
598 $ cd ..
598 $ cd ..
599
599
600
600
601 Check prepush with new branch head on former topo head:
601 Check prepush with new branch head on former topo head:
602
602
603 $ hg init o
603 $ hg init o
604 $ cd o
604 $ cd o
605 $ hg branch A
605 $ hg branch A
606 marked working directory as branch A
606 marked working directory as branch A
607 (branches are permanent and global, did you want a bookmark?)
607 (branches are permanent and global, did you want a bookmark?)
608 $ echo a >a
608 $ echo a >a
609 $ hg ci -Ama
609 $ hg ci -Ama
610 adding a
610 adding a
611 $ hg branch B
611 $ hg branch B
612 marked working directory as branch B
612 marked working directory as branch B
613 $ echo b >b
613 $ echo b >b
614 $ hg ci -Amb
614 $ hg ci -Amb
615 adding b
615 adding b
616
616
617 b is now branch head of B, and a topological head
617 b is now branch head of B, and a topological head
618
618
619 $ hg up 0
619 $ hg up 0
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 $ echo a1 >a1
621 $ echo a1 >a1
622 $ hg ci -Ama1
622 $ hg ci -Ama1
623 adding a1
623 adding a1
624
624
625 a1 is now branch head of A, and a topological head
625 a1 is now branch head of A, and a topological head
626
626
627 $ hg clone . inner
627 $ hg clone . inner
628 updating to branch A
628 updating to branch A
629 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
629 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
630 $ cd inner
630 $ cd inner
631 $ hg up B
631 $ hg up B
632 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
632 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
633 $ echo b1 >b1
633 $ echo b1 >b1
634 $ hg ci -Amb1
634 $ hg ci -Amb1
635 adding b1
635 adding b1
636
636
637 in the clone b1 is now the head of B
637 in the clone b1 is now the head of B
638
638
639 $ cd ..
639 $ cd ..
640 $ echo a2 >a2
640 $ echo a2 >a2
641 $ hg ci -Ama2
641 $ hg ci -Ama2
642 adding a2
642 adding a2
643
643
644 a2 is now the new branch head of A, and a topological head
644 a2 is now the new branch head of A, and a topological head
645 it replaces a former topological and branch head, so this should not warn
645 it replaces a former topological and branch head, so this should not warn
646
646
647 glog of local:
647 glog of local:
648
648
649 $ hg log -G --template "{rev}: {branches} {desc}\n"
649 $ hg log -G --template "{rev}: {branches} {desc}\n"
650 @ 3: A a2
650 @ 3: A a2
651 |
651 |
652 o 2: A a1
652 o 2: A a1
653 |
653 |
654 | o 1: B b
654 | o 1: B b
655 |/
655 |/
656 o 0: A a
656 o 0: A a
657
657
658 glog of remote:
658 glog of remote:
659
659
660 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
660 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
661 @ 3: B b1
661 @ 3: B b1
662 |
662 |
663 | o 2: A a1
663 | o 2: A a1
664 | |
664 | |
665 o | 1: B b
665 o | 1: B b
666 |/
666 |/
667 o 0: A a
667 o 0: A a
668
668
669 outgoing:
669 outgoing:
670
670
671 $ hg out inner --template "{rev}: {branches} {desc}\n"
671 $ hg out inner --template "{rev}: {branches} {desc}\n"
672 comparing with inner
672 comparing with inner
673 searching for changes
673 searching for changes
674 3: A a2
674 3: A a2
675
675
676 $ hg push inner
676 $ hg push inner
677 pushing to inner
677 pushing to inner
678 searching for changes
678 searching for changes
679 adding changesets
679 adding changesets
680 adding manifests
680 adding manifests
681 adding file changes
681 adding file changes
682 added 1 changesets with 1 changes to 1 files
682 added 1 changesets with 1 changes to 1 files
683
683
684 $ cd ..
684 $ cd ..
685
685
686
686
687 Check prepush with new branch head and new child of former branch head
687 Check prepush with new branch head and new child of former branch head
688 but child is on different branch:
688 but child is on different branch:
689
689
690 $ hg init p
690 $ hg init p
691 $ cd p
691 $ cd p
692 $ hg branch A
692 $ hg branch A
693 marked working directory as branch A
693 marked working directory as branch A
694 (branches are permanent and global, did you want a bookmark?)
694 (branches are permanent and global, did you want a bookmark?)
695 $ echo a0 >a
695 $ echo a0 >a
696 $ hg ci -Ama0
696 $ hg ci -Ama0
697 adding a
697 adding a
698 $ echo a1 >a
698 $ echo a1 >a
699 $ hg ci -ma1
699 $ hg ci -ma1
700 $ hg up null
700 $ hg up null
701 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
701 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
702 $ hg branch B
702 $ hg branch B
703 marked working directory as branch B
703 marked working directory as branch B
704 $ echo b0 >b
704 $ echo b0 >b
705 $ hg ci -Amb0
705 $ hg ci -Amb0
706 adding b
706 adding b
707 $ echo b1 >b
707 $ echo b1 >b
708 $ hg ci -mb1
708 $ hg ci -mb1
709
709
710 $ hg clone . inner
710 $ hg clone . inner
711 updating to branch B
711 updating to branch B
712 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
712 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
713
713
714 $ hg up A
714 $ hg up A
715 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
715 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
716 $ hg branch -f B
716 $ hg branch -f B
717 marked working directory as branch B
717 marked working directory as branch B
718 $ echo a3 >a
718 $ echo a3 >a
719 $ hg ci -ma3
719 $ hg ci -ma3
720 created new head
720 created new head
721 $ hg up 3
721 $ hg up 3
722 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
722 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
723 $ hg branch -f A
723 $ hg branch -f A
724 marked working directory as branch A
724 marked working directory as branch A
725 $ echo b3 >b
725 $ echo b3 >b
726 $ hg ci -mb3
726 $ hg ci -mb3
727 created new head
727 created new head
728
728
729 glog of local:
729 glog of local:
730
730
731 $ hg log -G --template "{rev}: {branches} {desc}\n"
731 $ hg log -G --template "{rev}: {branches} {desc}\n"
732 @ 5: A b3
732 @ 5: A b3
733 |
733 |
734 | o 4: B a3
734 | o 4: B a3
735 | |
735 | |
736 o | 3: B b1
736 o | 3: B b1
737 | |
737 | |
738 o | 2: B b0
738 o | 2: B b0
739 /
739 /
740 o 1: A a1
740 o 1: A a1
741 |
741 |
742 o 0: A a0
742 o 0: A a0
743
743
744 glog of remote:
744 glog of remote:
745
745
746 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
746 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
747 @ 3: B b1
747 @ 3: B b1
748 |
748 |
749 o 2: B b0
749 o 2: B b0
750
750
751 o 1: A a1
751 o 1: A a1
752 |
752 |
753 o 0: A a0
753 o 0: A a0
754
754
755 outgoing:
755 outgoing:
756
756
757 $ hg out inner --template "{rev}: {branches} {desc}\n"
757 $ hg out inner --template "{rev}: {branches} {desc}\n"
758 comparing with inner
758 comparing with inner
759 searching for changes
759 searching for changes
760 4: B a3
760 4: B a3
761 5: A b3
761 5: A b3
762
762
763 $ hg push inner
763 $ hg push inner
764 pushing to inner
764 pushing to inner
765 searching for changes
765 searching for changes
766 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
766 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
767 (merge or see 'hg help push' for details about pushing new heads)
767 (merge or see 'hg help push' for details about pushing new heads)
768 [255]
768 [255]
769
769
770 $ hg push inner -r4 -r5
770 $ hg push inner -r4 -r5
771 pushing to inner
771 pushing to inner
772 searching for changes
772 searching for changes
773 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
773 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
774 (merge or see 'hg help push' for details about pushing new heads)
774 (merge or see 'hg help push' for details about pushing new heads)
775 [255]
775 [255]
776
776
777 $ hg in inner
777 $ hg in inner
778 comparing with inner
778 comparing with inner
779 searching for changes
779 searching for changes
780 no changes found
780 no changes found
781 [1]
781 [1]
782
782
783 Test fail hook
783 Test fail hook
784
784
785 $ hg push inner --config hooks.fail-push="echo running fail-push hook"
785 $ hg push inner --config hooks.fail-push="echo running fail-push hook"
786 pushing to inner
786 pushing to inner
787 searching for changes
787 searching for changes
788 running fail-push hook
788 running fail-push hook
789 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
789 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
790 (merge or see 'hg help push' for details about pushing new heads)
790 (merge or see 'hg help push' for details about pushing new heads)
791 [255]
791 [255]
792
792
793 $ cd ..
793 $ cd ..
794
795 Test regarding pushing of closed branch/branches(Issue6080)
796
797 $ hg init x
798 $ cd x
799 $ hg -q branch a
800 $ echo 0 > foo
801 $ hg -q ci -Am 0
802 $ hg -q up 0
803 $ cd ..
804
805 $ hg -q clone x z
806 $ cd z
807
808 When there is a single closed branch
809
810 $ hg -q branch foo
811 $ echo 0 > foo
812 $ hg -q ci -Am 0
813 $ hg ci --close-branch -m 'closing branch foo'
814 $ hg -q up 0
815 $ hg push ../x
816 pushing to ../x
817 searching for changes
818 abort: push creates new remote branches: foo (1 closed)!
819 (use 'hg push --new-branch' to create new remote branches)
820 [255]
821
822 When there is more than one closed branches
823 $ hg -q branch bar
824 $ echo 0 > bar
825 $ hg -q ci -Am 0
826 $ hg ci --close-branch -m 'closing branch bar'
827 $ hg -q up 0
828 $ hg push ../x
829 pushing to ../x
830 searching for changes
831 abort: push creates new remote branches: bar, foo (2 closed)!
832 (use 'hg push --new-branch' to create new remote branches)
833 [255]
834
835 When there are more than one new branches and not all are closed
836 $ hg -q branch bar1
837 $ echo 0 > bar1
838 $ hg -q ci -Am 0
839 $ hg -q up 0
840 $ hg push ../x
841 pushing to ../x
842 searching for changes
843 abort: push creates new remote branches: bar, bar1, foo (2 closed)!
844 (use 'hg push --new-branch' to create new remote branches)
845 [255]
846
847 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now