##// END OF EJS Templates
discovery: improve "note: unsynced remote changes!" warning...
Mads Kiilerich -
r20501:8a9e0b52 default
parent child Browse files
Show More
@@ -1,356 +1,358 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 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
38 38 for h in heads:
39 39 if not knownnode(h):
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("served").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 if 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 knownnode = cl.hasnode # do not use nodemap until it is filtered
176 176 for h in heads:
177 177 if knownnode(h):
178 178 known.append(h)
179 179 else:
180 180 unsynced.append(h)
181 181 headssum[branch] = (known, list(known), unsynced)
182 182 # B. add new branch data
183 183 missingctx = list(repo[n] for n in outgoing.missing)
184 184 touchedbranches = set()
185 185 for ctx in missingctx:
186 186 branch = ctx.branch()
187 187 touchedbranches.add(branch)
188 188 if branch not in headssum:
189 189 headssum[branch] = (None, [], [])
190 190
191 191 # C drop data about untouched branches:
192 192 for branch in remotebranches - touchedbranches:
193 193 del headssum[branch]
194 194
195 195 # D. Update newmap with outgoing changes.
196 196 # This will possibly add new heads and remove existing ones.
197 197 newmap = branchmap.branchcache((branch, heads[1])
198 198 for branch, heads in headssum.iteritems()
199 199 if heads[0] is not None)
200 200 newmap.update(repo, (ctx.rev() for ctx in missingctx))
201 201 for branch, newheads in newmap.iteritems():
202 202 headssum[branch][1][:] = newheads
203 203 return headssum
204 204
205 205 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
206 206 """Compute branchmapsummary for repo without branchmap support"""
207 207
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 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
212 212 oldheads = set(h for h in remoteheads if knownnode(h))
213 213 # all nodes in outgoing.missing are children of either:
214 214 # - an element of oldheads
215 215 # - another element of outgoing.missing
216 216 # - nullrev
217 217 # This explains why the new head are very simple to compute.
218 218 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
219 219 newheads = list(c.node() for c in r)
220 220 unsynced = inc and set([None]) or set()
221 221 return {None: (oldheads, newheads, unsynced)}
222 222
223 223 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False,
224 224 newbookmarks=[]):
225 225 """Check that a push won't add any outgoing head
226 226
227 227 raise Abort error and display ui message as needed.
228 228 """
229 229 # Check for each named branch if we're creating new remote heads.
230 230 # To be a remote head after push, node must be either:
231 231 # - unknown locally
232 232 # - a local outgoing head descended from update
233 233 # - a remote head that's known locally and not
234 234 # ancestral to an outgoing head
235 235 if remoteheads == [nullid]:
236 236 # remote is empty, nothing to check.
237 237 return
238 238
239 239 if remote.capable('branchmap'):
240 240 headssum = _headssummary(repo, remote, outgoing)
241 241 else:
242 242 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
243 243 newbranches = [branch for branch, heads in headssum.iteritems()
244 244 if heads[0] is None]
245 245 # 1. Check for new branches on the remote.
246 246 if newbranches and not newbranch: # new branch requires --new-branch
247 247 branchnames = ', '.join(sorted(newbranches))
248 248 raise util.Abort(_("push creates new remote branches: %s!")
249 249 % branchnames,
250 250 hint=_("use 'hg push --new-branch' to create"
251 251 " new remote branches"))
252 252
253 253 # 2. Compute newly pushed bookmarks. We don't warn about bookmarked heads.
254 254 localbookmarks = repo._bookmarks
255 255 remotebookmarks = remote.listkeys('bookmarks')
256 256 bookmarkedheads = set()
257 257 for bm in localbookmarks:
258 258 rnode = remotebookmarks.get(bm)
259 259 if rnode and rnode in repo:
260 260 lctx, rctx = repo[bm], repo[rnode]
261 261 if bookmarks.validdest(repo, rctx, lctx):
262 262 bookmarkedheads.add(lctx.node())
263 263 else:
264 264 if bm in newbookmarks:
265 265 bookmarkedheads.add(repo[bm].node())
266 266
267 267 # 3. Check for new heads.
268 268 # If there are more heads after the push than before, a suitable
269 269 # error message, depending on unsynced status, is displayed.
270 270 error = None
271 unsynced = False
272 271 allmissing = set(outgoing.missing)
273 272 allfuturecommon = set(c.node() for c in repo.set('%ld', outgoing.common))
274 273 allfuturecommon.update(allmissing)
275 274 for branch, heads in sorted(headssum.iteritems()):
276 275 remoteheads, newheads, unsyncedheads = heads
277 276 candidate_newhs = set(newheads)
278 277 # add unsynced data
279 278 if remoteheads is None:
280 279 oldhs = set()
281 280 else:
282 281 oldhs = set(remoteheads)
283 282 oldhs.update(unsyncedheads)
284 283 candidate_newhs.update(unsyncedheads)
285 284 dhs = None # delta heads, the new heads on branch
286 285 discardedheads = set()
287 286 if repo.obsstore:
288 287 # remove future heads which are actually obsoleted by another
289 288 # pushed element:
290 289 #
291 290 # XXX as above, There are several cases this case does not handle
292 291 # XXX properly
293 292 #
294 293 # (1) if <nh> is public, it won't be affected by obsolete marker
295 294 # and a new is created
296 295 #
297 296 # (2) if the new heads have ancestors which are not obsolete and
298 297 # not ancestors of any other heads we will have a new head too.
299 298 #
300 299 # These two cases will be easy to handle for known changeset but
301 300 # much more tricky for unsynced changes.
302 301 newhs = set()
303 302 for nh in candidate_newhs:
304 303 if nh in repo and repo[nh].phase() <= phases.public:
305 304 newhs.add(nh)
306 305 else:
307 306 for suc in obsolete.allsuccessors(repo.obsstore, [nh]):
308 307 if suc != nh and suc in allfuturecommon:
309 308 discardedheads.add(nh)
310 309 break
311 310 else:
312 311 newhs.add(nh)
313 312 else:
314 313 newhs = candidate_newhs
315 if [h for h in unsyncedheads if h not in discardedheads]:
316 unsynced = True
314 unsynced = sorted(h for h in unsyncedheads if h not in discardedheads)
315 if unsynced:
316 heads = ' '.join(short(h) for h in unsynced)
317 if branch is None:
318 repo.ui.warn(_("remote has heads that are "
319 "not known locally: %s\n") % heads)
320 else:
321 repo.ui.warn(_("remote has heads on branch '%s' that are "
322 "not known locally: %s\n") % (branch, heads))
317 323 if remoteheads is None:
318 324 if len(newhs) > 1:
319 325 dhs = list(newhs)
320 326 if error is None:
321 327 error = (_("push creates new branch '%s' "
322 328 "with multiple heads") % (branch))
323 329 hint = _("merge or"
324 330 " see \"hg help push\" for details about"
325 331 " pushing new heads")
326 332 elif len(newhs) > len(oldhs):
327 333 # remove bookmarked or existing remote heads from the new heads list
328 334 dhs = sorted(newhs - bookmarkedheads - oldhs)
329 335 if dhs:
330 336 if error is None:
331 337 if branch not in ('default', None):
332 338 error = _("push creates new remote head %s "
333 339 "on branch '%s'!") % (short(dhs[0]), branch)
334 340 else:
335 341 error = _("push creates new remote head %s!"
336 342 ) % short(dhs[0])
337 343 if unsyncedheads:
338 344 hint = _("pull and merge or"
339 345 " see \"hg help push\" for details about"
340 346 " pushing new heads")
341 347 else:
342 348 hint = _("merge or"
343 349 " see \"hg help push\" for details about"
344 350 " pushing new heads")
345 351 if branch is None:
346 352 repo.ui.note(_("new remote heads:\n"))
347 353 else:
348 354 repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
349 355 for h in dhs:
350 356 repo.ui.note((" %s\n") % short(h))
351 357 if error:
352 358 raise util.Abort(error, hint=hint)
353
354 # 6. Check for unsynced changes on involved branches.
355 if unsynced:
356 repo.ui.warn(_("note: unsynced remote changes!\n"))
@@ -1,752 +1,755 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo foo > t1
4 4 $ hg add t1
5 5 $ hg commit -m "1"
6 6
7 7 $ cd ..
8 8 $ hg clone a b
9 9 updating to branch default
10 10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 11
12 12 $ cd a
13 13 $ echo foo > t2
14 14 $ hg add t2
15 15 $ hg commit -m "2"
16 16
17 17 $ cd ../b
18 18 $ echo foo > t3
19 19 $ hg add t3
20 20 $ hg commit -m "3"
21 21
22 22 $ hg push ../a
23 23 pushing to ../a
24 24 searching for changes
25 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
25 26 abort: push creates new remote head 1e108cc5548c!
26 27 (pull and merge or see "hg help push" for details about pushing new heads)
27 28 [255]
28 29
29 30 $ hg push --debug ../a
30 31 pushing to ../a
31 32 query 1; heads
32 33 searching for changes
33 34 taking quick initial sample
34 35 searching: 2 queries
35 36 query 2; still undecided: 1, sample size is: 1
36 37 2 total queries
37 38 listing keys for "bookmarks"
39 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
38 40 new remote heads on branch 'default':
39 41 1e108cc5548c
40 42 abort: push creates new remote head 1e108cc5548c!
41 43 (pull and merge or see "hg help push" for details about pushing new heads)
42 44 [255]
43 45
44 46 $ hg pull ../a
45 47 pulling from ../a
46 48 searching for changes
47 49 adding changesets
48 50 adding manifests
49 51 adding file changes
50 52 added 1 changesets with 1 changes to 1 files (+1 heads)
51 53 (run 'hg heads' to see heads, 'hg merge' to merge)
52 54
53 55 $ hg push ../a
54 56 pushing to ../a
55 57 searching for changes
56 58 abort: push creates new remote head 1e108cc5548c!
57 59 (merge or see "hg help push" for details about pushing new heads)
58 60 [255]
59 61
60 62 $ hg merge
61 63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 64 (branch merge, don't forget to commit)
63 65
64 66 $ hg commit -m "4"
65 67 $ hg push ../a
66 68 pushing to ../a
67 69 searching for changes
68 70 adding changesets
69 71 adding manifests
70 72 adding file changes
71 73 added 2 changesets with 1 changes to 1 files
72 74
73 75 $ cd ..
74 76
75 77 $ hg init c
76 78 $ cd c
77 79 $ for i in 0 1 2; do
78 80 > echo $i >> foo
79 81 > hg ci -Am $i
80 82 > done
81 83 adding foo
82 84 $ cd ..
83 85
84 86 $ hg clone c d
85 87 updating to branch default
86 88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 89
88 90 $ cd d
89 91 $ for i in 0 1; do
90 92 > hg co -C $i
91 93 > echo d-$i >> foo
92 94 > hg ci -m d-$i
93 95 > done
94 96 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 97 created new head
96 98 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 99 created new head
98 100
99 101 $ HGMERGE=true hg merge 3
100 102 merging foo
101 103 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
102 104 (branch merge, don't forget to commit)
103 105
104 106 $ hg ci -m c-d
105 107
106 108 $ hg push ../c
107 109 pushing to ../c
108 110 searching for changes
109 111 abort: push creates new remote head 6346d66eb9f5!
110 112 (merge or see "hg help push" for details about pushing new heads)
111 113 [255]
112 114
113 115 $ hg push -r 2 ../c
114 116 pushing to ../c
115 117 searching for changes
116 118 no changes found
117 119 [1]
118 120
119 121 $ hg push -r 3 ../c
120 122 pushing to ../c
121 123 searching for changes
122 124 abort: push creates new remote head a5dda829a167!
123 125 (merge or see "hg help push" for details about pushing new heads)
124 126 [255]
125 127
126 128 $ hg push -v -r 3 -r 4 ../c
127 129 pushing to ../c
128 130 searching for changes
129 131 new remote heads on branch 'default':
130 132 a5dda829a167
131 133 ee8fbc7a0295
132 134 abort: push creates new remote head a5dda829a167!
133 135 (merge or see "hg help push" for details about pushing new heads)
134 136 [255]
135 137
136 138 $ hg push -v -f -r 3 -r 4 ../c
137 139 pushing to ../c
138 140 searching for changes
139 141 2 changesets found
140 142 adding changesets
141 143 adding manifests
142 144 adding file changes
143 145 added 2 changesets with 2 changes to 1 files (+2 heads)
144 146
145 147 $ hg push -r 5 ../c
146 148 pushing to ../c
147 149 searching for changes
148 150 adding changesets
149 151 adding manifests
150 152 adding file changes
151 153 added 1 changesets with 1 changes to 1 files (-1 heads)
152 154
153 155 $ hg in ../c
154 156 comparing with ../c
155 157 searching for changes
156 158 no changes found
157 159 [1]
158 160
159 161
160 162 Issue450: push -r warns about remote head creation even if no heads
161 163 will be created
162 164
163 165 $ hg init ../e
164 166 $ hg push -r 0 ../e
165 167 pushing to ../e
166 168 searching for changes
167 169 adding changesets
168 170 adding manifests
169 171 adding file changes
170 172 added 1 changesets with 1 changes to 1 files
171 173
172 174 $ hg push -r 1 ../e
173 175 pushing to ../e
174 176 searching for changes
175 177 adding changesets
176 178 adding manifests
177 179 adding file changes
178 180 added 1 changesets with 1 changes to 1 files
179 181
180 182 $ cd ..
181 183
182 184
183 185 Issue736: named branches are not considered for detection of
184 186 unmerged heads in "hg push"
185 187
186 188 $ hg init f
187 189 $ cd f
188 190 $ hg -q branch a
189 191 $ echo 0 > foo
190 192 $ hg -q ci -Am 0
191 193 $ echo 1 > foo
192 194 $ hg -q ci -m 1
193 195 $ hg -q up 0
194 196 $ echo 2 > foo
195 197 $ hg -q ci -m 2
196 198 $ hg -q up 0
197 199 $ hg -q branch b
198 200 $ echo 3 > foo
199 201 $ hg -q ci -m 3
200 202 $ cd ..
201 203
202 204 $ hg -q clone f g
203 205 $ cd g
204 206
205 207 Push on existing branch and new branch:
206 208
207 209 $ hg -q up 1
208 210 $ echo 4 > foo
209 211 $ hg -q ci -m 4
210 212 $ hg -q up 0
211 213 $ echo 5 > foo
212 214 $ hg -q branch c
213 215 $ hg -q ci -m 5
214 216
215 217 $ hg push ../f
216 218 pushing to ../f
217 219 searching for changes
218 220 abort: push creates new remote branches: c!
219 221 (use 'hg push --new-branch' to create new remote branches)
220 222 [255]
221 223
222 224 $ hg push -r 4 -r 5 ../f
223 225 pushing to ../f
224 226 searching for changes
225 227 abort: push creates new remote branches: c!
226 228 (use 'hg push --new-branch' to create new remote branches)
227 229 [255]
228 230
229 231
230 232 Multiple new branches:
231 233
232 234 $ hg -q branch d
233 235 $ echo 6 > foo
234 236 $ hg -q ci -m 6
235 237
236 238 $ hg push ../f
237 239 pushing to ../f
238 240 searching for changes
239 241 abort: push creates new remote branches: c, d!
240 242 (use 'hg push --new-branch' to create new remote branches)
241 243 [255]
242 244
243 245 $ hg push -r 4 -r 6 ../f
244 246 pushing to ../f
245 247 searching for changes
246 248 abort: push creates new remote branches: c, d!
247 249 (use 'hg push --new-branch' to create new remote branches)
248 250 [255]
249 251
250 252 $ cd ../g
251 253
252 254
253 255 Fail on multiple head push:
254 256
255 257 $ hg -q up 1
256 258 $ echo 7 > foo
257 259 $ hg -q ci -m 7
258 260
259 261 $ hg push -r 4 -r 7 ../f
260 262 pushing to ../f
261 263 searching for changes
262 264 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
263 265 (merge or see "hg help push" for details about pushing new heads)
264 266 [255]
265 267
266 268 Push replacement head on existing branches:
267 269
268 270 $ hg -q up 3
269 271 $ echo 8 > foo
270 272 $ hg -q ci -m 8
271 273
272 274 $ hg push -r 7 -r 8 ../f
273 275 pushing to ../f
274 276 searching for changes
275 277 adding changesets
276 278 adding manifests
277 279 adding file changes
278 280 added 2 changesets with 2 changes to 1 files
279 281
280 282
281 283 Merge of branch a to other branch b followed by unrelated push
282 284 on branch a:
283 285
284 286 $ hg -q up 7
285 287 $ HGMERGE=true hg -q merge 8
286 288 $ hg -q ci -m 9
287 289 $ hg -q up 8
288 290 $ echo 10 > foo
289 291 $ hg -q ci -m 10
290 292
291 293 $ hg push -r 9 ../f
292 294 pushing to ../f
293 295 searching for changes
294 296 adding changesets
295 297 adding manifests
296 298 adding file changes
297 299 added 1 changesets with 1 changes to 1 files (-1 heads)
298 300
299 301 $ hg push -r 10 ../f
300 302 pushing to ../f
301 303 searching for changes
302 304 adding changesets
303 305 adding manifests
304 306 adding file changes
305 307 added 1 changesets with 1 changes to 1 files (+1 heads)
306 308
307 309
308 310 Cheating the counting algorithm:
309 311
310 312 $ hg -q up 9
311 313 $ HGMERGE=true hg -q merge 2
312 314 $ hg -q ci -m 11
313 315 $ hg -q up 1
314 316 $ echo 12 > foo
315 317 $ hg -q ci -m 12
316 318
317 319 $ hg push -r 11 -r 12 ../f
318 320 pushing to ../f
319 321 searching for changes
320 322 adding changesets
321 323 adding manifests
322 324 adding file changes
323 325 added 2 changesets with 2 changes to 1 files
324 326
325 327
326 328 Failed push of new named branch:
327 329
328 330 $ echo 12 > foo
329 331 $ hg -q ci -m 12a
330 332 [1]
331 333 $ hg -q up 11
332 334 $ echo 13 > foo
333 335 $ hg -q branch e
334 336 $ hg -q ci -m 13d
335 337
336 338 $ hg push -r 12 -r 13 ../f
337 339 pushing to ../f
338 340 searching for changes
339 341 abort: push creates new remote branches: e!
340 342 (use 'hg push --new-branch' to create new remote branches)
341 343 [255]
342 344
343 345
344 346 Using --new-branch to push new named branch:
345 347
346 348 $ hg push --new-branch -r 12 -r 13 ../f
347 349 pushing to ../f
348 350 searching for changes
349 351 adding changesets
350 352 adding manifests
351 353 adding file changes
352 354 added 1 changesets with 1 changes to 1 files
353 355
354 356 Pushing muliple headed new branch:
355 357
356 358 $ echo 14 > foo
357 359 $ hg -q branch f
358 360 $ hg -q ci -m 14
359 361 $ echo 15 > foo
360 362 $ hg -q ci -m 15
361 363 $ hg -q up 14
362 364 $ echo 16 > foo
363 365 $ hg -q ci -m 16
364 366 $ hg push --branch f --new-branch ../f
365 367 pushing to ../f
366 368 searching for changes
367 369 abort: push creates new branch 'f' with multiple heads
368 370 (merge or see "hg help push" for details about pushing new heads)
369 371 [255]
370 372 $ hg push --branch f --new-branch --force ../f
371 373 pushing to ../f
372 374 searching for changes
373 375 adding changesets
374 376 adding manifests
375 377 adding file changes
376 378 added 3 changesets with 3 changes to 1 files (+1 heads)
377 379
378 380 Checking prepush logic does not allow silently pushing
379 381 multiple new heads:
380 382
381 383 $ cd ..
382 384 $ hg init h
383 385 $ echo init > h/init
384 386 $ hg -R h ci -Am init
385 387 adding init
386 388 $ echo a > h/a
387 389 $ hg -R h ci -Am a
388 390 adding a
389 391 $ hg clone h i
390 392 updating to branch default
391 393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 394 $ hg -R h up 0
393 395 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
394 396 $ echo b > h/b
395 397 $ hg -R h ci -Am b
396 398 adding b
397 399 created new head
398 400 $ hg -R i up 0
399 401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
400 402 $ echo c > i/c
401 403 $ hg -R i ci -Am c
402 404 adding c
403 405 created new head
404 406
405 407 $ hg -R i push h
406 408 pushing to h
407 409 searching for changes
410 remote has heads on branch 'default' that are not known locally: ce4212fc8847
408 411 abort: push creates new remote head 97bd0c84d346!
409 412 (pull and merge or see "hg help push" for details about pushing new heads)
410 413 [255]
411 414
412 415
413 416 Check prepush logic with merged branches:
414 417
415 418 $ hg init j
416 419 $ hg -R j branch a
417 420 marked working directory as branch a
418 421 (branches are permanent and global, did you want a bookmark?)
419 422 $ echo init > j/foo
420 423 $ hg -R j ci -Am init
421 424 adding foo
422 425 $ hg clone j k
423 426 updating to branch a
424 427 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 428 $ echo a1 > j/foo
426 429 $ hg -R j ci -m a1
427 430 $ hg -R k branch b
428 431 marked working directory as branch b
429 432 (branches are permanent and global, did you want a bookmark?)
430 433 $ echo b > k/foo
431 434 $ hg -R k ci -m b
432 435 $ hg -R k up 0
433 436 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
434 437
435 438 $ hg -R k merge b
436 439 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 440 (branch merge, don't forget to commit)
438 441
439 442 $ hg -R k ci -m merge
440 443
441 444 $ hg -R k push -r a j
442 445 pushing to j
443 446 searching for changes
444 447 abort: push creates new remote branches: b!
445 448 (use 'hg push --new-branch' to create new remote branches)
446 449 [255]
447 450
448 451
449 452 Prepush -r should not allow you to sneak in new heads:
450 453
451 454 $ hg init l
452 455 $ cd l
453 456 $ echo a >> foo
454 457 $ hg -q add foo
455 458 $ hg -q branch a
456 459 $ hg -q ci -ma
457 460 $ hg -q up null
458 461 $ echo a >> foo
459 462 $ hg -q add foo
460 463 $ hg -q branch b
461 464 $ hg -q ci -mb
462 465 $ cd ..
463 466 $ hg -q clone l m -u a
464 467 $ cd m
465 468 $ hg -q merge b
466 469 $ hg -q ci -mmb
467 470 $ hg -q up 0
468 471 $ echo a >> foo
469 472 $ hg -q ci -ma2
470 473 $ hg -q up 2
471 474 $ echo a >> foo
472 475 $ hg -q branch -f b
473 476 $ hg -q ci -mb2
474 477 $ hg -q merge 3
475 478 $ hg -q ci -mma
476 479
477 480 $ hg push ../l -b b
478 481 pushing to ../l
479 482 searching for changes
480 483 abort: push creates new remote head 451211cc22b0 on branch 'a'!
481 484 (merge or see "hg help push" for details about pushing new heads)
482 485 [255]
483 486
484 487 $ cd ..
485 488
486 489
487 490 Check prepush with new branch head on former topo non-head:
488 491
489 492 $ hg init n
490 493 $ cd n
491 494 $ hg branch A
492 495 marked working directory as branch A
493 496 (branches are permanent and global, did you want a bookmark?)
494 497 $ echo a >a
495 498 $ hg ci -Ama
496 499 adding a
497 500 $ hg branch B
498 501 marked working directory as branch B
499 502 (branches are permanent and global, did you want a bookmark?)
500 503 $ echo b >b
501 504 $ hg ci -Amb
502 505 adding b
503 506
504 507 b is now branch head of B, and a topological head
505 508 a is now branch head of A, but not a topological head
506 509
507 510 $ hg clone . inner
508 511 updating to branch B
509 512 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
510 513 $ cd inner
511 514 $ hg up B
512 515 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
513 516 $ echo b1 >b1
514 517 $ hg ci -Amb1
515 518 adding b1
516 519
517 520 in the clone b1 is now the head of B
518 521
519 522 $ cd ..
520 523 $ hg up 0
521 524 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
522 525 $ echo a2 >a2
523 526 $ hg ci -Ama2
524 527 adding a2
525 528
526 529 a2 is now the new branch head of A, and a new topological head
527 530 it replaces a former inner branch head, so it should at most warn about
528 531 A, not B
529 532
530 533 glog of local:
531 534
532 535 $ hg log -G --template "{rev}: {branches} {desc}\n"
533 536 @ 2: A a2
534 537 |
535 538 | o 1: B b
536 539 |/
537 540 o 0: A a
538 541
539 542 glog of remote:
540 543
541 544 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
542 545 @ 2: B b1
543 546 |
544 547 o 1: B b
545 548 |
546 549 o 0: A a
547 550
548 551 outgoing:
549 552
550 553 $ hg out inner --template "{rev}: {branches} {desc}\n"
551 554 comparing with inner
552 555 searching for changes
553 556 2: A a2
554 557
555 558 $ hg push inner
556 559 pushing to inner
557 560 searching for changes
558 561 adding changesets
559 562 adding manifests
560 563 adding file changes
561 564 added 1 changesets with 1 changes to 1 files (+1 heads)
562 565
563 566 $ cd ..
564 567
565 568
566 569 Check prepush with new branch head on former topo head:
567 570
568 571 $ hg init o
569 572 $ cd o
570 573 $ hg branch A
571 574 marked working directory as branch A
572 575 (branches are permanent and global, did you want a bookmark?)
573 576 $ echo a >a
574 577 $ hg ci -Ama
575 578 adding a
576 579 $ hg branch B
577 580 marked working directory as branch B
578 581 (branches are permanent and global, did you want a bookmark?)
579 582 $ echo b >b
580 583 $ hg ci -Amb
581 584 adding b
582 585
583 586 b is now branch head of B, and a topological head
584 587
585 588 $ hg up 0
586 589 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
587 590 $ echo a1 >a1
588 591 $ hg ci -Ama1
589 592 adding a1
590 593
591 594 a1 is now branch head of A, and a topological head
592 595
593 596 $ hg clone . inner
594 597 updating to branch A
595 598 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
596 599 $ cd inner
597 600 $ hg up B
598 601 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
599 602 $ echo b1 >b1
600 603 $ hg ci -Amb1
601 604 adding b1
602 605
603 606 in the clone b1 is now the head of B
604 607
605 608 $ cd ..
606 609 $ echo a2 >a2
607 610 $ hg ci -Ama2
608 611 adding a2
609 612
610 613 a2 is now the new branch head of A, and a topological head
611 614 it replaces a former topological and branch head, so this should not warn
612 615
613 616 glog of local:
614 617
615 618 $ hg log -G --template "{rev}: {branches} {desc}\n"
616 619 @ 3: A a2
617 620 |
618 621 o 2: A a1
619 622 |
620 623 | o 1: B b
621 624 |/
622 625 o 0: A a
623 626
624 627 glog of remote:
625 628
626 629 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
627 630 @ 3: B b1
628 631 |
629 632 | o 2: A a1
630 633 | |
631 634 o | 1: B b
632 635 |/
633 636 o 0: A a
634 637
635 638 outgoing:
636 639
637 640 $ hg out inner --template "{rev}: {branches} {desc}\n"
638 641 comparing with inner
639 642 searching for changes
640 643 3: A a2
641 644
642 645 $ hg push inner
643 646 pushing to inner
644 647 searching for changes
645 648 adding changesets
646 649 adding manifests
647 650 adding file changes
648 651 added 1 changesets with 1 changes to 1 files
649 652
650 653 $ cd ..
651 654
652 655
653 656 Check prepush with new branch head and new child of former branch head
654 657 but child is on different branch:
655 658
656 659 $ hg init p
657 660 $ cd p
658 661 $ hg branch A
659 662 marked working directory as branch A
660 663 (branches are permanent and global, did you want a bookmark?)
661 664 $ echo a0 >a
662 665 $ hg ci -Ama0
663 666 adding a
664 667 $ echo a1 >a
665 668 $ hg ci -ma1
666 669 $ hg up null
667 670 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
668 671 $ hg branch B
669 672 marked working directory as branch B
670 673 (branches are permanent and global, did you want a bookmark?)
671 674 $ echo b0 >b
672 675 $ hg ci -Amb0
673 676 adding b
674 677 $ echo b1 >b
675 678 $ hg ci -mb1
676 679
677 680 $ hg clone . inner
678 681 updating to branch B
679 682 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
680 683
681 684 $ hg up A
682 685 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
683 686 $ hg branch -f B
684 687 marked working directory as branch B
685 688 (branches are permanent and global, did you want a bookmark?)
686 689 $ echo a3 >a
687 690 $ hg ci -ma3
688 691 created new head
689 692 $ hg up 3
690 693 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
691 694 $ hg branch -f A
692 695 marked working directory as branch A
693 696 (branches are permanent and global, did you want a bookmark?)
694 697 $ echo b3 >b
695 698 $ hg ci -mb3
696 699 created new head
697 700
698 701 glog of local:
699 702
700 703 $ hg log -G --template "{rev}: {branches} {desc}\n"
701 704 @ 5: A b3
702 705 |
703 706 | o 4: B a3
704 707 | |
705 708 o | 3: B b1
706 709 | |
707 710 o | 2: B b0
708 711 /
709 712 o 1: A a1
710 713 |
711 714 o 0: A a0
712 715
713 716 glog of remote:
714 717
715 718 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
716 719 @ 3: B b1
717 720 |
718 721 o 2: B b0
719 722
720 723 o 1: A a1
721 724 |
722 725 o 0: A a0
723 726
724 727 outgoing:
725 728
726 729 $ hg out inner --template "{rev}: {branches} {desc}\n"
727 730 comparing with inner
728 731 searching for changes
729 732 4: B a3
730 733 5: A b3
731 734
732 735 $ hg push inner
733 736 pushing to inner
734 737 searching for changes
735 738 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
736 739 (merge or see "hg help push" for details about pushing new heads)
737 740 [255]
738 741
739 742 $ hg push inner -r4 -r5
740 743 pushing to inner
741 744 searching for changes
742 745 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
743 746 (merge or see "hg help push" for details about pushing new heads)
744 747 [255]
745 748
746 749 $ hg in inner
747 750 comparing with inner
748 751 searching for changes
749 752 no changes found
750 753 [1]
751 754
752 755 $ cd ..
@@ -1,384 +1,384 b''
1 1
2 2
3 3 This test tries to exercise the ssh functionality with a dummy script
4 4
5 5 creating 'remote' repo
6 6
7 7 $ hg init remote
8 8 $ cd remote
9 9 $ echo this > foo
10 10 $ echo this > fooO
11 11 $ hg ci -A -m "init" foo fooO
12 12 $ cat <<EOF > .hg/hgrc
13 13 > [server]
14 14 > uncompressed = True
15 15 >
16 16 > [hooks]
17 17 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
18 18 > EOF
19 19 $ cd ..
20 20
21 21 repo not found error
22 22
23 23 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
24 24 remote: abort: there is no Mercurial repository here (.hg not found)!
25 25 abort: no suitable response from remote hg!
26 26 [255]
27 27
28 28 non-existent absolute path
29 29
30 30 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
31 31 remote: abort: there is no Mercurial repository here (.hg not found)!
32 32 abort: no suitable response from remote hg!
33 33 [255]
34 34
35 35 clone remote via stream
36 36
37 37 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
38 38 streaming all changes
39 39 4 files to transfer, 392 bytes of data
40 40 transferred 392 bytes in * seconds (*/sec) (glob)
41 41 updating to branch default
42 42 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ cd local-stream
44 44 $ hg verify
45 45 checking changesets
46 46 checking manifests
47 47 crosschecking files in changesets and manifests
48 48 checking files
49 49 2 files, 1 changesets, 2 total revisions
50 50 $ cd ..
51 51
52 52 clone remote via pull
53 53
54 54 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
55 55 requesting all changes
56 56 adding changesets
57 57 adding manifests
58 58 adding file changes
59 59 added 1 changesets with 2 changes to 2 files
60 60 updating to branch default
61 61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 62
63 63 verify
64 64
65 65 $ cd local
66 66 $ hg verify
67 67 checking changesets
68 68 checking manifests
69 69 crosschecking files in changesets and manifests
70 70 checking files
71 71 2 files, 1 changesets, 2 total revisions
72 72 $ echo '[hooks]' >> .hg/hgrc
73 73 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
74 74
75 75 empty default pull
76 76
77 77 $ hg paths
78 78 default = ssh://user@dummy/remote
79 79 $ hg pull -e "python \"$TESTDIR/dummyssh\""
80 80 pulling from ssh://user@dummy/remote
81 81 searching for changes
82 82 no changes found
83 83
84 84 local change
85 85
86 86 $ echo bleah > foo
87 87 $ hg ci -m "add"
88 88
89 89 updating rc
90 90
91 91 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
92 92 $ echo "[ui]" >> .hg/hgrc
93 93 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
94 94
95 95 find outgoing
96 96
97 97 $ hg out ssh://user@dummy/remote
98 98 comparing with ssh://user@dummy/remote
99 99 searching for changes
100 100 changeset: 1:a28a9d1a809c
101 101 tag: tip
102 102 user: test
103 103 date: Thu Jan 01 00:00:00 1970 +0000
104 104 summary: add
105 105
106 106
107 107 find incoming on the remote side
108 108
109 109 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
110 110 comparing with ssh://user@dummy/local
111 111 searching for changes
112 112 changeset: 1:a28a9d1a809c
113 113 tag: tip
114 114 user: test
115 115 date: Thu Jan 01 00:00:00 1970 +0000
116 116 summary: add
117 117
118 118
119 119 find incoming on the remote side (using absolute path)
120 120
121 121 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
122 122 comparing with ssh://user@dummy/$TESTTMP/local
123 123 searching for changes
124 124 changeset: 1:a28a9d1a809c
125 125 tag: tip
126 126 user: test
127 127 date: Thu Jan 01 00:00:00 1970 +0000
128 128 summary: add
129 129
130 130
131 131 push
132 132
133 133 $ hg push
134 134 pushing to ssh://user@dummy/remote
135 135 searching for changes
136 136 remote: adding changesets
137 137 remote: adding manifests
138 138 remote: adding file changes
139 139 remote: added 1 changesets with 1 changes to 1 files
140 140 $ cd ../remote
141 141
142 142 check remote tip
143 143
144 144 $ hg tip
145 145 changeset: 1:a28a9d1a809c
146 146 tag: tip
147 147 user: test
148 148 date: Thu Jan 01 00:00:00 1970 +0000
149 149 summary: add
150 150
151 151 $ hg verify
152 152 checking changesets
153 153 checking manifests
154 154 crosschecking files in changesets and manifests
155 155 checking files
156 156 2 files, 2 changesets, 3 total revisions
157 157 $ hg cat -r tip foo
158 158 bleah
159 159 $ echo z > z
160 160 $ hg ci -A -m z z
161 161 created new head
162 162
163 163 test pushkeys and bookmarks
164 164
165 165 $ cd ../local
166 166 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
167 167 bookmarks
168 168 namespaces
169 169 phases
170 170 $ hg book foo -r 0
171 171 $ hg out -B
172 172 comparing with ssh://user@dummy/remote
173 173 searching for changed bookmarks
174 174 foo 1160648e36ce
175 175 $ hg push -B foo
176 176 pushing to ssh://user@dummy/remote
177 177 searching for changes
178 178 no changes found
179 179 exporting bookmark foo
180 180 [1]
181 181 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
182 182 foo 1160648e36cec0054048a7edc4110c6f84fde594
183 183 $ hg book -f foo
184 184 $ hg push --traceback
185 185 pushing to ssh://user@dummy/remote
186 186 searching for changes
187 187 no changes found
188 188 updating bookmark foo
189 189 [1]
190 190 $ hg book -d foo
191 191 $ hg in -B
192 192 comparing with ssh://user@dummy/remote
193 193 searching for changed bookmarks
194 194 foo a28a9d1a809c
195 195 $ hg book -f -r 0 foo
196 196 $ hg pull -B foo
197 197 pulling from ssh://user@dummy/remote
198 198 no changes found
199 199 updating bookmark foo
200 200 importing bookmark foo
201 201 $ hg book -d foo
202 202 $ hg push -B foo
203 203 pushing to ssh://user@dummy/remote
204 204 searching for changes
205 205 no changes found
206 206 deleting remote bookmark foo
207 207 [1]
208 208
209 209 a bad, evil hook that prints to stdout
210 210
211 211 $ cat <<EOF > $TESTTMP/badhook
212 212 > import sys
213 213 > sys.stdout.write("KABOOM\n")
214 214 > EOF
215 215
216 216 $ echo '[hooks]' >> ../remote/.hg/hgrc
217 217 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
218 218 $ echo r > r
219 219 $ hg ci -A -m z r
220 220
221 221 push should succeed even though it has an unexpected response
222 222
223 223 $ hg push
224 224 pushing to ssh://user@dummy/remote
225 225 searching for changes
226 note: unsynced remote changes!
226 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
227 227 remote: adding changesets
228 228 remote: adding manifests
229 229 remote: adding file changes
230 230 remote: added 1 changesets with 1 changes to 1 files
231 231 remote: KABOOM
232 232 $ hg -R ../remote heads
233 233 changeset: 3:1383141674ec
234 234 tag: tip
235 235 parent: 1:a28a9d1a809c
236 236 user: test
237 237 date: Thu Jan 01 00:00:00 1970 +0000
238 238 summary: z
239 239
240 240 changeset: 2:6c0482d977a3
241 241 parent: 0:1160648e36ce
242 242 user: test
243 243 date: Thu Jan 01 00:00:00 1970 +0000
244 244 summary: z
245 245
246 246
247 247 clone bookmarks
248 248
249 249 $ hg -R ../remote bookmark test
250 250 $ hg -R ../remote bookmarks
251 251 * test 2:6c0482d977a3
252 252 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
253 253 requesting all changes
254 254 adding changesets
255 255 adding manifests
256 256 adding file changes
257 257 added 4 changesets with 5 changes to 4 files (+1 heads)
258 258 updating to branch default
259 259 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
260 260 $ hg -R local-bookmarks bookmarks
261 261 test 2:6c0482d977a3
262 262
263 263 passwords in ssh urls are not supported
264 264 (we use a glob here because different Python versions give different
265 265 results here)
266 266
267 267 $ hg push ssh://user:erroneouspwd@dummy/remote
268 268 pushing to ssh://user:*@dummy/remote (glob)
269 269 abort: password in URL not supported!
270 270 [255]
271 271
272 272 $ cd ..
273 273
274 274 hide outer repo
275 275 $ hg init
276 276
277 277 Test remote paths with spaces (issue2983):
278 278
279 279 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
280 280 $ touch "$TESTTMP/a repo/test"
281 281 $ hg -R 'a repo' commit -A -m "test"
282 282 adding test
283 283 $ hg -R 'a repo' tag tag
284 284 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
285 285 73649e48688a
286 286
287 287 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
288 288
289 289 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
290 290 destination directory: a repo
291 291 abort: destination 'a repo' is not empty
292 292 [255]
293 293
294 294 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
295 295 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
296 296 parameters:
297 297
298 298 $ cat > ssh.sh << EOF
299 299 > userhost="\$1"
300 300 > SSH_ORIGINAL_COMMAND="\$2"
301 301 > export SSH_ORIGINAL_COMMAND
302 302 > PYTHONPATH="$PYTHONPATH"
303 303 > export PYTHONPATH
304 304 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
305 305 > EOF
306 306
307 307 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
308 308 73649e48688a
309 309
310 310 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
311 311 remote: Illegal repository "$TESTTMP/a'repo" (glob)
312 312 abort: no suitable response from remote hg!
313 313 [255]
314 314
315 315 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
316 316 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
317 317 abort: no suitable response from remote hg!
318 318 [255]
319 319
320 320 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
321 321 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
322 322 [255]
323 323
324 324 Test hg-ssh in read-only mode:
325 325
326 326 $ cat > ssh.sh << EOF
327 327 > userhost="\$1"
328 328 > SSH_ORIGINAL_COMMAND="\$2"
329 329 > export SSH_ORIGINAL_COMMAND
330 330 > PYTHONPATH="$PYTHONPATH"
331 331 > export PYTHONPATH
332 332 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
333 333 > EOF
334 334
335 335 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
336 336 requesting all changes
337 337 adding changesets
338 338 adding manifests
339 339 adding file changes
340 340 added 4 changesets with 5 changes to 4 files (+1 heads)
341 341 updating to branch default
342 342 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 343
344 344 $ cd read-only-local
345 345 $ echo "baz" > bar
346 346 $ hg ci -A -m "unpushable commit" bar
347 347 $ hg push --ssh "sh ../ssh.sh"
348 348 pushing to ssh://user@dummy/*/remote (glob)
349 349 searching for changes
350 350 remote: Permission denied
351 351 remote: abort: prechangegroup.hg-ssh hook failed
352 352 remote: Permission denied
353 353 remote: abort: prepushkey.hg-ssh hook failed
354 354 abort: unexpected response: empty string
355 355 [255]
356 356
357 357 $ cd ..
358 358
359 359 $ cat dummylog
360 360 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
361 361 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
362 362 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
363 363 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
364 364 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
365 365 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
366 366 Got arguments 1:user@dummy 2:hg -R local serve --stdio
367 367 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
368 368 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
369 369 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
370 370 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
371 371 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
372 372 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
373 373 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
374 374 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
375 375 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
376 376 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
377 377 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
378 378 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
379 379 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
380 380 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
381 381 Got arguments 1:user@dummy 2:hg init 'a repo'
382 382 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
383 383 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
384 384 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now