Mercurial > hg
comparison mercurial/exchange.py @ 28977:740156eedf2c stable 3.8-rc
merge default into stable for 3.8 code freeze
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 16 Apr 2016 18:06:48 -0500 |
parents | 032c4c2f802a |
children | 9dc27a334fb1 |
comparison
equal
deleted
inserted
replaced
28665:2d39f987f0ba | 28977:740156eedf2c |
---|---|
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 __future__ import absolute_import | 8 from __future__ import absolute_import |
9 | 9 |
10 import errno | 10 import errno |
11 import urllib | |
12 import urllib2 | |
13 | 11 |
14 from .i18n import _ | 12 from .i18n import _ |
15 from .node import ( | 13 from .node import ( |
16 hex, | 14 hex, |
17 nullid, | 15 nullid, |
33 tags, | 31 tags, |
34 url as urlmod, | 32 url as urlmod, |
35 util, | 33 util, |
36 ) | 34 ) |
37 | 35 |
36 urlerr = util.urlerr | |
37 urlreq = util.urlreq | |
38 | |
38 # Maps bundle compression human names to internal representation. | 39 # Maps bundle compression human names to internal representation. |
39 _bundlespeccompressions = {'none': None, | 40 _bundlespeccompressions = {'none': None, |
40 'bzip2': 'BZ', | 41 'bzip2': 'BZ', |
41 'gzip': 'GZ', | 42 'gzip': 'GZ', |
42 } | 43 } |
95 raise error.InvalidBundleSpecification( | 96 raise error.InvalidBundleSpecification( |
96 _('invalid bundle specification: ' | 97 _('invalid bundle specification: ' |
97 'missing "=" in parameter: %s') % p) | 98 'missing "=" in parameter: %s') % p) |
98 | 99 |
99 key, value = p.split('=', 1) | 100 key, value = p.split('=', 1) |
100 key = urllib.unquote(key) | 101 key = urlreq.unquote(key) |
101 value = urllib.unquote(value) | 102 value = urlreq.unquote(value) |
102 params[key] = value | 103 params[key] = value |
103 | 104 |
104 return version, params | 105 return version, params |
105 | 106 |
106 | 107 |
234 | 235 |
235 return '%s-%s' % (comp, version) | 236 return '%s-%s' % (comp, version) |
236 elif isinstance(b, streamclone.streamcloneapplier): | 237 elif isinstance(b, streamclone.streamcloneapplier): |
237 requirements = streamclone.readbundle1header(fh)[2] | 238 requirements = streamclone.readbundle1header(fh)[2] |
238 params = 'requirements=%s' % ','.join(sorted(requirements)) | 239 params = 'requirements=%s' % ','.join(sorted(requirements)) |
239 return 'none-packed1;%s' % urllib.quote(params) | 240 return 'none-packed1;%s' % urlreq.quote(params) |
240 else: | 241 else: |
241 raise error.Abort(_('unknown bundle type: %s') % b) | 242 raise error.Abort(_('unknown bundle type: %s') % b) |
242 | 243 |
243 def buildobsmarkerspart(bundler, markers): | 244 def buildobsmarkerspart(bundler, markers): |
244 """add an obsmarker part to the bundler with <markers> | 245 """add an obsmarker part to the bundler with <markers> |
264 | 265 |
265 | 266 |
266 class pushoperation(object): | 267 class pushoperation(object): |
267 """A object that represent a single push operation | 268 """A object that represent a single push operation |
268 | 269 |
269 It purpose is to carry push related state and very common operation. | 270 Its purpose is to carry push related state and very common operations. |
270 | 271 |
271 A new should be created at the beginning of each push and discarded | 272 A new pushoperation should be created at the beginning of each push and |
272 afterward. | 273 discarded afterward. |
273 """ | 274 """ |
274 | 275 |
275 def __init__(self, repo, remote, force=False, revs=None, newbranch=False, | 276 def __init__(self, repo, remote, force=False, revs=None, newbranch=False, |
276 bookmarks=()): | 277 bookmarks=()): |
277 # repo we push from | 278 # repo we push from |
574 if pushop.revs: | 575 if pushop.revs: |
575 revnums = map(repo.changelog.rev, pushop.revs) | 576 revnums = map(repo.changelog.rev, pushop.revs) |
576 ancestors = repo.changelog.ancestors(revnums, inclusive=True) | 577 ancestors = repo.changelog.ancestors(revnums, inclusive=True) |
577 remotebookmark = remote.listkeys('bookmarks') | 578 remotebookmark = remote.listkeys('bookmarks') |
578 | 579 |
579 explicit = set(pushop.bookmarks) | 580 explicit = set([repo._bookmarks.expandname(bookmark) |
581 for bookmark in pushop.bookmarks]) | |
580 | 582 |
581 comp = bookmod.compare(repo, repo._bookmarks, remotebookmark, srchex=hex) | 583 comp = bookmod.compare(repo, repo._bookmarks, remotebookmark, srchex=hex) |
582 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp | 584 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp |
583 for b, scid, dcid in advsrc: | 585 for b, scid, dcid in advsrc: |
584 if b in explicit: | 586 if b in explicit: |
691 return | 693 return |
692 pushop.stepsdone.add('changesets') | 694 pushop.stepsdone.add('changesets') |
693 # Send known heads to the server for race detection. | 695 # Send known heads to the server for race detection. |
694 if not _pushcheckoutgoing(pushop): | 696 if not _pushcheckoutgoing(pushop): |
695 return | 697 return |
696 pushop.repo.prepushoutgoinghooks(pushop.repo, | 698 pushop.repo.prepushoutgoinghooks(pushop) |
697 pushop.remote, | |
698 pushop.outgoing) | |
699 | 699 |
700 _pushb2ctxcheckheads(pushop, bundler) | 700 _pushb2ctxcheckheads(pushop, bundler) |
701 | 701 |
702 b2caps = bundle2.bundle2caps(pushop.remote) | 702 b2caps = bundle2.bundle2caps(pushop.remote) |
703 version = None | 703 version = '01' |
704 cgversions = b2caps.get('changegroup') | 704 cgversions = b2caps.get('changegroup') |
705 if not cgversions: # 3.1 and 3.2 ship with an empty value | 705 if cgversions: # 3.1 and 3.2 ship with an empty value |
706 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', | |
707 pushop.outgoing) | |
708 else: | |
709 cgversions = [v for v in cgversions | 706 cgversions = [v for v in cgversions |
710 if v in changegroup.supportedoutgoingversions( | 707 if v in changegroup.supportedoutgoingversions( |
711 pushop.repo)] | 708 pushop.repo)] |
712 if not cgversions: | 709 if not cgversions: |
713 raise ValueError(_('no common changegroup version')) | 710 raise ValueError(_('no common changegroup version')) |
714 version = max(cgversions) | 711 version = max(cgversions) |
715 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', | 712 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', |
716 pushop.outgoing, | 713 pushop.outgoing, |
717 version=version) | 714 version=version) |
718 cgpart = bundler.newpart('changegroup', data=cg) | 715 cgpart = bundler.newpart('changegroup', data=cg) |
719 if version is not None: | 716 if cgversions: |
720 cgpart.addparam('version', version) | 717 cgpart.addparam('version', version) |
721 if 'treemanifest' in pushop.repo.requirements: | 718 if 'treemanifest' in pushop.repo.requirements: |
722 cgpart.addparam('treemanifest', '1') | 719 cgpart.addparam('treemanifest', '1') |
723 def handlereply(op): | 720 def handlereply(op): |
724 """extract addchangegroup returns from server reply""" | 721 """extract addchangegroup returns from server reply""" |
884 if 'changesets' in pushop.stepsdone: | 881 if 'changesets' in pushop.stepsdone: |
885 return | 882 return |
886 pushop.stepsdone.add('changesets') | 883 pushop.stepsdone.add('changesets') |
887 if not _pushcheckoutgoing(pushop): | 884 if not _pushcheckoutgoing(pushop): |
888 return | 885 return |
889 pushop.repo.prepushoutgoinghooks(pushop.repo, | 886 pushop.repo.prepushoutgoinghooks(pushop) |
890 pushop.remote, | |
891 pushop.outgoing) | |
892 outgoing = pushop.outgoing | 887 outgoing = pushop.outgoing |
893 unbundle = pushop.remote.capable('unbundle') | 888 unbundle = pushop.remote.capable('unbundle') |
894 # TODO: get bundlecaps from remote | 889 # TODO: get bundlecaps from remote |
895 bundlecaps = None | 890 bundlecaps = None |
896 # create a changegroup from local | 891 # create a changegroup from local |
1469 | 1464 |
1470 def caps20to10(repo): | 1465 def caps20to10(repo): |
1471 """return a set with appropriate options to use bundle20 during getbundle""" | 1466 """return a set with appropriate options to use bundle20 during getbundle""" |
1472 caps = set(['HG20']) | 1467 caps = set(['HG20']) |
1473 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo)) | 1468 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo)) |
1474 caps.add('bundle2=' + urllib.quote(capsblob)) | 1469 caps.add('bundle2=' + urlreq.quote(capsblob)) |
1475 return caps | 1470 return caps |
1476 | 1471 |
1477 # List of names of steps to perform for a bundle2 for getbundle, order matters. | 1472 # List of names of steps to perform for a bundle2 for getbundle, order matters. |
1478 getbundle2partsorder = [] | 1473 getbundle2partsorder = [] |
1479 | 1474 |
1535 | 1530 |
1536 # bundle20 case | 1531 # bundle20 case |
1537 b2caps = {} | 1532 b2caps = {} |
1538 for bcaps in bundlecaps: | 1533 for bcaps in bundlecaps: |
1539 if bcaps.startswith('bundle2='): | 1534 if bcaps.startswith('bundle2='): |
1540 blob = urllib.unquote(bcaps[len('bundle2='):]) | 1535 blob = urlreq.unquote(bcaps[len('bundle2='):]) |
1541 b2caps.update(bundle2.decodecaps(blob)) | 1536 b2caps.update(bundle2.decodecaps(blob)) |
1542 bundler = bundle2.bundle20(repo.ui, b2caps) | 1537 bundler = bundle2.bundle20(repo.ui, b2caps) |
1543 | 1538 |
1544 kwargs['heads'] = heads | 1539 kwargs['heads'] = heads |
1545 kwargs['common'] = common | 1540 kwargs['common'] = common |
1556 b2caps=None, heads=None, common=None, **kwargs): | 1551 b2caps=None, heads=None, common=None, **kwargs): |
1557 """add a changegroup part to the requested bundle""" | 1552 """add a changegroup part to the requested bundle""" |
1558 cg = None | 1553 cg = None |
1559 if kwargs.get('cg', True): | 1554 if kwargs.get('cg', True): |
1560 # build changegroup bundle here. | 1555 # build changegroup bundle here. |
1561 version = None | 1556 version = '01' |
1562 cgversions = b2caps.get('changegroup') | 1557 cgversions = b2caps.get('changegroup') |
1563 getcgkwargs = {} | |
1564 if cgversions: # 3.1 and 3.2 ship with an empty value | 1558 if cgversions: # 3.1 and 3.2 ship with an empty value |
1565 cgversions = [v for v in cgversions | 1559 cgversions = [v for v in cgversions |
1566 if v in changegroup.supportedoutgoingversions(repo)] | 1560 if v in changegroup.supportedoutgoingversions(repo)] |
1567 if not cgversions: | 1561 if not cgversions: |
1568 raise ValueError(_('no common changegroup version')) | 1562 raise ValueError(_('no common changegroup version')) |
1569 version = getcgkwargs['version'] = max(cgversions) | 1563 version = max(cgversions) |
1570 outgoing = changegroup.computeoutgoing(repo, heads, common) | 1564 outgoing = changegroup.computeoutgoing(repo, heads, common) |
1571 cg = changegroup.getlocalchangegroupraw(repo, source, outgoing, | 1565 cg = changegroup.getlocalchangegroupraw(repo, source, outgoing, |
1572 bundlecaps=bundlecaps, | 1566 bundlecaps=bundlecaps, |
1573 **getcgkwargs) | 1567 version=version) |
1574 | 1568 |
1575 if cg: | 1569 if cg: |
1576 part = bundler.newpart('changegroup', data=cg) | 1570 part = bundler.newpart('changegroup', data=cg) |
1577 if version is not None: | 1571 if cgversions: |
1578 part.addparam('version', version) | 1572 part.addparam('version', version) |
1579 part.addparam('nbchanges', str(len(outgoing.missing)), mandatory=False) | 1573 part.addparam('nbchanges', str(len(outgoing.missing)), mandatory=False) |
1580 if 'treemanifest' in repo.requirements: | 1574 if 'treemanifest' in repo.requirements: |
1581 part.addparam('treemanifest', '1') | 1575 part.addparam('treemanifest', '1') |
1582 | 1576 |
1805 if not fields: | 1799 if not fields: |
1806 continue | 1800 continue |
1807 attrs = {'URL': fields[0]} | 1801 attrs = {'URL': fields[0]} |
1808 for rawattr in fields[1:]: | 1802 for rawattr in fields[1:]: |
1809 key, value = rawattr.split('=', 1) | 1803 key, value = rawattr.split('=', 1) |
1810 key = urllib.unquote(key) | 1804 key = urlreq.unquote(key) |
1811 value = urllib.unquote(value) | 1805 value = urlreq.unquote(value) |
1812 attrs[key] = value | 1806 attrs[key] = value |
1813 | 1807 |
1814 # Parse BUNDLESPEC into components. This makes client-side | 1808 # Parse BUNDLESPEC into components. This makes client-side |
1815 # preferences easier to specify since you can prefer a single | 1809 # preferences easier to specify since you can prefer a single |
1816 # component of the BUNDLESPEC. | 1810 # component of the BUNDLESPEC. |
1922 cg.apply(repo) | 1916 cg.apply(repo) |
1923 else: | 1917 else: |
1924 cg.apply(repo, 'clonebundles', url) | 1918 cg.apply(repo, 'clonebundles', url) |
1925 tr.close() | 1919 tr.close() |
1926 return True | 1920 return True |
1927 except urllib2.HTTPError as e: | 1921 except urlerr.httperror as e: |
1928 ui.warn(_('HTTP error fetching bundle: %s\n') % str(e)) | 1922 ui.warn(_('HTTP error fetching bundle: %s\n') % str(e)) |
1929 except urllib2.URLError as e: | 1923 except urlerr.urlerror as e: |
1930 ui.warn(_('error fetching bundle: %s\n') % e.reason[1]) | 1924 ui.warn(_('error fetching bundle: %s\n') % e.reason[1]) |
1931 | 1925 |
1932 return False | 1926 return False |
1933 finally: | 1927 finally: |
1934 tr.release() | 1928 tr.release() |