4 # |
4 # |
5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 from i18n import _ |
8 from i18n import _ |
9 from node import hex |
9 from node import hex, nullid |
10 import errno |
10 import errno |
11 import util, scmutil, changegroup |
11 import util, scmutil, changegroup |
12 import discovery, phases, obsolete, bookmarks |
12 import discovery, phases, obsolete, bookmarks |
13 |
13 |
14 |
14 |
370 continue |
370 continue |
371 if remote.pushkey('bookmarks', b, dcid, scid): |
371 if remote.pushkey('bookmarks', b, dcid, scid): |
372 ui.status(_("updating bookmark %s\n") % b) |
372 ui.status(_("updating bookmark %s\n") % b) |
373 else: |
373 else: |
374 ui.warn(_('updating bookmark %s failed!\n') % b) |
374 ui.warn(_('updating bookmark %s failed!\n') % b) |
|
375 |
|
376 |
|
377 def pull(repo, remote, heads=None, force=False): |
|
378 if remote.local(): |
|
379 missing = set(remote.requirements) - repo.supported |
|
380 if missing: |
|
381 msg = _("required features are not" |
|
382 " supported in the destination:" |
|
383 " %s") % (', '.join(sorted(missing))) |
|
384 raise util.Abort(msg) |
|
385 |
|
386 # don't open transaction for nothing or you break future useful |
|
387 # rollback call |
|
388 tr = None |
|
389 trname = 'pull\n' + util.hidepassword(remote.url()) |
|
390 lock = repo.lock() |
|
391 try: |
|
392 tmp = discovery.findcommonincoming(repo.unfiltered(), remote, |
|
393 heads=heads, force=force) |
|
394 common, fetch, rheads = tmp |
|
395 if not fetch: |
|
396 repo.ui.status(_("no changes found\n")) |
|
397 result = 0 |
|
398 else: |
|
399 tr = repo.transaction(trname) |
|
400 if heads is None and list(common) == [nullid]: |
|
401 repo.ui.status(_("requesting all changes\n")) |
|
402 elif heads is None and remote.capable('changegroupsubset'): |
|
403 # issue1320, avoid a race if remote changed after discovery |
|
404 heads = rheads |
|
405 |
|
406 if remote.capable('getbundle'): |
|
407 # TODO: get bundlecaps from remote |
|
408 cg = remote.getbundle('pull', common=common, |
|
409 heads=heads or rheads) |
|
410 elif heads is None: |
|
411 cg = remote.changegroup(fetch, 'pull') |
|
412 elif not remote.capable('changegroupsubset'): |
|
413 raise util.Abort(_("partial pull cannot be done because " |
|
414 "other repository doesn't support " |
|
415 "changegroupsubset.")) |
|
416 else: |
|
417 cg = remote.changegroupsubset(fetch, heads, 'pull') |
|
418 result = repo.addchangegroup(cg, 'pull', remote.url()) |
|
419 |
|
420 # compute target subset |
|
421 if heads is None: |
|
422 # We pulled every thing possible |
|
423 # sync on everything common |
|
424 subset = common + rheads |
|
425 else: |
|
426 # We pulled a specific subset |
|
427 # sync on this subset |
|
428 subset = heads |
|
429 |
|
430 # Get remote phases data from remote |
|
431 remotephases = remote.listkeys('phases') |
|
432 publishing = bool(remotephases.get('publishing', False)) |
|
433 if remotephases and not publishing: |
|
434 # remote is new and unpublishing |
|
435 pheads, _dr = phases.analyzeremotephases(repo, subset, |
|
436 remotephases) |
|
437 phases.advanceboundary(repo, phases.public, pheads) |
|
438 phases.advanceboundary(repo, phases.draft, subset) |
|
439 else: |
|
440 # Remote is old or publishing all common changesets |
|
441 # should be seen as public |
|
442 phases.advanceboundary(repo, phases.public, subset) |
|
443 |
|
444 def gettransaction(): |
|
445 if tr is None: |
|
446 return repo.transaction(trname) |
|
447 return tr |
|
448 |
|
449 obstr = obsolete.syncpull(repo, remote, gettransaction) |
|
450 if obstr is not None: |
|
451 tr = obstr |
|
452 |
|
453 if tr is not None: |
|
454 tr.close() |
|
455 finally: |
|
456 if tr is not None: |
|
457 tr.release() |
|
458 lock.release() |
|
459 |
|
460 return result |