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