##// END OF EJS Templates
discovery: process heads in sorted order
Mads Kiilerich -
r18361:06f07583 default
parent child Browse files
Show More
@@ -1,339 +1,339 b''
1 1 # discovery.py - protocol changeset discovery functions
2 2 #
3 3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import nullid, short
9 9 from i18n import _
10 10 import util, setdiscovery, treediscovery, phases, obsolete, bookmarks
11 11 import branchmap
12 12
13 13 def findcommonincoming(repo, remote, heads=None, force=False):
14 14 """Return a tuple (common, anyincoming, heads) used to identify the common
15 15 subset of nodes between repo and remote.
16 16
17 17 "common" is a list of (at least) the heads of the common subset.
18 18 "anyincoming" is testable as a boolean indicating if any nodes are missing
19 19 locally. If remote does not support getbundle, this actually is a list of
20 20 roots of the nodes that would be incoming, to be supplied to
21 21 changegroupsubset. No code except for pull should be relying on this fact
22 22 any longer.
23 23 "heads" is either the supplied heads, or else the remote's heads.
24 24
25 25 If you pass heads and they are all known locally, the response lists just
26 26 these heads in "common" and in "heads".
27 27
28 28 Please use findcommonoutgoing to compute the set of outgoing nodes to give
29 29 extensions a good hook into outgoing.
30 30 """
31 31
32 32 if not remote.capable('getbundle'):
33 33 return treediscovery.findcommonincoming(repo, remote, heads, force)
34 34
35 35 if heads:
36 36 allknown = True
37 37 nm = repo.changelog.nodemap
38 38 for h in heads:
39 39 if nm.get(h) is None:
40 40 allknown = False
41 41 break
42 42 if allknown:
43 43 return (heads, False, heads)
44 44
45 45 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
46 46 abortwhenunrelated=not force)
47 47 common, anyinc, srvheads = res
48 48 return (list(common), anyinc, heads or list(srvheads))
49 49
50 50 class outgoing(object):
51 51 '''Represents the set of nodes present in a local repo but not in a
52 52 (possibly) remote one.
53 53
54 54 Members:
55 55
56 56 missing is a list of all nodes present in local but not in remote.
57 57 common is a list of all nodes shared between the two repos.
58 58 excluded is the list of missing changeset that shouldn't be sent remotely.
59 59 missingheads is the list of heads of missing.
60 60 commonheads is the list of heads of common.
61 61
62 62 The sets are computed on demand from the heads, unless provided upfront
63 63 by discovery.'''
64 64
65 65 def __init__(self, revlog, commonheads, missingheads):
66 66 self.commonheads = commonheads
67 67 self.missingheads = missingheads
68 68 self._revlog = revlog
69 69 self._common = None
70 70 self._missing = None
71 71 self.excluded = []
72 72
73 73 def _computecommonmissing(self):
74 74 sets = self._revlog.findcommonmissing(self.commonheads,
75 75 self.missingheads)
76 76 self._common, self._missing = sets
77 77
78 78 @util.propertycache
79 79 def common(self):
80 80 if self._common is None:
81 81 self._computecommonmissing()
82 82 return self._common
83 83
84 84 @util.propertycache
85 85 def missing(self):
86 86 if self._missing is None:
87 87 self._computecommonmissing()
88 88 return self._missing
89 89
90 90 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
91 91 commoninc=None, portable=False):
92 92 '''Return an outgoing instance to identify the nodes present in repo but
93 93 not in other.
94 94
95 95 If onlyheads is given, only nodes ancestral to nodes in onlyheads
96 96 (inclusive) are included. If you already know the local repo's heads,
97 97 passing them in onlyheads is faster than letting them be recomputed here.
98 98
99 99 If commoninc is given, it must be the result of a prior call to
100 100 findcommonincoming(repo, other, force) to avoid recomputing it here.
101 101
102 102 If portable is given, compute more conservative common and missingheads,
103 103 to make bundles created from the instance more portable.'''
104 104 # declare an empty outgoing object to be filled later
105 105 og = outgoing(repo.changelog, None, None)
106 106
107 107 # get common set if not provided
108 108 if commoninc is None:
109 109 commoninc = findcommonincoming(repo, other, force=force)
110 110 og.commonheads, _any, _hds = commoninc
111 111
112 112 # compute outgoing
113 113 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
114 114 if not mayexclude:
115 115 og.missingheads = onlyheads or repo.heads()
116 116 elif onlyheads is None:
117 117 # use visible heads as it should be cached
118 118 og.missingheads = repo.filtered("unserved").heads()
119 119 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
120 120 else:
121 121 # compute common, missing and exclude secret stuff
122 122 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
123 123 og._common, allmissing = sets
124 124 og._missing = missing = []
125 125 og.excluded = excluded = []
126 126 for node in allmissing:
127 127 ctx = repo[node]
128 128 if ctx.phase() >= phases.secret or ctx.extinct():
129 129 excluded.append(node)
130 130 else:
131 131 missing.append(node)
132 132 if len(missing) == len(allmissing):
133 133 missingheads = onlyheads
134 134 else: # update missing heads
135 135 missingheads = phases.newheads(repo, onlyheads, excluded)
136 136 og.missingheads = missingheads
137 137 if portable:
138 138 # recompute common and missingheads as if -r<rev> had been given for
139 139 # each head of missing, and --base <rev> for each head of the proper
140 140 # ancestors of missing
141 141 og._computecommonmissing()
142 142 cl = repo.changelog
143 143 missingrevs = set(cl.rev(n) for n in og._missing)
144 144 og._common = set(cl.ancestors(missingrevs)) - missingrevs
145 145 commonheads = set(og.commonheads)
146 146 og.missingheads = [h for h in og.missingheads if h not in commonheads]
147 147
148 148 return og
149 149
150 150 def _headssummary(repo, remote, outgoing):
151 151 """compute a summary of branch and heads status before and after push
152 152
153 153 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping
154 154
155 155 - branch: the branch name
156 156 - remoteheads: the list of remote heads known locally
157 157 None is the branch is new
158 158 - newheads: the new remote heads (known locally) with outgoing pushed
159 159 - unsyncedheads: the list of remote heads unknown locally.
160 160 """
161 161 cl = repo.changelog
162 162 headssum = {}
163 163 # A. Create set of branches involved in the push.
164 164 branches = set(repo[n].branch() for n in outgoing.missing)
165 165 remotemap = remote.branchmap()
166 166 newbranches = branches - set(remotemap)
167 167 branches.difference_update(newbranches)
168 168
169 169 # A. register remote heads
170 170 remotebranches = set()
171 171 for branch, heads in remote.branchmap().iteritems():
172 172 remotebranches.add(branch)
173 173 known = []
174 174 unsynced = []
175 175 for h in heads:
176 176 if h in cl.nodemap:
177 177 known.append(h)
178 178 else:
179 179 unsynced.append(h)
180 180 headssum[branch] = (known, list(known), unsynced)
181 181 # B. add new branch data
182 182 missingctx = list(repo[n] for n in outgoing.missing)
183 183 touchedbranches = set()
184 184 for ctx in missingctx:
185 185 branch = ctx.branch()
186 186 touchedbranches.add(branch)
187 187 if branch not in headssum:
188 188 headssum[branch] = (None, [], [])
189 189
190 190 # C drop data about untouched branches:
191 191 for branch in remotebranches - touchedbranches:
192 192 del headssum[branch]
193 193
194 194 # D. Update newmap with outgoing changes.
195 195 # This will possibly add new heads and remove existing ones.
196 196 newmap = branchmap.branchcache((branch, heads[1])
197 197 for branch, heads in headssum.iteritems()
198 198 if heads[0] is not None)
199 199 newmap.update(repo, (ctx.rev() for ctx in missingctx))
200 200 for branch, newheads in newmap.iteritems():
201 201 headssum[branch][1][:] = newheads
202 202 return headssum
203 203
204 204 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
205 205 """Compute branchmapsummary for repo without branchmap support"""
206 206
207 207 cl = repo.changelog
208 208 # 1-4b. old servers: Check for new topological heads.
209 209 # Construct {old,new}map with branch = None (topological branch).
210 210 # (code based on update)
211 211 oldheads = set(h for h in remoteheads if h in cl.nodemap)
212 212 # all nodes in outgoing.missing are children of either:
213 213 # - an element of oldheads
214 214 # - another element of outgoing.missing
215 215 # - nullrev
216 216 # This explains why the new head are very simple to compute.
217 217 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
218 218 newheads = list(c.node() for c in r)
219 219 unsynced = inc and set([None]) or set()
220 220 return {None: (oldheads, newheads, unsynced)}
221 221
222 222 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
223 223 """Check that a push won't add any outgoing head
224 224
225 225 raise Abort error and display ui message as needed.
226 226 """
227 227 # Check for each named branch if we're creating new remote heads.
228 228 # To be a remote head after push, node must be either:
229 229 # - unknown locally
230 230 # - a local outgoing head descended from update
231 231 # - a remote head that's known locally and not
232 232 # ancestral to an outgoing head
233 233 if remoteheads == [nullid]:
234 234 # remote is empty, nothing to check.
235 235 return
236 236
237 237 if remote.capable('branchmap'):
238 238 headssum = _headssummary(repo, remote, outgoing)
239 239 else:
240 240 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
241 241 newbranches = [branch for branch, heads in headssum.iteritems()
242 242 if heads[0] is None]
243 243 # 1. Check for new branches on the remote.
244 244 if newbranches and not newbranch: # new branch requires --new-branch
245 245 branchnames = ', '.join(sorted(newbranches))
246 246 raise util.Abort(_("push creates new remote branches: %s!")
247 247 % branchnames,
248 248 hint=_("use 'hg push --new-branch' to create"
249 249 " new remote branches"))
250 250
251 251 # 2 compute newly pushed bookmarks. We
252 252 # we don't warned about bookmarked heads.
253 253 localbookmarks = repo._bookmarks
254 254 remotebookmarks = remote.listkeys('bookmarks')
255 255 bookmarkedheads = set()
256 256 for bm in localbookmarks:
257 257 rnode = remotebookmarks.get(bm)
258 258 if rnode and rnode in repo:
259 259 lctx, rctx = repo[bm], repo[rnode]
260 260 if bookmarks.validdest(repo, rctx, lctx):
261 261 bookmarkedheads.add(lctx.node())
262 262
263 263 # 3. Check for new heads.
264 264 # If there are more heads after the push than before, a suitable
265 265 # error message, depending on unsynced status, is displayed.
266 266 error = None
267 267 unsynced = False
268 268 allmissing = set(outgoing.missing)
269 269 allfuturecommon = set(c.node() for c in repo.set('%ld', outgoing.common))
270 270 allfuturecommon.update(allmissing)
271 for branch, heads in headssum.iteritems():
271 for branch, heads in sorted(headssum.iteritems()):
272 272 if heads[0] is None:
273 273 # Maybe we should abort if we push more that one head
274 274 # for new branches ?
275 275 continue
276 276 candidate_newhs = set(heads[1])
277 277 # add unsynced data
278 278 oldhs = set(heads[0])
279 279 oldhs.update(heads[2])
280 280 candidate_newhs.update(heads[2])
281 281 dhs = None
282 282 discardedheads = set()
283 283 if repo.obsstore:
284 284 # remove future heads which are actually obsolete by another
285 285 # pushed element:
286 286 #
287 287 # XXX as above, There are several cases this case does not handle
288 288 # XXX properly
289 289 #
290 290 # (1) if <nh> is public, it won't be affected by obsolete marker
291 291 # and a new is created
292 292 #
293 293 # (2) if the new heads have ancestors which are not obsolete and
294 294 # not ancestors of any other heads we will have a new head too.
295 295 #
296 296 # This two case will be easy to handle for know changeset but much
297 297 # more tricky for unsynced changes.
298 298 newhs = set()
299 299 for nh in candidate_newhs:
300 300 if nh in repo and repo[nh].phase() <= phases.public:
301 301 newhs.add(nh)
302 302 else:
303 303 for suc in obsolete.allsuccessors(repo.obsstore, [nh]):
304 304 if suc != nh and suc in allfuturecommon:
305 305 discardedheads.add(nh)
306 306 break
307 307 else:
308 308 newhs.add(nh)
309 309 else:
310 310 newhs = candidate_newhs
311 311 if [h for h in heads[2] if h not in discardedheads]:
312 312 unsynced = True
313 313 if len(newhs) > len(oldhs):
314 314 # strip updates to existing remote heads from the new heads list
315 dhs = list(newhs - bookmarkedheads - oldhs)
315 dhs = sorted(newhs - bookmarkedheads - oldhs)
316 316 if dhs:
317 317 if error is None:
318 318 if branch not in ('default', None):
319 319 error = _("push creates new remote head %s "
320 320 "on branch '%s'!") % (short(dhs[0]), branch)
321 321 else:
322 322 error = _("push creates new remote head %s!"
323 323 ) % short(dhs[0])
324 324 if heads[2]: # unsynced
325 325 hint = _("you should pull and merge or "
326 326 "use push -f to force")
327 327 else:
328 328 hint = _("did you forget to merge? "
329 329 "use push -f to force")
330 330 if branch is not None:
331 331 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
332 332 for h in dhs:
333 333 repo.ui.note(_("new remote head %s\n") % short(h))
334 334 if error:
335 335 raise util.Abort(error, hint=hint)
336 336
337 337 # 6. Check for unsynced changes on involved branches.
338 338 if unsynced:
339 339 repo.ui.warn(_("note: unsynced remote changes!\n"))
@@ -1,732 +1,732 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "graphlog=" >> $HGRCPATH
3 3
4 4 $ hg init a
5 5 $ cd a
6 6 $ echo foo > t1
7 7 $ hg add t1
8 8 $ hg commit -m "1"
9 9
10 10 $ cd ..
11 11 $ hg clone a b
12 12 updating to branch default
13 13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14
15 15 $ cd a
16 16 $ echo foo > t2
17 17 $ hg add t2
18 18 $ hg commit -m "2"
19 19
20 20 $ cd ../b
21 21 $ echo foo > t3
22 22 $ hg add t3
23 23 $ hg commit -m "3"
24 24
25 25 $ hg push ../a
26 26 pushing to ../a
27 27 searching for changes
28 28 abort: push creates new remote head 1e108cc5548c!
29 29 (you should pull and merge or use push -f to force)
30 30 [255]
31 31
32 32 $ hg push --debug ../a
33 33 pushing to ../a
34 34 query 1; heads
35 35 searching for changes
36 36 taking quick initial sample
37 37 searching: 2 queries
38 38 query 2; still undecided: 1, sample size is: 1
39 39 2 total queries
40 40 listing keys for "bookmarks"
41 41 new remote heads on branch 'default'
42 42 new remote head 1e108cc5548c
43 43 abort: push creates new remote head 1e108cc5548c!
44 44 (you should pull and merge or use push -f to force)
45 45 [255]
46 46
47 47 $ hg pull ../a
48 48 pulling from ../a
49 49 searching for changes
50 50 adding changesets
51 51 adding manifests
52 52 adding file changes
53 53 added 1 changesets with 1 changes to 1 files (+1 heads)
54 54 (run 'hg heads' to see heads, 'hg merge' to merge)
55 55
56 56 $ hg push ../a
57 57 pushing to ../a
58 58 searching for changes
59 59 abort: push creates new remote head 1e108cc5548c!
60 60 (did you forget to merge? use push -f to force)
61 61 [255]
62 62
63 63 $ hg merge
64 64 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
65 65 (branch merge, don't forget to commit)
66 66
67 67 $ hg commit -m "4"
68 68 $ hg push ../a
69 69 pushing to ../a
70 70 searching for changes
71 71 adding changesets
72 72 adding manifests
73 73 adding file changes
74 74 added 2 changesets with 1 changes to 1 files
75 75
76 76 $ cd ..
77 77
78 78 $ hg init c
79 79 $ cd c
80 80 $ for i in 0 1 2; do
81 81 > echo $i >> foo
82 82 > hg ci -Am $i
83 83 > done
84 84 adding foo
85 85 $ cd ..
86 86
87 87 $ hg clone c d
88 88 updating to branch default
89 89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 90
91 91 $ cd d
92 92 $ for i in 0 1; do
93 93 > hg co -C $i
94 94 > echo d-$i >> foo
95 95 > hg ci -m d-$i
96 96 > done
97 97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 98 created new head
99 99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100 created new head
101 101
102 102 $ HGMERGE=true hg merge 3
103 103 merging foo
104 104 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
105 105 (branch merge, don't forget to commit)
106 106
107 107 $ hg ci -m c-d
108 108
109 109 $ hg push ../c
110 110 pushing to ../c
111 111 searching for changes
112 112 abort: push creates new remote head 6346d66eb9f5!
113 113 (did you forget to merge? use push -f to force)
114 114 [255]
115 115
116 116 $ hg push -r 2 ../c
117 117 pushing to ../c
118 118 searching for changes
119 119 no changes found
120 120 [1]
121 121
122 122 $ hg push -r 3 ../c
123 123 pushing to ../c
124 124 searching for changes
125 125 abort: push creates new remote head a5dda829a167!
126 126 (did you forget to merge? use push -f to force)
127 127 [255]
128 128
129 129 $ hg push -v -r 3 -r 4 ../c
130 130 pushing to ../c
131 131 searching for changes
132 132 new remote heads on branch 'default'
133 133 new remote head a5dda829a167
134 134 new remote head ee8fbc7a0295
135 135 abort: push creates new remote head a5dda829a167!
136 136 (did you forget to merge? use push -f to force)
137 137 [255]
138 138
139 139 $ hg push -v -f -r 3 -r 4 ../c
140 140 pushing to ../c
141 141 searching for changes
142 142 2 changesets found
143 143 adding changesets
144 144 adding manifests
145 145 adding file changes
146 146 added 2 changesets with 2 changes to 1 files (+2 heads)
147 147
148 148 $ hg push -r 5 ../c
149 149 pushing to ../c
150 150 searching for changes
151 151 adding changesets
152 152 adding manifests
153 153 adding file changes
154 154 added 1 changesets with 1 changes to 1 files (-1 heads)
155 155
156 156 $ hg in ../c
157 157 comparing with ../c
158 158 searching for changes
159 159 no changes found
160 160 [1]
161 161
162 162
163 163 Issue450: push -r warns about remote head creation even if no heads
164 164 will be created
165 165
166 166 $ hg init ../e
167 167 $ hg push -r 0 ../e
168 168 pushing to ../e
169 169 searching for changes
170 170 adding changesets
171 171 adding manifests
172 172 adding file changes
173 173 added 1 changesets with 1 changes to 1 files
174 174
175 175 $ hg push -r 1 ../e
176 176 pushing to ../e
177 177 searching for changes
178 178 adding changesets
179 179 adding manifests
180 180 adding file changes
181 181 added 1 changesets with 1 changes to 1 files
182 182
183 183 $ cd ..
184 184
185 185
186 186 Issue736: named branches are not considered for detection of
187 187 unmerged heads in "hg push"
188 188
189 189 $ hg init f
190 190 $ cd f
191 191 $ hg -q branch a
192 192 $ echo 0 > foo
193 193 $ hg -q ci -Am 0
194 194 $ echo 1 > foo
195 195 $ hg -q ci -m 1
196 196 $ hg -q up 0
197 197 $ echo 2 > foo
198 198 $ hg -q ci -m 2
199 199 $ hg -q up 0
200 200 $ hg -q branch b
201 201 $ echo 3 > foo
202 202 $ hg -q ci -m 3
203 203 $ cd ..
204 204
205 205 $ hg -q clone f g
206 206 $ cd g
207 207
208 208 Push on existing branch and new branch:
209 209
210 210 $ hg -q up 1
211 211 $ echo 4 > foo
212 212 $ hg -q ci -m 4
213 213 $ hg -q up 0
214 214 $ echo 5 > foo
215 215 $ hg -q branch c
216 216 $ hg -q ci -m 5
217 217
218 218 $ hg push ../f
219 219 pushing to ../f
220 220 searching for changes
221 221 abort: push creates new remote branches: c!
222 222 (use 'hg push --new-branch' to create new remote branches)
223 223 [255]
224 224
225 225 $ hg push -r 4 -r 5 ../f
226 226 pushing to ../f
227 227 searching for changes
228 228 abort: push creates new remote branches: c!
229 229 (use 'hg push --new-branch' to create new remote branches)
230 230 [255]
231 231
232 232
233 233 Multiple new branches:
234 234
235 235 $ hg -q branch d
236 236 $ echo 6 > foo
237 237 $ hg -q ci -m 6
238 238
239 239 $ hg push ../f
240 240 pushing to ../f
241 241 searching for changes
242 242 abort: push creates new remote branches: c, d!
243 243 (use 'hg push --new-branch' to create new remote branches)
244 244 [255]
245 245
246 246 $ hg push -r 4 -r 6 ../f
247 247 pushing to ../f
248 248 searching for changes
249 249 abort: push creates new remote branches: c, d!
250 250 (use 'hg push --new-branch' to create new remote branches)
251 251 [255]
252 252
253 253 $ cd ../g
254 254
255 255
256 256 Fail on multiple head push:
257 257
258 258 $ hg -q up 1
259 259 $ echo 7 > foo
260 260 $ hg -q ci -m 7
261 261
262 262 $ hg push -r 4 -r 7 ../f
263 263 pushing to ../f
264 264 searching for changes
265 265 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
266 266 (did you forget to merge? use push -f to force)
267 267 [255]
268 268
269 269 Push replacement head on existing branches:
270 270
271 271 $ hg -q up 3
272 272 $ echo 8 > foo
273 273 $ hg -q ci -m 8
274 274
275 275 $ hg push -r 7 -r 8 ../f
276 276 pushing to ../f
277 277 searching for changes
278 278 adding changesets
279 279 adding manifests
280 280 adding file changes
281 281 added 2 changesets with 2 changes to 1 files
282 282
283 283
284 284 Merge of branch a to other branch b followed by unrelated push
285 285 on branch a:
286 286
287 287 $ hg -q up 7
288 288 $ HGMERGE=true hg -q merge 8
289 289 $ hg -q ci -m 9
290 290 $ hg -q up 8
291 291 $ echo 10 > foo
292 292 $ hg -q ci -m 10
293 293
294 294 $ hg push -r 9 ../f
295 295 pushing to ../f
296 296 searching for changes
297 297 adding changesets
298 298 adding manifests
299 299 adding file changes
300 300 added 1 changesets with 1 changes to 1 files (-1 heads)
301 301
302 302 $ hg push -r 10 ../f
303 303 pushing to ../f
304 304 searching for changes
305 305 adding changesets
306 306 adding manifests
307 307 adding file changes
308 308 added 1 changesets with 1 changes to 1 files (+1 heads)
309 309
310 310
311 311 Cheating the counting algorithm:
312 312
313 313 $ hg -q up 9
314 314 $ HGMERGE=true hg -q merge 2
315 315 $ hg -q ci -m 11
316 316 $ hg -q up 1
317 317 $ echo 12 > foo
318 318 $ hg -q ci -m 12
319 319
320 320 $ hg push -r 11 -r 12 ../f
321 321 pushing to ../f
322 322 searching for changes
323 323 adding changesets
324 324 adding manifests
325 325 adding file changes
326 326 added 2 changesets with 2 changes to 1 files
327 327
328 328
329 329 Failed push of new named branch:
330 330
331 331 $ echo 12 > foo
332 332 $ hg -q ci -m 12a
333 333 [1]
334 334 $ hg -q up 11
335 335 $ echo 13 > foo
336 336 $ hg -q branch e
337 337 $ hg -q ci -m 13d
338 338
339 339 $ hg push -r 12 -r 13 ../f
340 340 pushing to ../f
341 341 searching for changes
342 342 abort: push creates new remote branches: e!
343 343 (use 'hg push --new-branch' to create new remote branches)
344 344 [255]
345 345
346 346
347 347 Using --new-branch to push new named branch:
348 348
349 349 $ hg push --new-branch -r 12 -r 13 ../f
350 350 pushing to ../f
351 351 searching for changes
352 352 adding changesets
353 353 adding manifests
354 354 adding file changes
355 355 added 1 changesets with 1 changes to 1 files
356 356
357 357
358 358 Checking prepush logic does not allow silently pushing
359 359 multiple new heads:
360 360
361 361 $ cd ..
362 362 $ hg init h
363 363 $ echo init > h/init
364 364 $ hg -R h ci -Am init
365 365 adding init
366 366 $ echo a > h/a
367 367 $ hg -R h ci -Am a
368 368 adding a
369 369 $ hg clone h i
370 370 updating to branch default
371 371 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
372 372 $ hg -R h up 0
373 373 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
374 374 $ echo b > h/b
375 375 $ hg -R h ci -Am b
376 376 adding b
377 377 created new head
378 378 $ hg -R i up 0
379 379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
380 380 $ echo c > i/c
381 381 $ hg -R i ci -Am c
382 382 adding c
383 383 created new head
384 384
385 385 $ hg -R i push h
386 386 pushing to h
387 387 searching for changes
388 388 abort: push creates new remote head 97bd0c84d346!
389 389 (you should pull and merge or use push -f to force)
390 390 [255]
391 391
392 392
393 393 Check prepush logic with merged branches:
394 394
395 395 $ hg init j
396 396 $ hg -R j branch a
397 397 marked working directory as branch a
398 398 (branches are permanent and global, did you want a bookmark?)
399 399 $ echo init > j/foo
400 400 $ hg -R j ci -Am init
401 401 adding foo
402 402 $ hg clone j k
403 403 updating to branch a
404 404 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 405 $ echo a1 > j/foo
406 406 $ hg -R j ci -m a1
407 407 $ hg -R k branch b
408 408 marked working directory as branch b
409 409 (branches are permanent and global, did you want a bookmark?)
410 410 $ echo b > k/foo
411 411 $ hg -R k ci -m b
412 412 $ hg -R k up 0
413 413 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 414
415 415 $ hg -R k merge b
416 416 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 417 (branch merge, don't forget to commit)
418 418
419 419 $ hg -R k ci -m merge
420 420
421 421 $ hg -R k push -r a j
422 422 pushing to j
423 423 searching for changes
424 424 abort: push creates new remote branches: b!
425 425 (use 'hg push --new-branch' to create new remote branches)
426 426 [255]
427 427
428 428
429 429 Prepush -r should not allow you to sneak in new heads:
430 430
431 431 $ hg init l
432 432 $ cd l
433 433 $ echo a >> foo
434 434 $ hg -q add foo
435 435 $ hg -q branch a
436 436 $ hg -q ci -ma
437 437 $ hg -q up null
438 438 $ echo a >> foo
439 439 $ hg -q add foo
440 440 $ hg -q branch b
441 441 $ hg -q ci -mb
442 442 $ cd ..
443 443 $ hg -q clone l m -u a
444 444 $ cd m
445 445 $ hg -q merge b
446 446 $ hg -q ci -mmb
447 447 $ hg -q up 0
448 448 $ echo a >> foo
449 449 $ hg -q ci -ma2
450 450 $ hg -q up 2
451 451 $ echo a >> foo
452 452 $ hg -q branch -f b
453 453 $ hg -q ci -mb2
454 454 $ hg -q merge 3
455 455 $ hg -q ci -mma
456 456
457 457 $ hg push ../l -b b
458 458 pushing to ../l
459 459 searching for changes
460 abort: push creates new remote head e7e31d71180f on branch 'a'!
460 abort: push creates new remote head 451211cc22b0 on branch 'a'!
461 461 (did you forget to merge? use push -f to force)
462 462 [255]
463 463
464 464 $ cd ..
465 465
466 466
467 467 Check prepush with new branch head on former topo non-head:
468 468
469 469 $ hg init n
470 470 $ cd n
471 471 $ hg branch A
472 472 marked working directory as branch A
473 473 (branches are permanent and global, did you want a bookmark?)
474 474 $ echo a >a
475 475 $ hg ci -Ama
476 476 adding a
477 477 $ hg branch B
478 478 marked working directory as branch B
479 479 (branches are permanent and global, did you want a bookmark?)
480 480 $ echo b >b
481 481 $ hg ci -Amb
482 482 adding b
483 483
484 484 b is now branch head of B, and a topological head
485 485 a is now branch head of A, but not a topological head
486 486
487 487 $ hg clone . inner
488 488 updating to branch B
489 489 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
490 490 $ cd inner
491 491 $ hg up B
492 492 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
493 493 $ echo b1 >b1
494 494 $ hg ci -Amb1
495 495 adding b1
496 496
497 497 in the clone b1 is now the head of B
498 498
499 499 $ cd ..
500 500 $ hg up 0
501 501 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
502 502 $ echo a2 >a2
503 503 $ hg ci -Ama2
504 504 adding a2
505 505
506 506 a2 is now the new branch head of A, and a new topological head
507 507 it replaces a former inner branch head, so it should at most warn about
508 508 A, not B
509 509
510 510 glog of local:
511 511
512 512 $ hg glog --template "{rev}: {branches} {desc}\n"
513 513 @ 2: A a2
514 514 |
515 515 | o 1: B b
516 516 |/
517 517 o 0: A a
518 518
519 519 glog of remote:
520 520
521 521 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
522 522 @ 2: B b1
523 523 |
524 524 o 1: B b
525 525 |
526 526 o 0: A a
527 527
528 528 outgoing:
529 529
530 530 $ hg out inner --template "{rev}: {branches} {desc}\n"
531 531 comparing with inner
532 532 searching for changes
533 533 2: A a2
534 534
535 535 $ hg push inner
536 536 pushing to inner
537 537 searching for changes
538 538 adding changesets
539 539 adding manifests
540 540 adding file changes
541 541 added 1 changesets with 1 changes to 1 files (+1 heads)
542 542
543 543 $ cd ..
544 544
545 545
546 546 Check prepush with new branch head on former topo head:
547 547
548 548 $ hg init o
549 549 $ cd o
550 550 $ hg branch A
551 551 marked working directory as branch A
552 552 (branches are permanent and global, did you want a bookmark?)
553 553 $ echo a >a
554 554 $ hg ci -Ama
555 555 adding a
556 556 $ hg branch B
557 557 marked working directory as branch B
558 558 (branches are permanent and global, did you want a bookmark?)
559 559 $ echo b >b
560 560 $ hg ci -Amb
561 561 adding b
562 562
563 563 b is now branch head of B, and a topological head
564 564
565 565 $ hg up 0
566 566 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
567 567 $ echo a1 >a1
568 568 $ hg ci -Ama1
569 569 adding a1
570 570
571 571 a1 is now branch head of A, and a topological head
572 572
573 573 $ hg clone . inner
574 574 updating to branch A
575 575 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 576 $ cd inner
577 577 $ hg up B
578 578 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
579 579 $ echo b1 >b1
580 580 $ hg ci -Amb1
581 581 adding b1
582 582
583 583 in the clone b1 is now the head of B
584 584
585 585 $ cd ..
586 586 $ echo a2 >a2
587 587 $ hg ci -Ama2
588 588 adding a2
589 589
590 590 a2 is now the new branch head of A, and a topological head
591 591 it replaces a former topological and branch head, so this should not warn
592 592
593 593 glog of local:
594 594
595 595 $ hg glog --template "{rev}: {branches} {desc}\n"
596 596 @ 3: A a2
597 597 |
598 598 o 2: A a1
599 599 |
600 600 | o 1: B b
601 601 |/
602 602 o 0: A a
603 603
604 604 glog of remote:
605 605
606 606 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
607 607 @ 3: B b1
608 608 |
609 609 | o 2: A a1
610 610 | |
611 611 o | 1: B b
612 612 |/
613 613 o 0: A a
614 614
615 615 outgoing:
616 616
617 617 $ hg out inner --template "{rev}: {branches} {desc}\n"
618 618 comparing with inner
619 619 searching for changes
620 620 3: A a2
621 621
622 622 $ hg push inner
623 623 pushing to inner
624 624 searching for changes
625 625 adding changesets
626 626 adding manifests
627 627 adding file changes
628 628 added 1 changesets with 1 changes to 1 files
629 629
630 630 $ cd ..
631 631
632 632
633 633 Check prepush with new branch head and new child of former branch head
634 634 but child is on different branch:
635 635
636 636 $ hg init p
637 637 $ cd p
638 638 $ hg branch A
639 639 marked working directory as branch A
640 640 (branches are permanent and global, did you want a bookmark?)
641 641 $ echo a0 >a
642 642 $ hg ci -Ama0
643 643 adding a
644 644 $ echo a1 >a
645 645 $ hg ci -ma1
646 646 $ hg up null
647 647 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
648 648 $ hg branch B
649 649 marked working directory as branch B
650 650 (branches are permanent and global, did you want a bookmark?)
651 651 $ echo b0 >b
652 652 $ hg ci -Amb0
653 653 adding b
654 654 $ echo b1 >b
655 655 $ hg ci -mb1
656 656
657 657 $ hg clone . inner
658 658 updating to branch B
659 659 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
660 660
661 661 $ hg up A
662 662 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
663 663 $ hg branch -f B
664 664 marked working directory as branch B
665 665 (branches are permanent and global, did you want a bookmark?)
666 666 $ echo a3 >a
667 667 $ hg ci -ma3
668 668 created new head
669 669 $ hg up 3
670 670 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
671 671 $ hg branch -f A
672 672 marked working directory as branch A
673 673 (branches are permanent and global, did you want a bookmark?)
674 674 $ echo b3 >b
675 675 $ hg ci -mb3
676 676 created new head
677 677
678 678 glog of local:
679 679
680 680 $ hg glog --template "{rev}: {branches} {desc}\n"
681 681 @ 5: A b3
682 682 |
683 683 | o 4: B a3
684 684 | |
685 685 o | 3: B b1
686 686 | |
687 687 o | 2: B b0
688 688 /
689 689 o 1: A a1
690 690 |
691 691 o 0: A a0
692 692
693 693 glog of remote:
694 694
695 695 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
696 696 @ 3: B b1
697 697 |
698 698 o 2: B b0
699 699
700 700 o 1: A a1
701 701 |
702 702 o 0: A a0
703 703
704 704 outgoing:
705 705
706 706 $ hg out inner --template "{rev}: {branches} {desc}\n"
707 707 comparing with inner
708 708 searching for changes
709 709 4: B a3
710 710 5: A b3
711 711
712 712 $ hg push inner
713 713 pushing to inner
714 714 searching for changes
715 715 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
716 716 (did you forget to merge? use push -f to force)
717 717 [255]
718 718
719 719 $ hg push inner -r4 -r5
720 720 pushing to inner
721 721 searching for changes
722 722 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
723 723 (did you forget to merge? use push -f to force)
724 724 [255]
725 725
726 726 $ hg in inner
727 727 comparing with inner
728 728 searching for changes
729 729 no changes found
730 730 [1]
731 731
732 732 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now