##// END OF EJS Templates
hg: avoid auto sharing when the clone destination is remote...
FUJIWARA Katsunori -
r26026:d08e7449 stable
parent child Browse files
Show More
@@ -1,798 +1,798 b''
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 from node import nullid
12 12
13 13 import localrepo, bundlerepo, unionrepo, httppeer, sshpeer, statichttprepo
14 14 import bookmarks, lock, util, extensions, error, node, scmutil, phases, url
15 15 import cmdutil, discovery, repoview, exchange
16 16 import ui as uimod
17 17 import merge as mergemod
18 18 import verify as verifymod
19 19 import errno, os, shutil
20 20
21 21 def _local(path):
22 22 path = util.expandpath(util.urllocalpath(path))
23 23 return (os.path.isfile(path) and bundlerepo or localrepo)
24 24
25 25 def addbranchrevs(lrepo, other, branches, revs):
26 26 peer = other.peer() # a courtesy to callers using a localrepo for other
27 27 hashbranch, branches = branches
28 28 if not hashbranch and not branches:
29 29 x = revs or None
30 30 if util.safehasattr(revs, 'first'):
31 31 y = revs.first()
32 32 elif revs:
33 33 y = revs[0]
34 34 else:
35 35 y = None
36 36 return x, y
37 37 if revs:
38 38 revs = list(revs)
39 39 else:
40 40 revs = []
41 41
42 42 if not peer.capable('branchmap'):
43 43 if branches:
44 44 raise util.Abort(_("remote branch lookup not supported"))
45 45 revs.append(hashbranch)
46 46 return revs, revs[0]
47 47 branchmap = peer.branchmap()
48 48
49 49 def primary(branch):
50 50 if branch == '.':
51 51 if not lrepo:
52 52 raise util.Abort(_("dirstate branch not accessible"))
53 53 branch = lrepo.dirstate.branch()
54 54 if branch in branchmap:
55 55 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
56 56 return True
57 57 else:
58 58 return False
59 59
60 60 for branch in branches:
61 61 if not primary(branch):
62 62 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
63 63 if hashbranch:
64 64 if not primary(hashbranch):
65 65 revs.append(hashbranch)
66 66 return revs, revs[0]
67 67
68 68 def parseurl(path, branches=None):
69 69 '''parse url#branch, returning (url, (branch, branches))'''
70 70
71 71 u = util.url(path)
72 72 branch = None
73 73 if u.fragment:
74 74 branch = u.fragment
75 75 u.fragment = None
76 76 return str(u), (branch, branches or [])
77 77
78 78 schemes = {
79 79 'bundle': bundlerepo,
80 80 'union': unionrepo,
81 81 'file': _local,
82 82 'http': httppeer,
83 83 'https': httppeer,
84 84 'ssh': sshpeer,
85 85 'static-http': statichttprepo,
86 86 }
87 87
88 88 def _peerlookup(path):
89 89 u = util.url(path)
90 90 scheme = u.scheme or 'file'
91 91 thing = schemes.get(scheme) or schemes['file']
92 92 try:
93 93 return thing(path)
94 94 except TypeError:
95 95 # we can't test callable(thing) because 'thing' can be an unloaded
96 96 # module that implements __call__
97 97 if not util.safehasattr(thing, 'instance'):
98 98 raise
99 99 return thing
100 100
101 101 def islocal(repo):
102 102 '''return true if repo (or path pointing to repo) is local'''
103 103 if isinstance(repo, str):
104 104 try:
105 105 return _peerlookup(repo).islocal(repo)
106 106 except AttributeError:
107 107 return False
108 108 return repo.local()
109 109
110 110 def openpath(ui, path):
111 111 '''open path with open if local, url.open if remote'''
112 112 pathurl = util.url(path, parsequery=False, parsefragment=False)
113 113 if pathurl.islocal():
114 114 return util.posixfile(pathurl.localpath(), 'rb')
115 115 else:
116 116 return url.open(ui, path)
117 117
118 118 # a list of (ui, repo) functions called for wire peer initialization
119 119 wirepeersetupfuncs = []
120 120
121 121 def _peerorrepo(ui, path, create=False):
122 122 """return a repository object for the specified path"""
123 123 obj = _peerlookup(path).instance(ui, path, create)
124 124 ui = getattr(obj, "ui", ui)
125 125 for name, module in extensions.extensions(ui):
126 126 hook = getattr(module, 'reposetup', None)
127 127 if hook:
128 128 hook(ui, obj)
129 129 if not obj.local():
130 130 for f in wirepeersetupfuncs:
131 131 f(ui, obj)
132 132 return obj
133 133
134 134 def repository(ui, path='', create=False):
135 135 """return a repository object for the specified path"""
136 136 peer = _peerorrepo(ui, path, create)
137 137 repo = peer.local()
138 138 if not repo:
139 139 raise util.Abort(_("repository '%s' is not local") %
140 140 (path or peer.url()))
141 141 return repo.filtered('visible')
142 142
143 143 def peer(uiorrepo, opts, path, create=False):
144 144 '''return a repository peer for the specified path'''
145 145 rui = remoteui(uiorrepo, opts)
146 146 return _peerorrepo(rui, path, create).peer()
147 147
148 148 def defaultdest(source):
149 149 '''return default destination of clone if none is given
150 150
151 151 >>> defaultdest('foo')
152 152 'foo'
153 153 >>> defaultdest('/foo/bar')
154 154 'bar'
155 155 >>> defaultdest('/')
156 156 ''
157 157 >>> defaultdest('')
158 158 ''
159 159 >>> defaultdest('http://example.org/')
160 160 ''
161 161 >>> defaultdest('http://example.org/foo/')
162 162 'foo'
163 163 '''
164 164 path = util.url(source).path
165 165 if not path:
166 166 return ''
167 167 return os.path.basename(os.path.normpath(path))
168 168
169 169 def share(ui, source, dest=None, update=True, bookmarks=True):
170 170 '''create a shared repository'''
171 171
172 172 if not islocal(source):
173 173 raise util.Abort(_('can only share local repositories'))
174 174
175 175 if not dest:
176 176 dest = defaultdest(source)
177 177 else:
178 178 dest = ui.expandpath(dest)
179 179
180 180 if isinstance(source, str):
181 181 origsource = ui.expandpath(source)
182 182 source, branches = parseurl(origsource)
183 183 srcrepo = repository(ui, source)
184 184 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
185 185 else:
186 186 srcrepo = source.local()
187 187 origsource = source = srcrepo.url()
188 188 checkout = None
189 189
190 190 sharedpath = srcrepo.sharedpath # if our source is already sharing
191 191
192 192 destwvfs = scmutil.vfs(dest, realpath=True)
193 193 destvfs = scmutil.vfs(os.path.join(destwvfs.base, '.hg'), realpath=True)
194 194
195 195 if destvfs.lexists():
196 196 raise util.Abort(_('destination already exists'))
197 197
198 198 if not destwvfs.isdir():
199 199 destwvfs.mkdir()
200 200 destvfs.makedir()
201 201
202 202 requirements = ''
203 203 try:
204 204 requirements = srcrepo.vfs.read('requires')
205 205 except IOError as inst:
206 206 if inst.errno != errno.ENOENT:
207 207 raise
208 208
209 209 requirements += 'shared\n'
210 210 destvfs.write('requires', requirements)
211 211 destvfs.write('sharedpath', sharedpath)
212 212
213 213 r = repository(ui, destwvfs.base)
214 214
215 215 default = srcrepo.ui.config('paths', 'default')
216 216 if default:
217 217 fp = r.vfs("hgrc", "w", text=True)
218 218 fp.write("[paths]\n")
219 219 fp.write("default = %s\n" % default)
220 220 fp.close()
221 221
222 222 if update:
223 223 r.ui.status(_("updating working directory\n"))
224 224 if update is not True:
225 225 checkout = update
226 226 for test in (checkout, 'default', 'tip'):
227 227 if test is None:
228 228 continue
229 229 try:
230 230 uprev = r.lookup(test)
231 231 break
232 232 except error.RepoLookupError:
233 233 continue
234 234 _update(r, uprev)
235 235
236 236 if bookmarks:
237 237 fp = r.vfs('shared', 'w')
238 238 fp.write('bookmarks\n')
239 239 fp.close()
240 240
241 241 def copystore(ui, srcrepo, destpath):
242 242 '''copy files from store of srcrepo in destpath
243 243
244 244 returns destlock
245 245 '''
246 246 destlock = None
247 247 try:
248 248 hardlink = None
249 249 num = 0
250 250 closetopic = [None]
251 251 def prog(topic, pos):
252 252 if pos is None:
253 253 closetopic[0] = topic
254 254 else:
255 255 ui.progress(topic, pos + num)
256 256 srcpublishing = srcrepo.publishing()
257 257 srcvfs = scmutil.vfs(srcrepo.sharedpath)
258 258 dstvfs = scmutil.vfs(destpath)
259 259 for f in srcrepo.store.copylist():
260 260 if srcpublishing and f.endswith('phaseroots'):
261 261 continue
262 262 dstbase = os.path.dirname(f)
263 263 if dstbase and not dstvfs.exists(dstbase):
264 264 dstvfs.mkdir(dstbase)
265 265 if srcvfs.exists(f):
266 266 if f.endswith('data'):
267 267 # 'dstbase' may be empty (e.g. revlog format 0)
268 268 lockfile = os.path.join(dstbase, "lock")
269 269 # lock to avoid premature writing to the target
270 270 destlock = lock.lock(dstvfs, lockfile)
271 271 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
272 272 hardlink, progress=prog)
273 273 num += n
274 274 if hardlink:
275 275 ui.debug("linked %d files\n" % num)
276 276 if closetopic[0]:
277 277 ui.progress(closetopic[0], None)
278 278 else:
279 279 ui.debug("copied %d files\n" % num)
280 280 if closetopic[0]:
281 281 ui.progress(closetopic[0], None)
282 282 return destlock
283 283 except: # re-raises
284 284 release(destlock)
285 285 raise
286 286
287 287 def clonewithshare(ui, peeropts, sharepath, source, srcpeer, dest, pull=False,
288 288 rev=None, update=True, stream=False):
289 289 """Perform a clone using a shared repo.
290 290
291 291 The store for the repository will be located at <sharepath>/.hg. The
292 292 specified revisions will be cloned or pulled from "source". A shared repo
293 293 will be created at "dest" and a working copy will be created if "update" is
294 294 True.
295 295 """
296 296 revs = None
297 297 if rev:
298 298 if not srcpeer.capable('lookup'):
299 299 raise util.Abort(_("src repository does not support "
300 300 "revision lookup and so doesn't "
301 301 "support clone by revision"))
302 302 revs = [srcpeer.lookup(r) for r in rev]
303 303
304 304 basename = os.path.basename(sharepath)
305 305
306 306 if os.path.exists(sharepath):
307 307 ui.status(_('(sharing from existing pooled repository %s)\n') %
308 308 basename)
309 309 else:
310 310 ui.status(_('(sharing from new pooled repository %s)\n') % basename)
311 311 # Always use pull mode because hardlinks in share mode don't work well.
312 312 # Never update because working copies aren't necessary in share mode.
313 313 clone(ui, peeropts, source, dest=sharepath, pull=True,
314 314 rev=rev, update=False, stream=stream)
315 315
316 316 sharerepo = repository(ui, path=sharepath)
317 317 share(ui, sharerepo, dest=dest, update=update, bookmarks=False)
318 318
319 319 # We need to perform a pull against the dest repo to fetch bookmarks
320 320 # and other non-store data that isn't shared by default. In the case of
321 321 # non-existing shared repo, this means we pull from the remote twice. This
322 322 # is a bit weird. But at the time it was implemented, there wasn't an easy
323 323 # way to pull just non-changegroup data.
324 324 destrepo = repository(ui, path=dest)
325 325 exchange.pull(destrepo, srcpeer, heads=revs)
326 326
327 327 return srcpeer, peer(ui, peeropts, dest)
328 328
329 329 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
330 330 update=True, stream=False, branch=None, shareopts=None):
331 331 """Make a copy of an existing repository.
332 332
333 333 Create a copy of an existing repository in a new directory. The
334 334 source and destination are URLs, as passed to the repository
335 335 function. Returns a pair of repository peers, the source and
336 336 newly created destination.
337 337
338 338 The location of the source is added to the new repository's
339 339 .hg/hgrc file, as the default to be used for future pulls and
340 340 pushes.
341 341
342 342 If an exception is raised, the partly cloned/updated destination
343 343 repository will be deleted.
344 344
345 345 Arguments:
346 346
347 347 source: repository object or URL
348 348
349 349 dest: URL of destination repository to create (defaults to base
350 350 name of source repository)
351 351
352 352 pull: always pull from source repository, even in local case or if the
353 353 server prefers streaming
354 354
355 355 stream: stream raw data uncompressed from repository (fast over
356 356 LAN, slow over WAN)
357 357
358 358 rev: revision to clone up to (implies pull=True)
359 359
360 360 update: update working directory after clone completes, if
361 361 destination is local repository (True means update to default rev,
362 362 anything else is treated as a revision)
363 363
364 364 branch: branches to clone
365 365
366 366 shareopts: dict of options to control auto sharing behavior. The "pool" key
367 367 activates auto sharing mode and defines the directory for stores. The
368 368 "mode" key determines how to construct the directory name of the shared
369 369 repository. "identity" means the name is derived from the node of the first
370 370 changeset in the repository. "remote" means the name is derived from the
371 371 remote's path/URL. Defaults to "identity."
372 372 """
373 373
374 374 if isinstance(source, str):
375 375 origsource = ui.expandpath(source)
376 376 source, branch = parseurl(origsource, branch)
377 377 srcpeer = peer(ui, peeropts, source)
378 378 else:
379 379 srcpeer = source.peer() # in case we were called with a localrepo
380 380 branch = (None, branch or [])
381 381 origsource = source = srcpeer.url()
382 382 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
383 383
384 384 if dest is None:
385 385 dest = defaultdest(source)
386 386 if dest:
387 387 ui.status(_("destination directory: %s\n") % dest)
388 388 else:
389 389 dest = ui.expandpath(dest)
390 390
391 391 dest = util.urllocalpath(dest)
392 392 source = util.urllocalpath(source)
393 393
394 394 if not dest:
395 395 raise util.Abort(_("empty destination path is not valid"))
396 396
397 397 destvfs = scmutil.vfs(dest, expandpath=True)
398 398 if destvfs.lexists():
399 399 if not destvfs.isdir():
400 400 raise util.Abort(_("destination '%s' already exists") % dest)
401 401 elif destvfs.listdir():
402 402 raise util.Abort(_("destination '%s' is not empty") % dest)
403 403
404 404 shareopts = shareopts or {}
405 405 sharepool = shareopts.get('pool')
406 406 sharenamemode = shareopts.get('mode')
407 if sharepool:
407 if sharepool and islocal(dest):
408 408 sharepath = None
409 409 if sharenamemode == 'identity':
410 410 # Resolve the name from the initial changeset in the remote
411 411 # repository. This returns nullid when the remote is empty. It
412 412 # raises RepoLookupError if revision 0 is filtered or otherwise
413 413 # not available. If we fail to resolve, sharing is not enabled.
414 414 try:
415 415 rootnode = srcpeer.lookup('0')
416 416 if rootnode != node.nullid:
417 417 sharepath = os.path.join(sharepool, node.hex(rootnode))
418 418 else:
419 419 ui.status(_('(not using pooled storage: '
420 420 'remote appears to be empty)\n'))
421 421 except error.RepoLookupError:
422 422 ui.status(_('(not using pooled storage: '
423 423 'unable to resolve identity of remote)\n'))
424 424 elif sharenamemode == 'remote':
425 425 sharepath = os.path.join(sharepool, util.sha1(source).hexdigest())
426 426 else:
427 427 raise util.Abort('unknown share naming mode: %s' % sharenamemode)
428 428
429 429 if sharepath:
430 430 return clonewithshare(ui, peeropts, sharepath, source, srcpeer,
431 431 dest, pull=pull, rev=rev, update=update,
432 432 stream=stream)
433 433
434 434 srclock = destlock = cleandir = None
435 435 srcrepo = srcpeer.local()
436 436 try:
437 437 abspath = origsource
438 438 if islocal(origsource):
439 439 abspath = os.path.abspath(util.urllocalpath(origsource))
440 440
441 441 if islocal(dest):
442 442 cleandir = dest
443 443
444 444 copy = False
445 445 if (srcrepo and srcrepo.cancopy() and islocal(dest)
446 446 and not phases.hassecret(srcrepo)):
447 447 copy = not pull and not rev
448 448
449 449 if copy:
450 450 try:
451 451 # we use a lock here because if we race with commit, we
452 452 # can end up with extra data in the cloned revlogs that's
453 453 # not pointed to by changesets, thus causing verify to
454 454 # fail
455 455 srclock = srcrepo.lock(wait=False)
456 456 except error.LockError:
457 457 copy = False
458 458
459 459 if copy:
460 460 srcrepo.hook('preoutgoing', throw=True, source='clone')
461 461 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
462 462 if not os.path.exists(dest):
463 463 os.mkdir(dest)
464 464 else:
465 465 # only clean up directories we create ourselves
466 466 cleandir = hgdir
467 467 try:
468 468 destpath = hgdir
469 469 util.makedir(destpath, notindexed=True)
470 470 except OSError as inst:
471 471 if inst.errno == errno.EEXIST:
472 472 cleandir = None
473 473 raise util.Abort(_("destination '%s' already exists")
474 474 % dest)
475 475 raise
476 476
477 477 destlock = copystore(ui, srcrepo, destpath)
478 478 # copy bookmarks over
479 479 srcbookmarks = srcrepo.join('bookmarks')
480 480 dstbookmarks = os.path.join(destpath, 'bookmarks')
481 481 if os.path.exists(srcbookmarks):
482 482 util.copyfile(srcbookmarks, dstbookmarks)
483 483
484 484 # Recomputing branch cache might be slow on big repos,
485 485 # so just copy it
486 486 def copybranchcache(fname):
487 487 srcbranchcache = srcrepo.join('cache/%s' % fname)
488 488 dstbranchcache = os.path.join(dstcachedir, fname)
489 489 if os.path.exists(srcbranchcache):
490 490 if not os.path.exists(dstcachedir):
491 491 os.mkdir(dstcachedir)
492 492 util.copyfile(srcbranchcache, dstbranchcache)
493 493
494 494 dstcachedir = os.path.join(destpath, 'cache')
495 495 # In local clones we're copying all nodes, not just served
496 496 # ones. Therefore copy all branch caches over.
497 497 copybranchcache('branch2')
498 498 for cachename in repoview.filtertable:
499 499 copybranchcache('branch2-%s' % cachename)
500 500
501 501 # we need to re-init the repo after manually copying the data
502 502 # into it
503 503 destpeer = peer(srcrepo, peeropts, dest)
504 504 srcrepo.hook('outgoing', source='clone',
505 505 node=node.hex(node.nullid))
506 506 else:
507 507 try:
508 508 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
509 509 # only pass ui when no srcrepo
510 510 except OSError as inst:
511 511 if inst.errno == errno.EEXIST:
512 512 cleandir = None
513 513 raise util.Abort(_("destination '%s' already exists")
514 514 % dest)
515 515 raise
516 516
517 517 revs = None
518 518 if rev:
519 519 if not srcpeer.capable('lookup'):
520 520 raise util.Abort(_("src repository does not support "
521 521 "revision lookup and so doesn't "
522 522 "support clone by revision"))
523 523 revs = [srcpeer.lookup(r) for r in rev]
524 524 checkout = revs[0]
525 525 if destpeer.local():
526 526 if not stream:
527 527 if pull:
528 528 stream = False
529 529 else:
530 530 stream = None
531 531 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
532 532 elif srcrepo:
533 533 exchange.push(srcrepo, destpeer, revs=revs,
534 534 bookmarks=srcrepo._bookmarks.keys())
535 535 else:
536 536 raise util.Abort(_("clone from remote to remote not supported"))
537 537
538 538 cleandir = None
539 539
540 540 destrepo = destpeer.local()
541 541 if destrepo:
542 542 template = uimod.samplehgrcs['cloned']
543 543 fp = destrepo.vfs("hgrc", "w", text=True)
544 544 u = util.url(abspath)
545 545 u.passwd = None
546 546 defaulturl = str(u)
547 547 fp.write(template % defaulturl)
548 548 fp.close()
549 549
550 550 destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
551 551
552 552 if update:
553 553 if update is not True:
554 554 checkout = srcpeer.lookup(update)
555 555 uprev = None
556 556 status = None
557 557 if checkout is not None:
558 558 try:
559 559 uprev = destrepo.lookup(checkout)
560 560 except error.RepoLookupError:
561 561 pass
562 562 if uprev is None:
563 563 try:
564 564 uprev = destrepo._bookmarks['@']
565 565 update = '@'
566 566 bn = destrepo[uprev].branch()
567 567 if bn == 'default':
568 568 status = _("updating to bookmark @\n")
569 569 else:
570 570 status = (_("updating to bookmark @ on branch %s\n")
571 571 % bn)
572 572 except KeyError:
573 573 try:
574 574 uprev = destrepo.branchtip('default')
575 575 except error.RepoLookupError:
576 576 uprev = destrepo.lookup('tip')
577 577 if not status:
578 578 bn = destrepo[uprev].branch()
579 579 status = _("updating to branch %s\n") % bn
580 580 destrepo.ui.status(status)
581 581 _update(destrepo, uprev)
582 582 if update in destrepo._bookmarks:
583 583 bookmarks.activate(destrepo, update)
584 584 finally:
585 585 release(srclock, destlock)
586 586 if cleandir is not None:
587 587 shutil.rmtree(cleandir, True)
588 588 if srcpeer is not None:
589 589 srcpeer.close()
590 590 return srcpeer, destpeer
591 591
592 592 def _showstats(repo, stats):
593 593 repo.ui.status(_("%d files updated, %d files merged, "
594 594 "%d files removed, %d files unresolved\n") % stats)
595 595
596 596 def updaterepo(repo, node, overwrite):
597 597 """Update the working directory to node.
598 598
599 599 When overwrite is set, changes are clobbered, merged else
600 600
601 601 returns stats (see pydoc mercurial.merge.applyupdates)"""
602 602 return mergemod.update(repo, node, False, overwrite, None,
603 603 labels=['working copy', 'destination'])
604 604
605 605 def update(repo, node):
606 606 """update the working directory to node, merging linear changes"""
607 607 stats = updaterepo(repo, node, False)
608 608 _showstats(repo, stats)
609 609 if stats[3]:
610 610 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
611 611 return stats[3] > 0
612 612
613 613 # naming conflict in clone()
614 614 _update = update
615 615
616 616 def clean(repo, node, show_stats=True):
617 617 """forcibly switch the working directory to node, clobbering changes"""
618 618 stats = updaterepo(repo, node, True)
619 619 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
620 620 if show_stats:
621 621 _showstats(repo, stats)
622 622 return stats[3] > 0
623 623
624 624 def merge(repo, node, force=None, remind=True):
625 625 """Branch merge with node, resolving changes. Return true if any
626 626 unresolved conflicts."""
627 627 stats = mergemod.update(repo, node, True, force, False)
628 628 _showstats(repo, stats)
629 629 if stats[3]:
630 630 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
631 631 "or 'hg update -C .' to abandon\n"))
632 632 elif remind:
633 633 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
634 634 return stats[3] > 0
635 635
636 636 def _incoming(displaychlist, subreporecurse, ui, repo, source,
637 637 opts, buffered=False):
638 638 """
639 639 Helper for incoming / gincoming.
640 640 displaychlist gets called with
641 641 (remoterepo, incomingchangesetlist, displayer) parameters,
642 642 and is supposed to contain only code that can't be unified.
643 643 """
644 644 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
645 645 other = peer(repo, opts, source)
646 646 ui.status(_('comparing with %s\n') % util.hidepassword(source))
647 647 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
648 648
649 649 if revs:
650 650 revs = [other.lookup(rev) for rev in revs]
651 651 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
652 652 revs, opts["bundle"], opts["force"])
653 653 try:
654 654 if not chlist:
655 655 ui.status(_("no changes found\n"))
656 656 return subreporecurse()
657 657
658 658 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
659 659 displaychlist(other, chlist, displayer)
660 660 displayer.close()
661 661 finally:
662 662 cleanupfn()
663 663 subreporecurse()
664 664 return 0 # exit code is zero since we found incoming changes
665 665
666 666 def incoming(ui, repo, source, opts):
667 667 def subreporecurse():
668 668 ret = 1
669 669 if opts.get('subrepos'):
670 670 ctx = repo[None]
671 671 for subpath in sorted(ctx.substate):
672 672 sub = ctx.sub(subpath)
673 673 ret = min(ret, sub.incoming(ui, source, opts))
674 674 return ret
675 675
676 676 def display(other, chlist, displayer):
677 677 limit = cmdutil.loglimit(opts)
678 678 if opts.get('newest_first'):
679 679 chlist.reverse()
680 680 count = 0
681 681 for n in chlist:
682 682 if limit is not None and count >= limit:
683 683 break
684 684 parents = [p for p in other.changelog.parents(n) if p != nullid]
685 685 if opts.get('no_merges') and len(parents) == 2:
686 686 continue
687 687 count += 1
688 688 displayer.show(other[n])
689 689 return _incoming(display, subreporecurse, ui, repo, source, opts)
690 690
691 691 def _outgoing(ui, repo, dest, opts):
692 692 dest = ui.expandpath(dest or 'default-push', dest or 'default')
693 693 dest, branches = parseurl(dest, opts.get('branch'))
694 694 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
695 695 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
696 696 if revs:
697 697 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
698 698
699 699 other = peer(repo, opts, dest)
700 700 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
701 701 force=opts.get('force'))
702 702 o = outgoing.missing
703 703 if not o:
704 704 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
705 705 return o, other
706 706
707 707 def outgoing(ui, repo, dest, opts):
708 708 def recurse():
709 709 ret = 1
710 710 if opts.get('subrepos'):
711 711 ctx = repo[None]
712 712 for subpath in sorted(ctx.substate):
713 713 sub = ctx.sub(subpath)
714 714 ret = min(ret, sub.outgoing(ui, dest, opts))
715 715 return ret
716 716
717 717 limit = cmdutil.loglimit(opts)
718 718 o, other = _outgoing(ui, repo, dest, opts)
719 719 if not o:
720 720 cmdutil.outgoinghooks(ui, repo, other, opts, o)
721 721 return recurse()
722 722
723 723 if opts.get('newest_first'):
724 724 o.reverse()
725 725 displayer = cmdutil.show_changeset(ui, repo, opts)
726 726 count = 0
727 727 for n in o:
728 728 if limit is not None and count >= limit:
729 729 break
730 730 parents = [p for p in repo.changelog.parents(n) if p != nullid]
731 731 if opts.get('no_merges') and len(parents) == 2:
732 732 continue
733 733 count += 1
734 734 displayer.show(repo[n])
735 735 displayer.close()
736 736 cmdutil.outgoinghooks(ui, repo, other, opts, o)
737 737 recurse()
738 738 return 0 # exit code is zero since we found outgoing changes
739 739
740 740 def revert(repo, node, choose):
741 741 """revert changes to revision in node without updating dirstate"""
742 742 return mergemod.update(repo, node, False, True, choose)[3] > 0
743 743
744 744 def verify(repo):
745 745 """verify the consistency of a repository"""
746 746 ret = verifymod.verify(repo)
747 747
748 748 # Broken subrepo references in hidden csets don't seem worth worrying about,
749 749 # since they can't be pushed/pulled, and --hidden can be used if they are a
750 750 # concern.
751 751
752 752 # pathto() is needed for -R case
753 753 revs = repo.revs("filelog(%s)",
754 754 util.pathto(repo.root, repo.getcwd(), '.hgsubstate'))
755 755
756 756 if revs:
757 757 repo.ui.status(_('checking subrepo links\n'))
758 758 for rev in revs:
759 759 ctx = repo[rev]
760 760 try:
761 761 for subpath in ctx.substate:
762 762 ret = ctx.sub(subpath).verify() or ret
763 763 except Exception:
764 764 repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') %
765 765 node.short(ctx.node()))
766 766
767 767 return ret
768 768
769 769 def remoteui(src, opts):
770 770 'build a remote ui from ui or repo and opts'
771 771 if util.safehasattr(src, 'baseui'): # looks like a repository
772 772 dst = src.baseui.copy() # drop repo-specific config
773 773 src = src.ui # copy target options from repo
774 774 else: # assume it's a global ui object
775 775 dst = src.copy() # keep all global options
776 776
777 777 # copy ssh-specific options
778 778 for o in 'ssh', 'remotecmd':
779 779 v = opts.get(o) or src.config('ui', o)
780 780 if v:
781 781 dst.setconfig("ui", o, v, 'copied')
782 782
783 783 # copy bundle-specific options
784 784 r = src.config('bundle', 'mainreporoot')
785 785 if r:
786 786 dst.setconfig('bundle', 'mainreporoot', r, 'copied')
787 787
788 788 # copy selected local settings to the remote ui
789 789 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
790 790 for key, val in src.configitems(sect):
791 791 dst.setconfig(sect, key, val, 'copied')
792 792 v = src.config('web', 'cacerts')
793 793 if v == '!':
794 794 dst.setconfig('web', 'cacerts', v, 'copied')
795 795 elif v:
796 796 dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
797 797
798 798 return dst
@@ -1,1015 +1,1027 b''
1 1 Prepare repo a:
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg add a
7 7 $ hg commit -m test
8 8 $ echo first line > b
9 9 $ hg add b
10 10
11 11 Create a non-inlined filelog:
12 12
13 13 $ $PYTHON -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
14 14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
15 15 > cat data1 >> b
16 16 > hg commit -m test
17 17 > done
18 18
19 19 List files in store/data (should show a 'b.d'):
20 20
21 21 $ for i in .hg/store/data/*; do
22 22 > echo $i
23 23 > done
24 24 .hg/store/data/a.i
25 25 .hg/store/data/b.d
26 26 .hg/store/data/b.i
27 27
28 28 Trigger branchcache creation:
29 29
30 30 $ hg branches
31 31 default 10:a7949464abda
32 32 $ ls .hg/cache
33 33 branch2-served
34 34 rbc-names-v1
35 35 rbc-revs-v1
36 36
37 37 Default operation:
38 38
39 39 $ hg clone . ../b
40 40 updating to branch default
41 41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 $ cd ../b
43 43
44 44 Ensure branchcache got copied over:
45 45
46 46 $ ls .hg/cache
47 47 branch2-served
48 48
49 49 $ cat a
50 50 a
51 51 $ hg verify
52 52 checking changesets
53 53 checking manifests
54 54 crosschecking files in changesets and manifests
55 55 checking files
56 56 2 files, 11 changesets, 11 total revisions
57 57
58 58 Invalid dest '' must abort:
59 59
60 60 $ hg clone . ''
61 61 abort: empty destination path is not valid
62 62 [255]
63 63
64 64 No update, with debug option:
65 65
66 66 #if hardlink
67 67 $ hg --debug clone -U . ../c --config progress.debug=true
68 68 linking: 1
69 69 linking: 2
70 70 linking: 3
71 71 linking: 4
72 72 linking: 5
73 73 linking: 6
74 74 linking: 7
75 75 linking: 8
76 76 linked 8 files
77 77 #else
78 78 $ hg --debug clone -U . ../c --config progress.debug=true
79 79 linking: 1
80 80 copying: 2
81 81 copying: 3
82 82 copying: 4
83 83 copying: 5
84 84 copying: 6
85 85 copying: 7
86 86 copying: 8
87 87 copied 8 files
88 88 #endif
89 89 $ cd ../c
90 90
91 91 Ensure branchcache got copied over:
92 92
93 93 $ ls .hg/cache
94 94 branch2-served
95 95
96 96 $ cat a 2>/dev/null || echo "a not present"
97 97 a not present
98 98 $ hg verify
99 99 checking changesets
100 100 checking manifests
101 101 crosschecking files in changesets and manifests
102 102 checking files
103 103 2 files, 11 changesets, 11 total revisions
104 104
105 105 Default destination:
106 106
107 107 $ mkdir ../d
108 108 $ cd ../d
109 109 $ hg clone ../a
110 110 destination directory: a
111 111 updating to branch default
112 112 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 113 $ cd a
114 114 $ hg cat a
115 115 a
116 116 $ cd ../..
117 117
118 118 Check that we drop the 'file:' from the path before writing the .hgrc:
119 119
120 120 $ hg clone file:a e
121 121 updating to branch default
122 122 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 123 $ grep 'file:' e/.hg/hgrc
124 124 [1]
125 125
126 126 Check that path aliases are expanded:
127 127
128 128 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
129 129 $ hg -R f showconfig paths.default
130 130 $TESTTMP/a#0 (glob)
131 131
132 132 Use --pull:
133 133
134 134 $ hg clone --pull a g
135 135 requesting all changes
136 136 adding changesets
137 137 adding manifests
138 138 adding file changes
139 139 added 11 changesets with 11 changes to 2 files
140 140 updating to branch default
141 141 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 142 $ hg -R g verify
143 143 checking changesets
144 144 checking manifests
145 145 crosschecking files in changesets and manifests
146 146 checking files
147 147 2 files, 11 changesets, 11 total revisions
148 148
149 149 Invalid dest '' with --pull must abort (issue2528):
150 150
151 151 $ hg clone --pull a ''
152 152 abort: empty destination path is not valid
153 153 [255]
154 154
155 155 Clone to '.':
156 156
157 157 $ mkdir h
158 158 $ cd h
159 159 $ hg clone ../a .
160 160 updating to branch default
161 161 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 162 $ cd ..
163 163
164 164
165 165 *** Tests for option -u ***
166 166
167 167 Adding some more history to repo a:
168 168
169 169 $ cd a
170 170 $ hg tag ref1
171 171 $ echo the quick brown fox >a
172 172 $ hg ci -m "hacked default"
173 173 $ hg up ref1
174 174 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
175 175 $ hg branch stable
176 176 marked working directory as branch stable
177 177 (branches are permanent and global, did you want a bookmark?)
178 178 $ echo some text >a
179 179 $ hg ci -m "starting branch stable"
180 180 $ hg tag ref2
181 181 $ echo some more text >a
182 182 $ hg ci -m "another change for branch stable"
183 183 $ hg up ref2
184 184 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
185 185 $ hg parents
186 186 changeset: 13:e8ece76546a6
187 187 branch: stable
188 188 tag: ref2
189 189 parent: 10:a7949464abda
190 190 user: test
191 191 date: Thu Jan 01 00:00:00 1970 +0000
192 192 summary: starting branch stable
193 193
194 194
195 195 Repo a has two heads:
196 196
197 197 $ hg heads
198 198 changeset: 15:0aae7cf88f0d
199 199 branch: stable
200 200 tag: tip
201 201 user: test
202 202 date: Thu Jan 01 00:00:00 1970 +0000
203 203 summary: another change for branch stable
204 204
205 205 changeset: 12:f21241060d6a
206 206 user: test
207 207 date: Thu Jan 01 00:00:00 1970 +0000
208 208 summary: hacked default
209 209
210 210
211 211 $ cd ..
212 212
213 213
214 214 Testing --noupdate with --updaterev (must abort):
215 215
216 216 $ hg clone --noupdate --updaterev 1 a ua
217 217 abort: cannot specify both --noupdate and --updaterev
218 218 [255]
219 219
220 220
221 221 Testing clone -u:
222 222
223 223 $ hg clone -u . a ua
224 224 updating to branch stable
225 225 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 226
227 227 Repo ua has both heads:
228 228
229 229 $ hg -R ua heads
230 230 changeset: 15:0aae7cf88f0d
231 231 branch: stable
232 232 tag: tip
233 233 user: test
234 234 date: Thu Jan 01 00:00:00 1970 +0000
235 235 summary: another change for branch stable
236 236
237 237 changeset: 12:f21241060d6a
238 238 user: test
239 239 date: Thu Jan 01 00:00:00 1970 +0000
240 240 summary: hacked default
241 241
242 242
243 243 Same revision checked out in repo a and ua:
244 244
245 245 $ hg -R a parents --template "{node|short}\n"
246 246 e8ece76546a6
247 247 $ hg -R ua parents --template "{node|short}\n"
248 248 e8ece76546a6
249 249
250 250 $ rm -r ua
251 251
252 252
253 253 Testing clone --pull -u:
254 254
255 255 $ hg clone --pull -u . a ua
256 256 requesting all changes
257 257 adding changesets
258 258 adding manifests
259 259 adding file changes
260 260 added 16 changesets with 16 changes to 3 files (+1 heads)
261 261 updating to branch stable
262 262 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 263
264 264 Repo ua has both heads:
265 265
266 266 $ hg -R ua heads
267 267 changeset: 15:0aae7cf88f0d
268 268 branch: stable
269 269 tag: tip
270 270 user: test
271 271 date: Thu Jan 01 00:00:00 1970 +0000
272 272 summary: another change for branch stable
273 273
274 274 changeset: 12:f21241060d6a
275 275 user: test
276 276 date: Thu Jan 01 00:00:00 1970 +0000
277 277 summary: hacked default
278 278
279 279
280 280 Same revision checked out in repo a and ua:
281 281
282 282 $ hg -R a parents --template "{node|short}\n"
283 283 e8ece76546a6
284 284 $ hg -R ua parents --template "{node|short}\n"
285 285 e8ece76546a6
286 286
287 287 $ rm -r ua
288 288
289 289
290 290 Testing clone -u <branch>:
291 291
292 292 $ hg clone -u stable a ua
293 293 updating to branch stable
294 294 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
295 295
296 296 Repo ua has both heads:
297 297
298 298 $ hg -R ua heads
299 299 changeset: 15:0aae7cf88f0d
300 300 branch: stable
301 301 tag: tip
302 302 user: test
303 303 date: Thu Jan 01 00:00:00 1970 +0000
304 304 summary: another change for branch stable
305 305
306 306 changeset: 12:f21241060d6a
307 307 user: test
308 308 date: Thu Jan 01 00:00:00 1970 +0000
309 309 summary: hacked default
310 310
311 311
312 312 Branch 'stable' is checked out:
313 313
314 314 $ hg -R ua parents
315 315 changeset: 15:0aae7cf88f0d
316 316 branch: stable
317 317 tag: tip
318 318 user: test
319 319 date: Thu Jan 01 00:00:00 1970 +0000
320 320 summary: another change for branch stable
321 321
322 322
323 323 $ rm -r ua
324 324
325 325
326 326 Testing default checkout:
327 327
328 328 $ hg clone a ua
329 329 updating to branch default
330 330 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 331
332 332 Repo ua has both heads:
333 333
334 334 $ hg -R ua heads
335 335 changeset: 15:0aae7cf88f0d
336 336 branch: stable
337 337 tag: tip
338 338 user: test
339 339 date: Thu Jan 01 00:00:00 1970 +0000
340 340 summary: another change for branch stable
341 341
342 342 changeset: 12:f21241060d6a
343 343 user: test
344 344 date: Thu Jan 01 00:00:00 1970 +0000
345 345 summary: hacked default
346 346
347 347
348 348 Branch 'default' is checked out:
349 349
350 350 $ hg -R ua parents
351 351 changeset: 12:f21241060d6a
352 352 user: test
353 353 date: Thu Jan 01 00:00:00 1970 +0000
354 354 summary: hacked default
355 355
356 356 Test clone with a branch named "@" (issue3677)
357 357
358 358 $ hg -R ua branch @
359 359 marked working directory as branch @
360 360 $ hg -R ua commit -m 'created branch @'
361 361 $ hg clone ua atbranch
362 362 updating to branch default
363 363 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
364 364 $ hg -R atbranch heads
365 365 changeset: 16:798b6d97153e
366 366 branch: @
367 367 tag: tip
368 368 parent: 12:f21241060d6a
369 369 user: test
370 370 date: Thu Jan 01 00:00:00 1970 +0000
371 371 summary: created branch @
372 372
373 373 changeset: 15:0aae7cf88f0d
374 374 branch: stable
375 375 user: test
376 376 date: Thu Jan 01 00:00:00 1970 +0000
377 377 summary: another change for branch stable
378 378
379 379 changeset: 12:f21241060d6a
380 380 user: test
381 381 date: Thu Jan 01 00:00:00 1970 +0000
382 382 summary: hacked default
383 383
384 384 $ hg -R atbranch parents
385 385 changeset: 12:f21241060d6a
386 386 user: test
387 387 date: Thu Jan 01 00:00:00 1970 +0000
388 388 summary: hacked default
389 389
390 390
391 391 $ rm -r ua atbranch
392 392
393 393
394 394 Testing #<branch>:
395 395
396 396 $ hg clone -u . a#stable ua
397 397 adding changesets
398 398 adding manifests
399 399 adding file changes
400 400 added 14 changesets with 14 changes to 3 files
401 401 updating to branch stable
402 402 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
403 403
404 404 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
405 405
406 406 $ hg -R ua heads
407 407 changeset: 13:0aae7cf88f0d
408 408 branch: stable
409 409 tag: tip
410 410 user: test
411 411 date: Thu Jan 01 00:00:00 1970 +0000
412 412 summary: another change for branch stable
413 413
414 414 changeset: 10:a7949464abda
415 415 user: test
416 416 date: Thu Jan 01 00:00:00 1970 +0000
417 417 summary: test
418 418
419 419
420 420 Same revision checked out in repo a and ua:
421 421
422 422 $ hg -R a parents --template "{node|short}\n"
423 423 e8ece76546a6
424 424 $ hg -R ua parents --template "{node|short}\n"
425 425 e8ece76546a6
426 426
427 427 $ rm -r ua
428 428
429 429
430 430 Testing -u -r <branch>:
431 431
432 432 $ hg clone -u . -r stable a ua
433 433 adding changesets
434 434 adding manifests
435 435 adding file changes
436 436 added 14 changesets with 14 changes to 3 files
437 437 updating to branch stable
438 438 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
439 439
440 440 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
441 441
442 442 $ hg -R ua heads
443 443 changeset: 13:0aae7cf88f0d
444 444 branch: stable
445 445 tag: tip
446 446 user: test
447 447 date: Thu Jan 01 00:00:00 1970 +0000
448 448 summary: another change for branch stable
449 449
450 450 changeset: 10:a7949464abda
451 451 user: test
452 452 date: Thu Jan 01 00:00:00 1970 +0000
453 453 summary: test
454 454
455 455
456 456 Same revision checked out in repo a and ua:
457 457
458 458 $ hg -R a parents --template "{node|short}\n"
459 459 e8ece76546a6
460 460 $ hg -R ua parents --template "{node|short}\n"
461 461 e8ece76546a6
462 462
463 463 $ rm -r ua
464 464
465 465
466 466 Testing -r <branch>:
467 467
468 468 $ hg clone -r stable a ua
469 469 adding changesets
470 470 adding manifests
471 471 adding file changes
472 472 added 14 changesets with 14 changes to 3 files
473 473 updating to branch stable
474 474 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 475
476 476 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
477 477
478 478 $ hg -R ua heads
479 479 changeset: 13:0aae7cf88f0d
480 480 branch: stable
481 481 tag: tip
482 482 user: test
483 483 date: Thu Jan 01 00:00:00 1970 +0000
484 484 summary: another change for branch stable
485 485
486 486 changeset: 10:a7949464abda
487 487 user: test
488 488 date: Thu Jan 01 00:00:00 1970 +0000
489 489 summary: test
490 490
491 491
492 492 Branch 'stable' is checked out:
493 493
494 494 $ hg -R ua parents
495 495 changeset: 13:0aae7cf88f0d
496 496 branch: stable
497 497 tag: tip
498 498 user: test
499 499 date: Thu Jan 01 00:00:00 1970 +0000
500 500 summary: another change for branch stable
501 501
502 502
503 503 $ rm -r ua
504 504
505 505
506 506 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
507 507 iterable in addbranchrevs()
508 508
509 509 $ cat <<EOF > simpleclone.py
510 510 > from mercurial import ui, hg
511 511 > myui = ui.ui()
512 512 > repo = hg.repository(myui, 'a')
513 513 > hg.clone(myui, {}, repo, dest="ua")
514 514 > EOF
515 515
516 516 $ python simpleclone.py
517 517 updating to branch default
518 518 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
519 519
520 520 $ rm -r ua
521 521
522 522 $ cat <<EOF > branchclone.py
523 523 > from mercurial import ui, hg, extensions
524 524 > myui = ui.ui()
525 525 > extensions.loadall(myui)
526 526 > repo = hg.repository(myui, 'a')
527 527 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
528 528 > EOF
529 529
530 530 $ python branchclone.py
531 531 adding changesets
532 532 adding manifests
533 533 adding file changes
534 534 added 14 changesets with 14 changes to 3 files
535 535 updating to branch stable
536 536 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
537 537 $ rm -r ua
538 538
539 539
540 540 Test clone with special '@' bookmark:
541 541 $ cd a
542 542 $ hg bookmark -r a7949464abda @ # branch point of stable from default
543 543 $ hg clone . ../i
544 544 updating to bookmark @
545 545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 546 $ hg id -i ../i
547 547 a7949464abda
548 548 $ rm -r ../i
549 549
550 550 $ hg bookmark -f -r stable @
551 551 $ hg bookmarks
552 552 @ 15:0aae7cf88f0d
553 553 $ hg clone . ../i
554 554 updating to bookmark @ on branch stable
555 555 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 556 $ hg id -i ../i
557 557 0aae7cf88f0d
558 558 $ cd "$TESTTMP"
559 559
560 560
561 561 Testing failures:
562 562
563 563 $ mkdir fail
564 564 $ cd fail
565 565
566 566 No local source
567 567
568 568 $ hg clone a b
569 569 abort: repository a not found!
570 570 [255]
571 571
572 572 No remote source
573 573
574 574 #if windows
575 575 $ hg clone http://127.0.0.1:3121/a b
576 576 abort: error: * (glob)
577 577 [255]
578 578 #else
579 579 $ hg clone http://127.0.0.1:3121/a b
580 580 abort: error: *refused* (glob)
581 581 [255]
582 582 #endif
583 583 $ rm -rf b # work around bug with http clone
584 584
585 585
586 586 #if unix-permissions no-root
587 587
588 588 Inaccessible source
589 589
590 590 $ mkdir a
591 591 $ chmod 000 a
592 592 $ hg clone a b
593 593 abort: repository a not found!
594 594 [255]
595 595
596 596 Inaccessible destination
597 597
598 598 $ hg init b
599 599 $ cd b
600 600 $ hg clone . ../a
601 601 abort: Permission denied: '../a'
602 602 [255]
603 603 $ cd ..
604 604 $ chmod 700 a
605 605 $ rm -r a b
606 606
607 607 #endif
608 608
609 609
610 610 #if fifo
611 611
612 612 Source of wrong type
613 613
614 614 $ mkfifo a
615 615 $ hg clone a b
616 616 abort: repository a not found!
617 617 [255]
618 618 $ rm a
619 619
620 620 #endif
621 621
622 622 Default destination, same directory
623 623
624 624 $ hg init q
625 625 $ hg clone q
626 626 destination directory: q
627 627 abort: destination 'q' is not empty
628 628 [255]
629 629
630 630 destination directory not empty
631 631
632 632 $ mkdir a
633 633 $ echo stuff > a/a
634 634 $ hg clone q a
635 635 abort: destination 'a' is not empty
636 636 [255]
637 637
638 638
639 639 #if unix-permissions no-root
640 640
641 641 leave existing directory in place after clone failure
642 642
643 643 $ hg init c
644 644 $ cd c
645 645 $ echo c > c
646 646 $ hg commit -A -m test
647 647 adding c
648 648 $ chmod -rx .hg/store/data
649 649 $ cd ..
650 650 $ mkdir d
651 651 $ hg clone c d 2> err
652 652 [255]
653 653 $ test -d d
654 654 $ test -d d/.hg
655 655 [1]
656 656
657 657 re-enable perm to allow deletion
658 658
659 659 $ chmod +rx c/.hg/store/data
660 660
661 661 #endif
662 662
663 663 $ cd ..
664 664
665 665 Test clone from the repository in (emulated) revlog format 0 (issue4203):
666 666
667 667 $ mkdir issue4203
668 668 $ mkdir -p src/.hg
669 669 $ echo foo > src/foo
670 670 $ hg -R src add src/foo
671 671 $ hg -R src commit -m '#0'
672 672 $ hg -R src log -q
673 673 0:e1bab28bca43
674 674 $ hg clone -U -q src dst
675 675 $ hg -R dst log -q
676 676 0:e1bab28bca43
677 677
678 678 Create repositories to test auto sharing functionality
679 679
680 680 $ cat >> $HGRCPATH << EOF
681 681 > [extensions]
682 682 > share=
683 683 > EOF
684 684
685 685 $ hg init empty
686 686 $ hg init source1a
687 687 $ cd source1a
688 688 $ echo initial1 > foo
689 689 $ hg -q commit -A -m initial
690 690 $ echo second > foo
691 691 $ hg commit -m second
692 692 $ cd ..
693 693
694 694 $ hg init filteredrev0
695 695 $ cd filteredrev0
696 696 $ cat >> .hg/hgrc << EOF
697 697 > [experimental]
698 698 > evolution=createmarkers
699 699 > EOF
700 700 $ echo initial1 > foo
701 701 $ hg -q commit -A -m initial0
702 702 $ hg -q up -r null
703 703 $ echo initial2 > foo
704 704 $ hg -q commit -A -m initial1
705 705 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
706 706 $ cd ..
707 707
708 708 $ hg -q clone --pull source1a source1b
709 709 $ cd source1a
710 710 $ hg bookmark bookA
711 711 $ echo 1a > foo
712 712 $ hg commit -m 1a
713 713 $ cd ../source1b
714 714 $ hg -q up -r 0
715 715 $ echo head1 > foo
716 716 $ hg commit -m head1
717 717 created new head
718 718 $ hg bookmark head1
719 719 $ hg -q up -r 0
720 720 $ echo head2 > foo
721 721 $ hg commit -m head2
722 722 created new head
723 723 $ hg bookmark head2
724 724 $ hg -q up -r 0
725 725 $ hg branch branch1
726 726 marked working directory as branch branch1
727 727 (branches are permanent and global, did you want a bookmark?)
728 728 $ echo branch1 > foo
729 729 $ hg commit -m branch1
730 730 $ hg -q up -r 0
731 731 $ hg branch branch2
732 732 marked working directory as branch branch2
733 733 $ echo branch2 > foo
734 734 $ hg commit -m branch2
735 735 $ cd ..
736 736 $ hg init source2
737 737 $ cd source2
738 738 $ echo initial2 > foo
739 739 $ hg -q commit -A -m initial2
740 740 $ echo second > foo
741 741 $ hg commit -m second
742 742 $ cd ..
743 743
744 744 Clone with auto share from an empty repo should not result in share
745 745
746 746 $ mkdir share
747 747 $ hg --config share.pool=share clone empty share-empty
748 748 (not using pooled storage: remote appears to be empty)
749 749 updating to branch default
750 750 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
751 751 $ ls share
752 752 $ test -d share-empty/.hg/store
753 753 $ test -f share-empty/.hg/sharedpath
754 754 [1]
755 755
756 756 Clone with auto share from a repo with filtered revision 0 should not result in share
757 757
758 758 $ hg --config share.pool=share clone filteredrev0 share-filtered
759 759 (not using pooled storage: unable to resolve identity of remote)
760 760 requesting all changes
761 761 adding changesets
762 762 adding manifests
763 763 adding file changes
764 764 added 1 changesets with 1 changes to 1 files
765 765 updating to branch default
766 766 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
767 767
768 768 Clone from repo with content should result in shared store being created
769 769
770 770 $ hg --config share.pool=share clone source1a share-dest1a
771 771 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
772 772 requesting all changes
773 773 adding changesets
774 774 adding manifests
775 775 adding file changes
776 776 added 3 changesets with 3 changes to 1 files
777 777 updating working directory
778 778 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
779 779 searching for changes
780 780 no changes found
781 781 adding remote bookmark bookA
782 782
783 783 The shared repo should have been created
784 784
785 785 $ ls share
786 786 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
787 787
788 788 The destination should point to it
789 789
790 790 $ cat share-dest1a/.hg/sharedpath; echo
791 791 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
792 792
793 793 The destination should have bookmarks
794 794
795 795 $ hg -R share-dest1a bookmarks
796 796 bookA 2:e5bfe23c0b47
797 797
798 798 The default path should be the remote, not the share
799 799
800 800 $ hg -R share-dest1a config paths.default
801 801 $TESTTMP/source1a (glob)
802 802
803 803 Clone with existing share dir should result in pull + share
804 804
805 805 $ hg --config share.pool=share clone source1b share-dest1b
806 806 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
807 807 updating working directory
808 808 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
809 809 searching for changes
810 810 adding changesets
811 811 adding manifests
812 812 adding file changes
813 813 added 4 changesets with 4 changes to 1 files (+4 heads)
814 814 adding remote bookmark head1
815 815 adding remote bookmark head2
816 816
817 817 $ ls share
818 818 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
819 819
820 820 $ cat share-dest1b/.hg/sharedpath; echo
821 821 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg (glob)
822 822
823 823 We only get bookmarks from the remote, not everything in the share
824 824
825 825 $ hg -R share-dest1b bookmarks
826 826 head1 3:4a8dc1ab4c13
827 827 head2 4:99f71071f117
828 828
829 829 Default path should be source, not share.
830 830
831 831 $ hg -R share-dest1b config paths.default
832 832 $TESTTMP/source1a (glob)
833 833
834 834 Clone from unrelated repo should result in new share
835 835
836 836 $ hg --config share.pool=share clone source2 share-dest2
837 837 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
838 838 requesting all changes
839 839 adding changesets
840 840 adding manifests
841 841 adding file changes
842 842 added 2 changesets with 2 changes to 1 files
843 843 updating working directory
844 844 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
845 845 searching for changes
846 846 no changes found
847 847
848 848 $ ls share
849 849 22aeff664783fd44c6d9b435618173c118c3448e
850 850 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
851 851
852 852 remote naming mode works as advertised
853 853
854 854 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
855 855 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
856 856 requesting all changes
857 857 adding changesets
858 858 adding manifests
859 859 adding file changes
860 860 added 3 changesets with 3 changes to 1 files
861 861 updating working directory
862 862 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
863 863 searching for changes
864 864 no changes found
865 865 adding remote bookmark bookA
866 866
867 867 $ ls shareremote
868 868 195bb1fcdb595c14a6c13e0269129ed78f6debde
869 869
870 870 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
871 871 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
872 872 requesting all changes
873 873 adding changesets
874 874 adding manifests
875 875 adding file changes
876 876 added 6 changesets with 6 changes to 1 files (+4 heads)
877 877 updating working directory
878 878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 879 searching for changes
880 880 no changes found
881 881 adding remote bookmark head1
882 882 adding remote bookmark head2
883 883
884 884 $ ls shareremote
885 885 195bb1fcdb595c14a6c13e0269129ed78f6debde
886 886 c0d4f83847ca2a873741feb7048a45085fd47c46
887 887
888 888 request to clone a single revision is respected in sharing mode
889 889
890 890 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
891 891 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
892 892 adding changesets
893 893 adding manifests
894 894 adding file changes
895 895 added 2 changesets with 2 changes to 1 files
896 896 updating working directory
897 897 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
898 898 no changes found
899 899 adding remote bookmark head1
900 900
901 901 $ hg -R share-1arev log -G
902 902 @ changeset: 1:4a8dc1ab4c13
903 903 | bookmark: head1
904 904 | tag: tip
905 905 | user: test
906 906 | date: Thu Jan 01 00:00:00 1970 +0000
907 907 | summary: head1
908 908 |
909 909 o changeset: 0:b5f04eac9d8f
910 910 user: test
911 911 date: Thu Jan 01 00:00:00 1970 +0000
912 912 summary: initial
913 913
914 914
915 915 making another clone should only pull down requested rev
916 916
917 917 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
918 918 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
919 919 updating working directory
920 920 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
921 921 searching for changes
922 922 adding changesets
923 923 adding manifests
924 924 adding file changes
925 925 added 1 changesets with 1 changes to 1 files (+1 heads)
926 926 adding remote bookmark head1
927 927 adding remote bookmark head2
928 928
929 929 $ hg -R share-1brev log -G
930 930 o changeset: 2:99f71071f117
931 931 | bookmark: head2
932 932 | tag: tip
933 933 | parent: 0:b5f04eac9d8f
934 934 | user: test
935 935 | date: Thu Jan 01 00:00:00 1970 +0000
936 936 | summary: head2
937 937 |
938 938 | @ changeset: 1:4a8dc1ab4c13
939 939 |/ bookmark: head1
940 940 | user: test
941 941 | date: Thu Jan 01 00:00:00 1970 +0000
942 942 | summary: head1
943 943 |
944 944 o changeset: 0:b5f04eac9d8f
945 945 user: test
946 946 date: Thu Jan 01 00:00:00 1970 +0000
947 947 summary: initial
948 948
949 949
950 950 Request to clone a single branch is respected in sharing mode
951 951
952 952 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
953 953 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
954 954 adding changesets
955 955 adding manifests
956 956 adding file changes
957 957 added 2 changesets with 2 changes to 1 files
958 958 updating working directory
959 959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 960 no changes found
961 961
962 962 $ hg -R share-1bbranch1 log -G
963 963 o changeset: 1:5f92a6c1a1b1
964 964 | branch: branch1
965 965 | tag: tip
966 966 | user: test
967 967 | date: Thu Jan 01 00:00:00 1970 +0000
968 968 | summary: branch1
969 969 |
970 970 @ changeset: 0:b5f04eac9d8f
971 971 user: test
972 972 date: Thu Jan 01 00:00:00 1970 +0000
973 973 summary: initial
974 974
975 975
976 976 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
977 977 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
978 978 updating working directory
979 979 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
980 980 searching for changes
981 981 adding changesets
982 982 adding manifests
983 983 adding file changes
984 984 added 1 changesets with 1 changes to 1 files (+1 heads)
985 985
986 986 $ hg -R share-1bbranch2 log -G
987 987 o changeset: 2:6bacf4683960
988 988 | branch: branch2
989 989 | tag: tip
990 990 | parent: 0:b5f04eac9d8f
991 991 | user: test
992 992 | date: Thu Jan 01 00:00:00 1970 +0000
993 993 | summary: branch2
994 994 |
995 995 | o changeset: 1:5f92a6c1a1b1
996 996 |/ branch: branch1
997 997 | user: test
998 998 | date: Thu Jan 01 00:00:00 1970 +0000
999 999 | summary: branch1
1000 1000 |
1001 1001 @ changeset: 0:b5f04eac9d8f
1002 1002 user: test
1003 1003 date: Thu Jan 01 00:00:00 1970 +0000
1004 1004 summary: initial
1005 1005
1006 1006
1007 1007 -U is respected in share clone mode
1008 1008
1009 1009 $ hg --config share.pool=share clone -U source1a share-1anowc
1010 1010 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1011 1011 searching for changes
1012 1012 no changes found
1013 1013 adding remote bookmark bookA
1014 1014
1015 1015 $ ls share-1anowc
1016
1017 Test that auto sharing doesn't cause failure of "hg clone local remote"
1018
1019 $ cd $TESTTMP
1020 $ hg -R a id -r 0
1021 acb14030fe0a
1022 $ hg id -R remote -r 0
1023 abort: there is no Mercurial repository here (.hg not found)
1024 [255]
1025 $ hg --config share.pool=share -q clone -e "python \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1026 $ hg -R remote id -r 0
1027 acb14030fe0a
General Comments 0
You need to be logged in to leave comments. Login now