##// END OF EJS Templates
sidedata-exchange: add `wanted_sidedata` and `sidedata_computers` to repos...
Raphaël Gomès -
r47447:bc251951 default
parent child Browse files
Show More
@@ -1812,6 +1812,28 b' def _formatrequirementsparams(requiremen'
1812 1812 return params
1813 1813
1814 1814
1815 def format_remote_wanted_sidedata(repo):
1816 """Formats a repo's wanted sidedata categories into a bytestring for
1817 capabilities exchange."""
1818 wanted = b""
1819 if repo._wanted_sidedata:
1820 wanted = b','.join(
1821 pycompat.bytestr(c) for c in sorted(repo._wanted_sidedata)
1822 )
1823 return wanted
1824
1825
1826 def read_remote_wanted_sidedata(remote):
1827 sidedata_categories = remote.capable(b'exp-wanted-sidedata')
1828 return read_wanted_sidedata(sidedata_categories)
1829
1830
1831 def read_wanted_sidedata(formatted):
1832 if formatted:
1833 return set(formatted.split(b','))
1834 return set()
1835
1836
1815 1837 def addpartbundlestream2(bundler, repo, **kwargs):
1816 1838 if not kwargs.get('stream', False):
1817 1839 return
@@ -1957,6 +1979,7 b' def combinechangegroupresults(op):'
1957 1979 b'version',
1958 1980 b'nbchanges',
1959 1981 b'exp-sidedata',
1982 b'exp-wanted-sidedata',
1960 1983 b'treemanifest',
1961 1984 b'targetphase',
1962 1985 ),
@@ -1999,6 +2022,10 b' def handlechangegroup(op, inpart):'
1999 2022 targetphase = inpart.params.get(b'targetphase')
2000 2023 if targetphase is not None:
2001 2024 extrakwargs['targetphase'] = int(targetphase)
2025
2026 remote_sidedata = inpart.params.get(b'exp-wanted-sidedata')
2027 extrakwargs['sidedata_categories'] = read_wanted_sidedata(remote_sidedata)
2028
2002 2029 ret = _processchangegroup(
2003 2030 op,
2004 2031 cg,
@@ -2559,5 +2586,7 b' def widen_bundle('
2559 2586 part.addparam(b'treemanifest', b'1')
2560 2587 if b'exp-sidedata-flag' in repo.requirements:
2561 2588 part.addparam(b'exp-sidedata', b'1')
2589 wanted = format_remote_wanted_sidedata(repo)
2590 part.addparam(b'exp-wanted-sidedata', wanted)
2562 2591
2563 2592 return bundler
@@ -945,6 +945,9 b' class cgpacker(object):'
945 945 if bundlecaps is None:
946 946 bundlecaps = set()
947 947 self._bundlecaps = bundlecaps
948 if remote_sidedata is None:
949 remote_sidedata = set()
950 self._remote_sidedata = remote_sidedata
948 951 self._isshallow = shallow
949 952 self._fullclnodes = fullnodes
950 953
@@ -420,7 +420,20 b' def push('
420 420 b'unbundle wire protocol command'
421 421 )
422 422 )
423
423 for category in sorted(bundle2.read_remote_wanted_sidedata(pushop.remote)):
424 # Check that a computer is registered for that category for at least
425 # one revlog kind.
426 for kind, computers in repo._sidedata_computers.items():
427 if computers.get(category):
428 break
429 else:
430 raise error.Abort(
431 _(
432 b'cannot push: required sidedata category not supported'
433 b" by this client: '%s'"
434 )
435 % pycompat.bytestr(category)
436 )
424 437 # get lock as we might write phase data
425 438 wlock = lock = None
426 439 try:
@@ -865,8 +878,15 b' def _pushb2ctx(pushop, bundler):'
865 878 if not cgversions:
866 879 raise error.Abort(_(b'no common changegroup version'))
867 880 version = max(cgversions)
881
882 remote_sidedata = bundle2.read_remote_wanted_sidedata(pushop.remote)
868 883 cgstream = changegroup.makestream(
869 pushop.repo, pushop.outgoing, version, b'push'
884 pushop.repo,
885 pushop.outgoing,
886 version,
887 b'push',
888 bundlecaps=b2caps,
889 remote_sidedata=remote_sidedata,
870 890 )
871 891 cgpart = bundler.newpart(b'changegroup', data=cgstream)
872 892 if cgversions:
@@ -1607,6 +1627,23 b' def pull('
1607 1627 ) % (b', '.join(sorted(missing)))
1608 1628 raise error.Abort(msg)
1609 1629
1630 for category in repo._wanted_sidedata:
1631 # Check that a computer is registered for that category for at least
1632 # one revlog kind.
1633 for kind, computers in repo._sidedata_computers.items():
1634 if computers.get(category):
1635 break
1636 else:
1637 # This should never happen since repos are supposed to be able to
1638 # generate the sidedata they require.
1639 raise error.ProgrammingError(
1640 _(
1641 b'sidedata category requested by local side without local'
1642 b"support: '%s'"
1643 )
1644 % pycompat.bytestr(category)
1645 )
1646
1610 1647 pullop.trmanager = transactionmanager(repo, b'pull', remote.url())
1611 1648 wlock = util.nullcontextmanager()
1612 1649 if not bookmod.bookmarksinstore(repo):
@@ -1820,6 +1857,10 b' def _pullbundle2(pullop):'
1820 1857 pullop.stepsdone.add(b'obsmarkers')
1821 1858 _pullbundle2extraprepare(pullop, kwargs)
1822 1859
1860 remote_sidedata = bundle2.read_remote_wanted_sidedata(pullop.remote)
1861 if remote_sidedata:
1862 kwargs[b'remote_sidedata'] = remote_sidedata
1863
1823 1864 with pullop.remote.commandexecutor() as e:
1824 1865 args = dict(kwargs)
1825 1866 args[b'source'] = b'pull'
@@ -2388,6 +2429,8 b' def _getbundlechangegrouppart('
2388 2429
2389 2430 if b'exp-sidedata-flag' in repo.requirements:
2390 2431 part.addparam(b'exp-sidedata', b'1')
2432 sidedata = bundle2.format_remote_wanted_sidedata(repo)
2433 part.addparam(b'exp-wanted-sidedata', sidedata)
2391 2434
2392 2435 if (
2393 2436 kwargs.get('narrow', False)
@@ -1832,6 +1832,12 b' class ilocalrepositorymain(interfaceutil'
1832 1832 def savecommitmessage(text):
1833 1833 pass
1834 1834
1835 def register_sidedata_computer(kind, category, keys, computer):
1836 pass
1837
1838 def register_wanted_sidedata(category):
1839 pass
1840
1835 1841
1836 1842 class completelocalrepository(
1837 1843 ilocalrepositorymain, ilocalrepositoryfilestorage
@@ -49,6 +49,7 b' from . import ('
49 49 match as matchmod,
50 50 mergestate as mergestatemod,
51 51 mergeutil,
52 metadata as metadatamod,
52 53 namespaces,
53 54 narrowspec,
54 55 obsolete,
@@ -273,6 +274,11 b' class localpeer(repository.peer):'
273 274 caps = moderncaps.copy()
274 275 self._repo = repo.filtered(b'served')
275 276 self.ui = repo.ui
277
278 if repo._wanted_sidedata:
279 formatted = bundle2.format_remote_wanted_sidedata(repo)
280 caps.add(b'exp-wanted-sidedata=' + formatted)
281
276 282 self._caps = repo._restrictcapabilities(caps)
277 283
278 284 # Begin of _basepeer interface.
@@ -1395,6 +1401,10 b' class localrepository(object):'
1395 1401 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1396 1402 self.filecopiesmode = b'changeset-sidedata'
1397 1403
1404 self._wanted_sidedata = set()
1405 self._sidedata_computers = {}
1406 metadatamod.set_sidedata_spec_for_repo(self)
1407
1398 1408 def _getvfsward(self, origfunc):
1399 1409 """build a ward for self.vfs"""
1400 1410 rref = weakref.ref(self)
@@ -3332,6 +3342,22 b' class localrepository(object):'
3332 3342 fp.close()
3333 3343 return self.pathto(fp.name[len(self.root) + 1 :])
3334 3344
3345 def register_wanted_sidedata(self, category):
3346 self._wanted_sidedata.add(pycompat.bytestr(category))
3347
3348 def register_sidedata_computer(self, kind, category, keys, computer):
3349 if kind not in (b"changelog", b"manifest", b"filelog"):
3350 msg = _(b"unexpected revlog kind '%s'.")
3351 raise error.ProgrammingError(msg % kind)
3352 category = pycompat.bytestr(category)
3353 if category in self._sidedata_computers.get(kind, []):
3354 msg = _(
3355 b"cannot register a sidedata computer twice for category '%s'."
3356 )
3357 raise error.ProgrammingError(msg % category)
3358 self._sidedata_computers.setdefault(kind, {})
3359 self._sidedata_computers[kind][category] = (keys, computer)
3360
3335 3361
3336 3362 # used to avoid circular references so destructors work
3337 3363 def aftertrans(files):
@@ -18,6 +18,7 b' from .node import ('
18 18 from . import (
19 19 error,
20 20 pycompat,
21 requirements as requirementsmod,
21 22 util,
22 23 )
23 24
@@ -804,6 +805,21 b' def _getsidedata(srcrepo, rev):'
804 805 return encode_files_sidedata(files), files.has_copies_info
805 806
806 807
808 def copies_sidedata_computer(repo, revlog, rev, existing_sidedata):
809 return _getsidedata(repo, rev)[0]
810
811
812 def set_sidedata_spec_for_repo(repo):
813 if requirementsmod.COPIESSDC_REQUIREMENT in repo.requirements:
814 repo.register_wanted_sidedata(sidedatamod.SD_FILES)
815 repo.register_sidedata_computer(
816 b"changelog",
817 sidedatamod.SD_FILES,
818 (sidedatamod.SD_FILES,),
819 copies_sidedata_computer,
820 )
821
822
807 823 def getsidedataadder(srcrepo, destrepo):
808 824 use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade')
809 825 if pycompat.iswindows or not use_w:
@@ -172,6 +172,7 b' class statichttprepository('
172 172 self.names = namespaces.namespaces()
173 173 self.filtername = None
174 174 self._extrafilterid = None
175 self._wanted_sidedata = set()
175 176
176 177 try:
177 178 requirements = set(self.vfs.read(b'requires').splitlines())
@@ -85,6 +85,7 b' def checkzobject(o, allowextra=False):'
85 85 class dummyrepo(object):
86 86 def __init__(self):
87 87 self.ui = uimod.ui()
88 self._wanted_sidedata = set()
88 89
89 90 def filtered(self, name):
90 91 pass
General Comments 0
You need to be logged in to leave comments. Login now