narrowwirepeer.py
183 lines
| 5.8 KiB
| text/x-python
|
PythonLexer
Augie Fackler
|
r36096 | # narrowwirepeer.py - passes narrow spec with unbundle command | ||
# | ||||
# Copyright 2017 Google, Inc. | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
Matt Harbison
|
r52756 | from __future__ import annotations | ||
Augie Fackler
|
r36096 | |||
Arun Kulshreshtha
|
r52202 | from mercurial.i18n import _ | ||
from mercurial.utils import stringutil | ||||
Augie Fackler
|
r36096 | from mercurial import ( | ||
Pulkit Goyal
|
r40106 | bundle2, | ||
error, | ||||
r50136 | exchange, | |||
Augie Fackler
|
r36096 | extensions, | ||
hg, | ||||
Pulkit Goyal
|
r40106 | narrowspec, | ||
wireprototypes, | ||||
wireprotov1peer, | ||||
Pulkit Goyal
|
r39559 | wireprotov1server, | ||
Augie Fackler
|
r36096 | ) | ||
Pulkit Goyal
|
r42605 | from . import narrowbundle2 | ||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r36096 | def uisetup(): | ||
Pulkit Goyal
|
r40106 | wireprotov1peer.wirepeer.narrow_widen = peernarrowwiden | ||
Pulkit Goyal
|
r39559 | |||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r36096 | def reposetup(repo): | ||
def wirereposetup(ui, peer): | ||||
def wrapped(orig, cmd, *args, **kwargs): | ||||
Augie Fackler
|
r43347 | if cmd == b'unbundle': | ||
Augie Fackler
|
r36119 | # TODO: don't blindly add include/exclude wireproto | ||
# arguments to unbundle. | ||||
Augie Fackler
|
r36096 | include, exclude = repo.narrowpats | ||
Augie Fackler
|
r43809 | kwargs["includepats"] = b','.join(include) | ||
kwargs["excludepats"] = b','.join(exclude) | ||||
Augie Fackler
|
r36096 | return orig(cmd, *args, **kwargs) | ||
Augie Fackler
|
r43346 | |||
r51680 | extensions.wrapfunction(peer, '_calltwowaystream', wrapped) | |||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r36096 | hg.wirepeersetupfuncs.append(wirereposetup) | ||
Pulkit Goyal
|
r40106 | |||
Augie Fackler
|
r43346 | |||
@wireprotov1server.wireprotocommand( | ||||
Augie Fackler
|
r43347 | b'narrow_widen', | ||
b'oldincludes oldexcludes' | ||||
b' newincludes newexcludes' | ||||
b' commonheads cgversion' | ||||
b' known ellipses', | ||||
permission=b'pull', | ||||
Augie Fackler
|
r43346 | ) | ||
def narrow_widen( | ||||
repo, | ||||
proto, | ||||
oldincludes, | ||||
oldexcludes, | ||||
newincludes, | ||||
newexcludes, | ||||
commonheads, | ||||
cgversion, | ||||
known, | ||||
ellipses, | ||||
): | ||||
Pulkit Goyal
|
r40106 | """wireprotocol command to send data when a narrow clone is widen. We will | ||
be sending a changegroup here. | ||||
The current set of arguments which are required: | ||||
oldincludes: the old includes of the narrow copy | ||||
oldexcludes: the old excludes of the narrow copy | ||||
newincludes: the new includes of the narrow copy | ||||
newexcludes: the new excludes of the narrow copy | ||||
commonheads: list of heads which are common between the server and client | ||||
cgversion(maybe): the changegroup version to produce | ||||
known: list of nodes which are known on the client (used in ellipses cases) | ||||
ellipses: whether to send ellipses data or not | ||||
""" | ||||
Pulkit Goyal
|
r40183 | preferuncompressed = False | ||
Pulkit Goyal
|
r40106 | try: | ||
Augie Fackler
|
r43346 | |||
Martin von Zweigbergk
|
r43214 | def splitpaths(data): | ||
# work around ''.split(',') => [''] | ||||
return data.split(b',') if data else [] | ||||
Augie Fackler
|
r43346 | |||
Arun Kulshreshtha
|
r52202 | oldincludes = set(splitpaths(oldincludes)) | ||
newincludes = set(splitpaths(newincludes)) | ||||
oldexcludes = set(splitpaths(oldexcludes)) | ||||
newexcludes = set(splitpaths(newexcludes)) | ||||
r50136 | ||||
# enforce narrow acl if set | ||||
if repo.ui.has_section(exchange._NARROWACL_SECTION): | ||||
Arun Kulshreshtha
|
r52202 | kwargs = exchange.applynarrowacl( | ||
repo, {'includepats': newincludes, 'excludepats': newexcludes} | ||||
) | ||||
newincludes = kwargs['includepats'] | ||||
requiredexcludes = kwargs['excludepats'] - newexcludes | ||||
if requiredexcludes: | ||||
# XXX: The below code to get the username was copied from exchange.py, | ||||
# where it is noted that this is technically a layering violation for | ||||
# assuming the existence of HTTP. Using it anyway to make the error | ||||
# message consistent with the error message for invalid includes. | ||||
ui = repo.ui | ||||
username = ui.shortuser( | ||||
ui.environ.get(b'REMOTE_USER') or ui.username() | ||||
) | ||||
raise error.Abort( | ||||
_(b"The following excludes cannot be removed for %s: %s") | ||||
% (username, stringutil.pprint(list(requiredexcludes))) | ||||
) | ||||
newexcludes = kwargs['excludepats'] | ||||
r50136 | ||||
Pulkit Goyal
|
r40106 | # validate the patterns | ||
Arun Kulshreshtha
|
r52202 | narrowspec.validatepatterns(oldincludes) | ||
narrowspec.validatepatterns(newincludes) | ||||
narrowspec.validatepatterns(oldexcludes) | ||||
narrowspec.validatepatterns(newexcludes) | ||||
Pulkit Goyal
|
r40106 | |||
common = wireprototypes.decodelist(commonheads) | ||||
Pulkit Goyal
|
r42605 | known = wireprototypes.decodelist(known) | ||
Augie Fackler
|
r43347 | if ellipses == b'0': | ||
Pulkit Goyal
|
r40106 | ellipses = False | ||
else: | ||||
ellipses = bool(ellipses) | ||||
cgversion = cgversion | ||||
Pulkit Goyal
|
r42607 | bundler = bundle2.bundle20(repo.ui) | ||
Martin von Zweigbergk
|
r43543 | newmatch = narrowspec.match( | ||
repo.root, include=newincludes, exclude=newexcludes | ||||
) | ||||
oldmatch = narrowspec.match( | ||||
repo.root, include=oldincludes, exclude=oldexcludes | ||||
) | ||||
Pulkit Goyal
|
r42605 | if not ellipses: | ||
Augie Fackler
|
r43346 | bundle2.widen_bundle( | ||
bundler, | ||||
repo, | ||||
oldmatch, | ||||
newmatch, | ||||
common, | ||||
known, | ||||
cgversion, | ||||
ellipses, | ||||
) | ||||
Pulkit Goyal
|
r42605 | else: | ||
Martin von Zweigbergk
|
r43536 | narrowbundle2.generate_ellipses_bundle2_for_widening( | ||
Augie Fackler
|
r46554 | bundler, | ||
repo, | ||||
oldmatch, | ||||
newmatch, | ||||
cgversion, | ||||
common, | ||||
known, | ||||
Augie Fackler
|
r43346 | ) | ||
Pulkit Goyal
|
r40106 | except error.Abort as exc: | ||
Pulkit Goyal
|
r40107 | bundler = bundle2.bundle20(repo.ui) | ||
Martin von Zweigbergk
|
r46274 | manargs = [(b'message', exc.message)] | ||
Pulkit Goyal
|
r40106 | advargs = [] | ||
if exc.hint is not None: | ||||
Augie Fackler
|
r43347 | advargs.append((b'hint', exc.hint)) | ||
bundler.addpart(bundle2.bundlepart(b'error:abort', manargs, advargs)) | ||||
Pulkit Goyal
|
r40183 | preferuncompressed = True | ||
Pulkit Goyal
|
r40106 | |||
chunks = bundler.getchunks() | ||||
Augie Fackler
|
r43346 | return wireprototypes.streamres( | ||
gen=chunks, prefer_uncompressed=preferuncompressed | ||||
) | ||||
Pulkit Goyal
|
r40106 | |||
def peernarrowwiden(remote, **kwargs): | ||||
Augie Fackler
|
r43906 | for ch in ('commonheads', 'known'): | ||
Pulkit Goyal
|
r40106 | kwargs[ch] = wireprototypes.encodelist(kwargs[ch]) | ||
Augie Fackler
|
r43906 | for ch in ('oldincludes', 'newincludes', 'oldexcludes', 'newexcludes'): | ||
Martin von Zweigbergk
|
r43214 | kwargs[ch] = b','.join(kwargs[ch]) | ||
Augie Fackler
|
r43906 | kwargs['ellipses'] = b'%i' % bool(kwargs['ellipses']) | ||
Augie Fackler
|
r43347 | f = remote._callcompressable(b'narrow_widen', **kwargs) | ||
Pulkit Goyal
|
r40106 | return bundle2.getunbundler(remote.ui, f) | ||