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()