##// END OF EJS Templates
context: set stack level for deprecation warning...
context: set stack level for deprecation warning This patch makes the deprecation warning print the caller of repo.__getitem__. That's not quite correct, since there could also be other callers of changectx.__init__, but it seems like the most helpful stack level in practice. Differential Revision: https://phab.mercurial-scm.org/D3307

File last commit:

r37632:a81d02ea default
r37694:1764527a default
Show More
wireproto.py
866 lines | 34.4 KiB | text/x-python | PythonLexer
Matt Mackall
protocol: introduce wireproto.py...
r11581 # wireproto.py - generic wire protocol support functions
#
# Copyright 2005-2010 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Gregory Szorc
wireproto: use absolute_import
r25993 from __future__ import absolute_import
import os
import tempfile
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: use absolute_import
r25993 from .i18n import _
from .node import (
hex,
Siddharth Agarwal
clone: add a server-side option to disable full getbundles (pull-based clones)...
r32260 nullid,
Gregory Szorc
wireproto: use absolute_import
r25993 )
from . import (
bundle2,
changegroup as changegroupmod,
Durham Goode
changegroup: replace changegroupsubset with makechangegroup...
r34099 discovery,
Gregory Szorc
wireproto: use absolute_import
r25993 encoding,
error,
exchange,
pushkey as pushkeymod,
Pulkit Goyal
py3: convert the mode argument of os.fdopen to unicodes (1 of 2)...
r30924 pycompat,
Gregory Szorc
streamclone: move code out of exchange.py...
r26443 streamclone,
Gregory Szorc
wireproto: use absolute_import
r25993 util,
Gregory Szorc
wireprototypes: move wire protocol response types to new module...
r36090 wireprototypes,
Gregory Szorc
wireproto: use absolute_import
r25993 )
Pierre-Yves David
wireproto: introduce an abstractserverproto class...
r20903
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Pierre-Yves David
bundle1: fix bundle1-denied reporting for push over ssh...
r30909 bundle2requiredmain = _('incompatible Mercurial client; bundle2 required')
bundle2requiredhint = _('see https://www.mercurial-scm.org/wiki/'
'IncompatibleClient')
bundle2required = '%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint)
Gregory Szorc
wireproto: config options to disable bundle1...
r27246
Joerg Sonnenberger
wireproto: provide accessors for client capabilities...
r37411 def clientcompressionsupport(proto):
"""Returns a list of compression methods supported by the client.
Returns a list of the compression methods supported by the client
according to the protocol capabilities. If no such capability has
been announced, fallback to the default of zlib and uncompressed.
"""
for cap in proto.getprotocaps():
if cap.startswith('comp='):
return cap[5:].split(',')
return ['zlib', 'none']
Pierre-Yves David
wireproto: document possible return type...
r20902 # wire protocol command can either return a string or one of these classes.
Andrew Pritchard
wireproto: add out-of-band error class to allow remote repo to report errors...
r15017
Gregory Szorc
wireproto: extract repo filtering to standalone function...
r29590 def getdispatchrepo(repo, proto, command):
"""Obtain the repo used for processing wire protocol commands.
The intent of this function is to serve as a monkeypatch point for
extensions that need commands to operate on different repo views under
specialized circumstances.
"""
return repo.filtered('served')
Matt Mackall
protocol: introduce wireproto.py...
r11581 def dispatch(repo, proto, command):
Gregory Szorc
wireproto: extract repo filtering to standalone function...
r29590 repo = getdispatchrepo(repo, proto, command)
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311
transportversion = wireprototypes.TRANSPORTS[proto.name]['version']
commandtable = commandsv2 if transportversion == 2 else commands
func, spec = commandtable[command]
Matt Mackall
protocol: introduce wireproto.py...
r11581 args = proto.getargs(spec)
Gregory Szorc
wireproto: port heads command to wire protocol v2...
r37503
# Version 1 protocols define arguments as a list. Version 2 uses a dict.
if isinstance(args, list):
return func(repo, proto, *args)
elif isinstance(args, dict):
return func(repo, proto, **args)
else:
raise error.ProgrammingError('unexpected type returned from '
'proto.getargs(): %s' % type(args))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Peter Arrenbrecht
wireproto: fix handling of '*' args for HTTP and SSH
r13721 def options(cmd, keys, others):
opts = {}
for k in keys:
if k in others:
opts[k] = others[k]
del others[k]
if others:
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil.stderr.write("warning: %s ignored unexpected arguments %s\n"
% (cmd, ",".join(others)))
Peter Arrenbrecht
wireproto: fix handling of '*' args for HTTP and SSH
r13721 return opts
Gregory Szorc
wireproto: support disabling bundle1 only if repo is generaldelta...
r27633 def bundle1allowed(repo, action):
"""Whether a bundle1 operation is allowed from the server.
Priority is:
1. server.bundle1gd.<action> (if generaldelta active)
2. server.bundle1.<action>
3. server.bundle1gd (if generaldelta active)
4. server.bundle1
"""
ui = repo.ui
gd = 'generaldelta' in repo.requirements
if gd:
Boris Feld
configitems: register the 'server.bundle*' family of config...
r34614 v = ui.configbool('server', 'bundle1gd.%s' % action)
Gregory Szorc
wireproto: support disabling bundle1 only if repo is generaldelta...
r27633 if v is not None:
return v
Boris Feld
configitems: register the 'server.bundle*' family of config...
r34614 v = ui.configbool('server', 'bundle1.%s' % action)
Gregory Szorc
wireproto: config options to disable bundle1...
r27246 if v is not None:
return v
Gregory Szorc
wireproto: support disabling bundle1 only if repo is generaldelta...
r27633 if gd:
configitems: register the 'server.bundle1gd' config
r33217 v = ui.configbool('server', 'bundle1gd')
Gregory Szorc
wireproto: support disabling bundle1 only if repo is generaldelta...
r27633 if v is not None:
return v
configitems: register the 'server.bundle1' config
r33216 return ui.configbool('server', 'bundle1')
Gregory Szorc
wireproto: config options to disable bundle1...
r27246
Gregory Szorc
wireproto: remove unused proto argument from supportedcompengines (API)...
r36088 def supportedcompengines(ui, role):
Gregory Szorc
wireproto: advertise supported media types and compression formats...
r30762 """Obtain the list of supported compression engines for a request."""
assert role in (util.CLIENTROLE, util.SERVERROLE)
compengines = util.compengines.supportedwireengines(role)
# Allow config to override default list and ordering.
if role == util.SERVERROLE:
configengines = ui.configlist('server', 'compressionengines')
config = 'server.compressionengines'
else:
# This is currently implemented mainly to facilitate testing. In most
# cases, the server should be in charge of choosing a compression engine
# because a server has the most to lose from a sub-optimal choice. (e.g.
# CPU DoS due to an expensive engine or a network DoS due to poor
# compression ratio).
configengines = ui.configlist('experimental',
'clientcompressionengines')
config = 'experimental.clientcompressionengines'
# No explicit config. Filter out the ones that aren't supposed to be
# advertised and return default ordering.
if not configengines:
attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority'
return [e for e in compengines
if getattr(e.wireprotosupport(), attr) > 0]
# If compression engines are listed in the config, assume there is a good
# reason for it (like server operators wanting to achieve specific
# performance characteristics). So fail fast if the config references
# unusable compression engines.
validnames = set(e.name() for e in compengines)
invalidnames = set(e for e in configengines if e not in validnames)
if invalidnames:
raise error.Abort(_('invalid compression engine defined in %s: %s') %
(config, ', '.join(sorted(invalidnames))))
compengines = [e for e in compengines if e.name() in configengines]
compengines = sorted(compengines,
key=lambda e: configengines.index(e.name()))
if not compengines:
raise error.Abort(_('%s config option does not specify any known '
'compression engines') % config,
hint=_('usable compression engines: %s') %
', '.sorted(validnames))
return compengines
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999 class commandentry(object):
"""Represents a declared wire protocol command."""
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 def __init__(self, func, args='', transports=None,
permission='push'):
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999 self.func = func
self.args = args
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 self.transports = transports or set()
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 self.permission = permission
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999
def _merge(self, func, args):
"""Merge this instance with an incoming 2-tuple.
This is called when a caller using the old 2-tuple API attempts
to replace an instance. The incoming values are merged with
data not captured by the 2-tuple and a new instance containing
the union of the two objects is returned.
"""
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 return commandentry(func, args=args, transports=set(self.transports),
permission=self.permission)
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999
# Old code treats instances as 2-tuples. So expose that interface.
def __iter__(self):
yield self.func
yield self.args
def __getitem__(self, i):
if i == 0:
return self.func
elif i == 1:
return self.args
else:
raise IndexError('can only access elements 0 and 1')
class commanddict(dict):
"""Container for registered wire protocol commands.
It behaves like a dict. But __setitem__ is overwritten to allow silent
coercion of values from 2-tuples for API compatibility.
"""
def __setitem__(self, k, v):
if isinstance(v, commandentry):
pass
# Cast 2-tuples to commandentry instances.
elif isinstance(v, tuple):
if len(v) != 2:
raise ValueError('command tuples must have exactly 2 elements')
# It is common for extensions to wrap wire protocol commands via
# e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
# doing this aren't aware of the new API that uses objects to store
# command entries, we automatically merge old state with new.
if k in self:
v = self[k]._merge(v[0], v[1])
else:
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 # Use default values from @wireprotocommand.
v = commandentry(v[0], args=v[1],
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 transports=set(wireprototypes.TRANSPORTS),
permission='push')
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999 else:
raise ValueError('command entries must be commandentry instances '
'or 2-tuples')
return super(commanddict, self).__setitem__(k, v)
Gregory Szorc
wireproto: function for testing if wire protocol command is available...
r36000 def commandavailable(self, command, proto):
"""Determine if a command is available for the requested protocol."""
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 assert proto.name in wireprototypes.TRANSPORTS
entry = self.get(command)
if not entry:
return False
if proto.name not in entry.transports:
return False
return True
# Constants specifying which transports a wire protocol command should be
# available on. For use with @wireprotocommand.
POLICY_V1_ONLY = 'v1-only'
POLICY_V2_ONLY = 'v2-only'
Gregory Szorc
wireproto: function for testing if wire protocol command is available...
r36000
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311 # For version 1 transports.
Gregory Szorc
wireproto: define and use types for wire protocol commands...
r35999 commands = commanddict()
Pierre-Yves David
wireproto: add decorator for wire protocol command...
r20906
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311 # For version 2 transports.
commandsv2 = commanddict()
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 def wireprotocommand(name, args=None, transportpolicy=POLICY_V1_ONLY,
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 permission='push'):
Gregory Szorc
wireproto: improve docstring for @wireprotocommand...
r35998 """Decorator to declare a wire protocol command.
``name`` is the name of the wire protocol command being provided.
Gregory Szorc
wireproto: define and expose types of wire command arguments...
r37553 ``args`` defines the named arguments accepted by the command. It is
ideally a dict mapping argument names to their types. For backwards
compatibility, it can be a space-delimited list of argument names. For
version 1 transports, ``*`` denotes a special value that says to accept
all named arguments.
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627
``transportpolicy`` is a POLICY_* constant denoting which transports
this wire protocol command should be exposed to. By default, commands
are exposed to all wire protocol transports.
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818
``permission`` defines the permission type needed to run this command.
Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
respectively. Default is to assume command requires ``push`` permissions
because otherwise commands not declaring their permissions could modify
a repository that is supposed to be read-only.
Gregory Szorc
wireproto: improve docstring for @wireprotocommand...
r35998 """
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 if transportpolicy == POLICY_V1_ONLY:
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
if v['version'] == 1}
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 transportversion = 1
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 elif transportpolicy == POLICY_V2_ONLY:
transports = {k for k, v in wireprototypes.TRANSPORTS.items()
if v['version'] == 2}
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 transportversion = 2
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627 else:
Gregory Szorc
wireproto: raise ProgrammingError instead of Abort...
r36858 raise error.ProgrammingError('invalid transport policy value: %s' %
transportpolicy)
Gregory Szorc
wireproto: allow wire protocol commands to declare transport support...
r36627
Gregory Szorc
wireproto: nominally don't expose "batch" to version 2 wire transports...
r37071 # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to
# SSHv2.
# TODO undo this hack when SSH is using the unified frame protocol.
if name == b'batch':
transports.add(wireprototypes.SSHV2)
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 if permission not in ('push', 'pull'):
Gregory Szorc
wireproto: raise ProgrammingError instead of Abort...
r36858 raise error.ProgrammingError('invalid wire protocol permission; '
'got %s; expected "push" or "pull"' %
permission)
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 if transportversion == 1:
if args is None:
args = ''
Gregory Szorc
wireproto: define and expose types of wire command arguments...
r37553
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 if not isinstance(args, bytes):
raise error.ProgrammingError('arguments for version 1 commands '
'must be declared as bytes')
elif transportversion == 2:
if args is None:
args = {}
if not isinstance(args, dict):
raise error.ProgrammingError('arguments for version 2 commands '
'must be declared as dicts')
Gregory Szorc
wireproto: define and expose types of wire command arguments...
r37553
Pierre-Yves David
wireproto: add decorator for wire protocol command...
r20906 def register(func):
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 if transportversion == 1:
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311 if name in commands:
raise error.ProgrammingError('%s command already registered '
'for version 1' % name)
commands[name] = commandentry(func, args=args,
transports=transports,
permission=permission)
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 elif transportversion == 2:
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311 if name in commandsv2:
raise error.ProgrammingError('%s command already registered '
'for version 2' % name)
Gregory Szorc
wireproto: define and expose types of wire command arguments...
r37553
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 commandsv2[name] = commandentry(func, args=args,
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311 transports=transports,
permission=permission)
Gregory Szorc
wireproto: disallow commands handlers for multiple transport versions...
r37559 else:
raise error.ProgrammingError('unhandled transport version: %d' %
transportversion)
Gregory Szorc
wireproto: separate commands tables for version 1 and 2 commands...
r37311
Pierre-Yves David
wireproto: add decorator for wire protocol command...
r20906 return func
return register
Gregory Szorc
wireproto: check permissions when executing "batch" command (BC) (SEC)...
r36773 # TODO define a more appropriate permissions type to use for this.
Gregory Szorc
wireproto: nominally don't expose "batch" to version 2 wire transports...
r37071 @wireprotocommand('batch', 'cmds *', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Peter Arrenbrecht
wireproto: add batching support to wirerepository...
r14622 def batch(repo, proto, cmds, others):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 unescapearg = wireprototypes.unescapebatcharg
Kevin Bullock
filtering: rename filters to their antonyms...
r18382 repo = repo.filtered("served")
Peter Arrenbrecht
wireproto: add batching support to wirerepository...
r14622 res = []
for pair in cmds.split(';'):
op, args = pair.split(' ', 1)
vals = {}
for a in args.split(','):
if a:
n, v = a.split('=')
Gregory Szorc
wireproto: unescape argument names in batch command (BC)...
r29734 vals[unescapearg(n)] = unescapearg(v)
Peter Arrenbrecht
wireproto: add batching support to wirerepository...
r14622 func, spec = commands[op]
Gregory Szorc
wireproto: check permissions when executing "batch" command (BC) (SEC)...
r36773
Gregory Szorc
wireproto: formalize permissions checking as part of protocol interface...
r36819 # Validate that client has permissions to perform this command.
perm = commands[op].permission
assert perm in ('push', 'pull')
proto.checkperm(perm)
Gregory Szorc
wireproto: check permissions when executing "batch" command (BC) (SEC)...
r36773
Peter Arrenbrecht
wireproto: add batching support to wirerepository...
r14622 if spec:
keys = spec.split()
data = {}
for k in keys:
if k == '*':
star = {}
for key in vals.keys():
if key not in keys:
star[key] = vals[key]
data['*'] = star
else:
data[k] = vals[k]
result = func(repo, proto, *[data[k] for k in keys])
else:
result = func(repo, proto)
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 if isinstance(result, wireprototypes.ooberror):
Andrew Pritchard
wireproto: add out-of-band error class to allow remote repo to report errors...
r15017 return result
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091
# For now, all batchable commands must return bytesresponse or
# raw bytes (for backwards compatibility).
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 assert isinstance(result, (wireprototypes.bytesresponse, bytes))
if isinstance(result, wireprototypes.bytesresponse):
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091 result = result.data
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 res.append(wireprototypes.escapebatcharg(result))
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(';'.join(res))
Peter Arrenbrecht
wireproto: add batching support to wirerepository...
r14622
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
permission='pull')
Matt Mackall
protocol: add proto to method prototypes
r11583 def between(repo, proto, pairs):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 pairs = [wireprototypes.decodelist(p, '-') for p in pairs.split(" ")]
Matt Mackall
protocol: introduce wireproto.py...
r11581 r = []
for b in repo.between(pairs):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 r.append(wireprototypes.encodelist(b) + "\n")
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(''.join(r))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: port branchmap to wire protocol v2...
r37506 @wireprotocommand('branchmap', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: add proto to method prototypes
r11583 def branchmap(repo, proto):
Pierre-Yves David
clfilter: drop extra filtering in wireprotocol...
r18281 branchmap = repo.branchmap()
Matt Mackall
protocol: introduce wireproto.py...
r11581 heads = []
for branch, nodes in branchmap.iteritems():
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 branchname = urlreq.quote(encoding.fromlocal(branch))
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 branchnodes = wireprototypes.encodelist(nodes)
Benoit Boissinot
wireproto: refactor list of nodeid encoding / decoding
r11597 heads.append('%s %s' % (branchname, branchnodes))
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse('\n'.join(heads))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
permission='pull')
Matt Mackall
protocol: add proto to method prototypes
r11583 def branches(repo, proto, nodes):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 nodes = wireprototypes.decodelist(nodes)
Matt Mackall
protocol: introduce wireproto.py...
r11581 r = []
for b in repo.branches(nodes):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 r.append(wireprototypes.encodelist(b) + "\n")
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(''.join(r))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: only expose "clonebundles" to version 1 transports...
r37554 @wireprotocommand('clonebundles', '', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Gregory Szorc
wireproto: move clonebundles command from extension (issue4931)...
r26857 def clonebundles(repo, proto):
"""Server command for returning info for available bundles to seed clones.
Clients will parse this response and determine what bundle to fetch.
Extensions may wrap this command to filter or dynamically emit data
depending on the request. e.g. you could advertise URLs for the closest
data center given the client's IP address.
"""
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(
repo.vfs.tryread('clonebundles.manifest'))
Pierre-Yves David
wireproto: extract capabilities list in outside the wireproto function...
r20774
Gregory Szorc
wireproto: don't expose changegroupsubset capability if not available...
r36630 wireprotocaps = ['lookup', 'branchmap', 'pushkey',
Gregory Szorc
wireproto: nominally don't expose "batch" to version 2 wire transports...
r37071 'known', 'getbundle', 'unbundlehash']
Pierre-Yves David
wireproto: move wireproto capabilities computation in a subfunction...
r20775
def _capabilities(repo, proto):
"""return a list of capabilities for a repo
This function exists to allow extensions to easily wrap capabilities
computation
- returns a lists: easy to alter
- change done here will be propagated to both `capabilities` and `hello`
Mads Kiilerich
spelling: fixes from spell checker
r21024 command without any other action needed.
Pierre-Yves David
wireproto: move wireproto capabilities computation in a subfunction...
r20775 """
Pierre-Yves David
wireproto: extract capabilities list in outside the wireproto function...
r20774 # copy to prevent modification of the global list
caps = list(wireprotocaps)
Gregory Szorc
wireproto: don't expose changegroupsubset capability if not available...
r36630
# Command of same name as capability isn't exposed to version 1 of
# transports. So conditionally add it.
if commands.commandavailable('changegroupsubset', proto):
caps.append('changegroupsubset')
Gregory Szorc
streamclone: consider secret changesets (BC) (issue5589)...
r32744 if streamclone.allowservergeneration(repo):
configitems: register the 'server.preferuncompressed' config
r33222 if repo.ui.configbool('server', 'preferuncompressed'):
Benoit Allard
protocol: Add the stream-preferred capability...
r16361 caps.append('stream-preferred')
Sune Foldager
clone: only use stream when we understand the revlog format...
r12296 requiredformats = repo.requirements & repo.supportedformats
# if our local revlogs are just revlogv1, add 'stream' cap
Martin von Zweigbergk
cleanup: use set literals...
r32291 if not requiredformats - {'revlogv1'}:
Sune Foldager
clone: only use stream when we understand the revlog format...
r12296 caps.append('stream')
# otherwise, add 'streamreqs' detailing our local revlog format
else:
Pierre-Yves David
stream: sort stream capability before serialisation...
r26911 caps.append('streamreqs=%s' % ','.join(sorted(requiredformats)))
Jun Wu
codemod: register core configitems using a script...
r33499 if repo.ui.configbool('experimental', 'bundle2-advertise'):
Gregory Szorc
bundle2: specify what capabilities will be used for...
r35801 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role='server'))
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 caps.append('bundle2=' + urlreq.quote(capsblob))
Martin von Zweigbergk
bundle: move writebundle() from changegroup.py to bundle2.py (API)...
r28666 caps.append('unbundle=%s' % ','.join(bundle2.bundlepriority))
Gregory Szorc
wireproto: only advertise HTTP-specific capabilities to HTTP peers (BC)...
r30563
Gregory Szorc
wireproto: add transport specific capabilities in the transport...
r36631 return proto.addcapabilities(repo, caps)
Pierre-Yves David
wireproto: move wireproto capabilities computation in a subfunction...
r20775
Mads Kiilerich
spelling: fixes from spell checker
r21024 # If you are writing an extension and consider wrapping this function. Wrap
Pierre-Yves David
wireproto: move wireproto capabilities computation in a subfunction...
r20775 # `_capabilities` instead.
Gregory Szorc
wireproto: implement capabilities for wire protocol v2...
r37551 @wireprotocommand('capabilities', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Pierre-Yves David
wireproto: move wireproto capabilities computation in a subfunction...
r20775 def capabilities(repo, proto):
Joerg Sonnenberger
wireproto: send server capabilities in canonical order...
r37431 caps = _capabilities(repo, proto)
return wireprototypes.bytesresponse(' '.join(sorted(caps)))
Matt Mackall
protocol: unify server-side capabilities functions
r11594
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
permission='pull')
Matt Mackall
protocol: unify changegroup commands...
r11584 def changegroup(repo, proto, roots):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 nodes = wireprototypes.decodelist(roots)
Durham Goode
changegroup: replace changegroup with makechangegroup...
r34102 outgoing = discovery.outgoing(repo, missingroots=nodes,
missingheads=repo.heads())
cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
Gregory Szorc
wireproto: drop support for reader interface from streamres (API)...
r35723 gen = iter(lambda: cg.read(32768), '')
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamres(gen=gen)
Matt Mackall
protocol: unify changegroup commands...
r11584
Gregory Szorc
wireproto: don't expose legacy commands to version 2 of wire protocol...
r36629 @wireprotocommand('changegroupsubset', 'bases heads',
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 transportpolicy=POLICY_V1_ONLY,
permission='pull')
Matt Mackall
protocol: unify changegroup commands...
r11584 def changegroupsubset(repo, proto, bases, heads):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 bases = wireprototypes.decodelist(bases)
heads = wireprototypes.decodelist(heads)
Durham Goode
changegroup: replace changegroupsubset with makechangegroup...
r34099 outgoing = discovery.outgoing(repo, missingroots=bases,
missingheads=heads)
cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
Gregory Szorc
wireproto: drop support for reader interface from streamres (API)...
r35723 gen = iter(lambda: cg.read(32768), '')
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamres(gen=gen)
Matt Mackall
protocol: unify changegroup commands...
r11584
Gregory Szorc
wireproto: declare permissions requirements in @wireprotocommand (API)...
r36818 @wireprotocommand('debugwireargs', 'one two *',
Gregory Szorc
wireproto: only expose "debugwireargs" to version 1 transports...
r37508 permission='pull', transportpolicy=POLICY_V1_ONLY)
Peter Arrenbrecht
wireproto: fix handling of '*' args for HTTP and SSH
r13721 def debugwireargs(repo, proto, one, two, others):
# only accept optional args from the known set
opts = options('debugwireargs', ['three', 'four'], others)
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(repo.debugwireargs(
one, two, **pycompat.strkwargs(opts)))
Peter Arrenbrecht
debug: add debugwireargs to test argument passing over the wire...
r13720
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 def find_pullbundle(repo, proto, opts, clheads, heads, common):
"""Return a file object for the first matching pullbundle.
Pullbundles are specified in .hg/pullbundles.manifest similar to
clonebundles.
For each entry, the bundle specification is checked for compatibility:
- Client features vs the BUNDLESPEC.
- Revisions shared with the clients vs base revisions of the bundle.
A bundle can be applied only if all its base revisions are known by
the client.
- At least one leaf of the bundle's DAG is missing on the client.
- Every leaf of the bundle's DAG is part of node set the client wants.
E.g. do not send a bundle of all changes if the client wants only
one specific branch of many.
"""
def decodehexstring(s):
return set([h.decode('hex') for h in s.split(';')])
manifest = repo.vfs.tryread('pullbundles.manifest')
if not manifest:
return None
res = exchange.parseclonebundlesmanifest(repo, manifest)
res = exchange.filterclonebundleentries(repo, res)
if not res:
return None
cl = repo.changelog
heads_anc = cl.ancestors([cl.rev(rev) for rev in heads], inclusive=True)
common_anc = cl.ancestors([cl.rev(rev) for rev in common], inclusive=True)
compformats = clientcompressionsupport(proto)
for entry in res:
if 'COMPRESSION' in entry and entry['COMPRESSION'] not in compformats:
continue
# No test yet for VERSION, since V2 is supported by any client
# that advertises partial pulls
if 'heads' in entry:
try:
bundle_heads = decodehexstring(entry['heads'])
except TypeError:
# Bad heads entry
continue
if bundle_heads.issubset(common):
continue # Nothing new
if all(cl.rev(rev) in common_anc for rev in bundle_heads):
continue # Still nothing new
if any(cl.rev(rev) not in heads_anc and
cl.rev(rev) not in common_anc for rev in bundle_heads):
continue
if 'bases' in entry:
try:
bundle_bases = decodehexstring(entry['bases'])
except TypeError:
# Bad bases entry
continue
if not all(cl.rev(rev) in common_anc for rev in bundle_bases):
continue
path = entry['URL']
repo.ui.debug('sending pullbundle "%s"\n' % path)
try:
return repo.vfs.open(path)
except IOError:
repo.ui.debug('pullbundle "%s" not accessible\n' % path)
continue
return None
Gregory Szorc
wireproto: only expose "getbundle" and "unbundle" to v1 transports...
r37557 @wireprotocommand('getbundle', '*', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741 def getbundle(repo, proto, others):
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 opts = options('getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(),
others)
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741 for k, v in opts.iteritems():
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k]
Pierre-Yves David
getbundle: declare type of parameters...
r21646 if keytype == 'nodes':
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 opts[k] = wireprototypes.decodelist(v)
Pierre-Yves David
getbundle: declare type of parameters...
r21646 elif keytype == 'csv':
Pierre-Yves David
wireprotocol: distinguish list and set in getbundle argument...
r25403 opts[k] = list(v.split(','))
elif keytype == 'scsv':
Benoit Boissinot
bundle-ng: add bundlecaps argument to getbundle() command
r19201 opts[k] = set(v.split(','))
Pierre-Yves David
wireproto: add a ``boolean`` type for getbundle parameters...
r21988 elif keytype == 'boolean':
Gregory Szorc
wireproto: properly parse false boolean args (BC)...
r26686 # Client should serialize False as '0', which is a non-empty string
# so it evaluates as a True bool.
if v == '0':
opts[k] = False
else:
opts[k] = bool(v)
Pierre-Yves David
getbundle: declare type of parameters...
r21646 elif keytype != 'plain':
raise KeyError('unknown getbundle option type %s'
% keytype)
Gregory Szorc
wireproto: config options to disable bundle1...
r27246
Gregory Szorc
wireproto: support disabling bundle1 only if repo is generaldelta...
r27633 if not bundle1allowed(repo, 'pull'):
Gregory Szorc
wireproto: config options to disable bundle1...
r27246 if not exchange.bundle2requested(opts.get('bundlecaps')):
Gregory Szorc
wireprotoserver: add version to HTTP protocol name (API)...
r36241 if proto.name == 'http-v1':
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.ooberror(bundle2required)
Pierre-Yves David
bundle1: fix bundle1-denied reporting for pull over ssh...
r30912 raise error.Abort(bundle2requiredmain,
hint=bundle2requiredhint)
Gregory Szorc
wireproto: config options to disable bundle1...
r27246
Gregory Szorc
exchange: send bundle2 stream clones uncompressed...
r35805 prefercompressed = True
Gregory Szorc
wireproto: don't compress errors from getbundle()...
r35800
Pierre-Yves David
wireproto: properly report server Abort during 'getbundle'...
r30914 try:
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 clheads = set(repo.changelog.heads())
heads = set(opts.get('heads', set()))
common = set(opts.get('common', set()))
common.discard(nullid)
if (repo.ui.configbool('server', 'pullbundle') and
'partial-pull' in proto.getprotocaps()):
# Check if a pre-built bundle covers this request.
bundle = find_pullbundle(repo, proto, opts, clheads, heads, common)
if bundle:
return wireprototypes.streamres(gen=util.filechunkiter(bundle),
prefer_uncompressed=True)
configitems: register the 'server.disablefullbundle' config
r33220 if repo.ui.configbool('server', 'disablefullbundle'):
Siddharth Agarwal
clone: add a server-side option to disable full getbundles (pull-based clones)...
r32260 # Check to see if this is a full clone.
Boris Feld
clone: allow bundle2's stream clone with 'server.disablefullbundle'...
r35778 changegroup = opts.get('cg', True)
if changegroup and not common and clheads == heads:
Siddharth Agarwal
clone: add a server-side option to disable full getbundles (pull-based clones)...
r32260 raise error.Abort(
_('server has pull-based clones disabled'),
hint=_('remove --pull if specified or upgrade Mercurial'))
Gregory Szorc
exchange: return bundle info from getbundlechunks() (API)...
r35803 info, chunks = exchange.getbundlechunks(repo, 'serve',
**pycompat.strkwargs(opts))
Gregory Szorc
exchange: send bundle2 stream clones uncompressed...
r35805 prefercompressed = info.get('prefercompressed', True)
Pierre-Yves David
wireproto: properly report server Abort during 'getbundle'...
r30914 except error.Abort as exc:
# cleanly forward Abort error to the client
if not exchange.bundle2requested(opts.get('bundlecaps')):
Gregory Szorc
wireprotoserver: add version to HTTP protocol name (API)...
r36241 if proto.name == 'http-v1':
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.ooberror(pycompat.bytestr(exc) + '\n')
Pierre-Yves David
wireproto: properly report server Abort during 'getbundle'...
r30914 raise # cannot do better for bundle1 + ssh
# bundle2 request expect a bundle2 reply
bundler = bundle2.bundle20(repo.ui)
Augie Fackler
py3: get bytes-repr of network errors portably...
r36272 manargs = [('message', pycompat.bytestr(exc))]
Pierre-Yves David
wireproto: properly report server Abort during 'getbundle'...
r30914 advargs = []
if exc.hint is not None:
advargs.append(('hint', exc.hint))
bundler.addpart(bundle2.bundlepart('error:abort',
manargs, advargs))
Gregory Szorc
wireproto: don't compress errors from getbundle()...
r35800 chunks = bundler.getchunks()
Gregory Szorc
exchange: send bundle2 stream clones uncompressed...
r35805 prefercompressed = False
Gregory Szorc
wireproto: don't compress errors from getbundle()...
r35800
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamres(
gen=chunks, prefer_uncompressed=not prefercompressed)
Peter Arrenbrecht
wireproto: add getbundle() function...
r13741
Gregory Szorc
wireproto: port heads command to wire protocol v2...
r37503 @wireprotocommand('heads', permission='pull', transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: add proto to method prototypes
r11583 def heads(repo, proto):
Pierre-Yves David
clfilter: drop extra filtering in wireprotocol...
r18281 h = repo.heads()
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + '\n')
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: only expose "hello" command to version 1 transports...
r37507 @wireprotocommand('hello', permission='pull', transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: unify server-side capabilities functions
r11594 def hello(repo, proto):
Gregory Szorc
wireproto: improve docstring for "hello"...
r36239 """Called as part of SSH handshake to obtain server info.
Returns a list of lines describing interesting things about the
server, in an RFC822-like format.
Matt Mackall
protocol: unify server-side capabilities functions
r11594
Gregory Szorc
wireproto: improve docstring for "hello"...
r36239 Currently, the only one defined is ``capabilities``, which consists of a
line of space separated tokens describing server abilities:
capabilities: <token0> <token1> <token2>
"""
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091 caps = capabilities(repo, proto).data
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse('capabilities: %s\n' % caps)
Matt Mackall
protocol: unify server-side capabilities functions
r11594
Gregory Szorc
wireproto: port listkeys commands to wire protocol v2...
r37505 @wireprotocommand('listkeys', 'namespace', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: add proto to method prototypes
r11583 def listkeys(repo, proto, namespace):
Gregory Szorc
wireproto: sort response to listkeys...
r36546 d = sorted(repo.listkeys(encoding.tolocal(namespace)).items())
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(pushkeymod.encodekeys(d))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: port lookup to wire protocol v2...
r37556 @wireprotocommand('lookup', 'key', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: add proto to method prototypes
r11583 def lookup(repo, proto, key):
Matt Mackall
protocol: introduce wireproto.py...
r11581 try:
Matt Mackall
wireproto: refuse to lookup secret csets
r15925 k = encoding.tolocal(key)
Martin von Zweigbergk
wireproto: use repo.lookup() for lookup command...
r37371 n = repo.lookup(k)
r = hex(n)
Matt Mackall
protocol: introduce wireproto.py...
r11581 success = 1
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except Exception as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 r = stringutil.forcebytestr(inst)
Matt Mackall
protocol: introduce wireproto.py...
r11581 success = 0
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse('%d %s\n' % (success, r))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: port keep command to wire protocol v2...
r37504 @wireprotocommand('known', 'nodes *', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Peter Arrenbrecht
wireproto: enable optional args for known() for future extensibility...
r14436 def known(repo, proto, nodes, others):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 v = ''.join(b and '1' or '0'
for b in repo.known(wireprototypes.decodelist(nodes)))
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse(v)
Peter Arrenbrecht
wireproto: add known([id]) function...
r13723
Joerg Sonnenberger
wireproto: provide accessors for client capabilities...
r37411 @wireprotocommand('protocaps', 'caps', permission='pull',
transportpolicy=POLICY_V1_ONLY)
def protocaps(repo, proto, caps):
if proto.name == wireprototypes.SSHV1:
proto._protocaps = set(caps.split(' '))
return wireprototypes.bytesresponse('OK')
Gregory Szorc
wireproto: port pushkey command to wire protocol version 2...
r37555 @wireprotocommand('pushkey', 'namespace key old new', permission='push',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: add proto to method prototypes
r11583 def pushkey(repo, proto, namespace, key, old, new):
Matt Mackall
pushkey: use UTF-8
r13050 # compatibility with pre-1.8 clients which were accidentally
# sending raw binary nodes rather than utf-8-encoded hex
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if len(new) == 20 and stringutil.escapestr(new) != new:
Matt Mackall
pushkey: use UTF-8
r13050 # looks like it could be a binary node
try:
Alexander Solovyov
remove unused imports and variables
r14064 new.decode('utf-8')
Matt Mackall
pushkey: use UTF-8
r13050 new = encoding.tolocal(new) # but cleanly decodes as UTF-8
except UnicodeDecodeError:
pass # binary, leave unmodified
else:
new = encoding.tolocal(new) # normal path
Gregory Szorc
wireprotoserver: add context manager mechanism for redirecting stdio...
r36083 with proto.mayberedirectstdio() as output:
Gregory Szorc
wireproto: remove unnecessary exception trapping...
r35997 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
encoding.tolocal(old), new) or False
Wagner Bruna
wireproto: fix pushkey hook failure and output on remote http repo...
r17793
Gregory Szorc
wireprotoserver: add context manager mechanism for redirecting stdio...
r36083 output = output.getvalue() if output else ''
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.bytesresponse('%d\n%s' % (int(r), output))
Matt Mackall
protocol: introduce wireproto.py...
r11581
Gregory Szorc
wireproto: only expose "stream_out" to version 1 transports...
r37552 @wireprotocommand('stream_out', permission='pull',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: unify stream_out command
r11585 def stream(repo, proto):
Dirkjan Ochtman
protocol: move the streamclone implementation into wireproto
r11627 '''If the server supports streaming clone, it advertises the "stream"
capability with a value representing the version and flags of the repo
it is serving. Client checks to see if it understands the format.
'''
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamreslegacy(
streamclone.generatev1wireproto(repo))
Matt Mackall
protocol: unify stream_out command
r11585
Gregory Szorc
wireproto: only expose "getbundle" and "unbundle" to v1 transports...
r37557 @wireprotocommand('unbundle', 'heads', permission='push',
transportpolicy=POLICY_V1_ONLY)
Matt Mackall
protocol: unify unbundle on the server side
r11593 def unbundle(repo, proto, heads):
Gregory Szorc
wireproto: move value encoding functions to wireprototypes (API)...
r37630 their_heads = wireprototypes.decodelist(heads)
Matt Mackall
protocol: unify unbundle on the server side
r11593
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 with proto.mayberedirectstdio() as output:
Matt Mackall
protocol: unify unbundle on the server side
r11593 try:
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 exchange.check_heads(repo, their_heads, 'preparing changes')
Joerg Sonnenberger
wireproto: allow direct stream processing for unbundle...
r37432 cleanup = lambda: None
try:
payload = proto.getpayload()
if repo.ui.configbool('server', 'streamunbundle'):
def cleanup():
# Ensure that the full payload is consumed, so
# that the connection doesn't contain trailing garbage.
for p in payload:
pass
fp = util.chunkbuffer(payload)
else:
# write bundle data to temporary file as it can be big
fp, tempname = None, None
def cleanup():
if fp:
fp.close()
if tempname:
os.unlink(tempname)
fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
repo.ui.debug('redirecting incoming bundle to %s\n' %
tempname)
fp = os.fdopen(fd, pycompat.sysstr('wb+'))
r = 0
for p in payload:
fp.write(p)
fp.seek(0)
Gregory Szorc
wireproto: config options to disable bundle1...
r27246
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 gen = exchange.readbundle(repo.ui, fp, None)
if (isinstance(gen, changegroupmod.cg1unpacker)
and not bundle1allowed(repo, 'push')):
Gregory Szorc
wireprotoserver: add version to HTTP protocol name (API)...
r36241 if proto.name == 'http-v1':
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 # need to special case http because stderr do not get to
# the http client on failed push so we need to abuse
# some other error type to make sure the message get to
# the user.
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.ooberror(bundle2required)
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 raise error.Abort(bundle2requiredmain,
hint=bundle2requiredhint)
Pierre-Yves David
bundle2: refactor error bundle creation for the wireprotocol...
r24796
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 r = exchange.unbundle(repo, gen, their_heads, 'serve',
Gregory Szorc
wireprotoserver: rename _client to client (API)...
r36086 proto.client())
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 if util.safehasattr(r, 'addpart'):
# The return looks streamable, we are in the bundle2 case
# and should return a stream.
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamreslegacy(gen=r.getchunks())
return wireprototypes.pushres(
r, output.getvalue() if output else '')
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084
finally:
Joerg Sonnenberger
wireproto: allow direct stream processing for unbundle...
r37432 cleanup()
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084
except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
# handle non-bundle2 case first
if not getattr(exc, 'duringunbundle2', False):
try:
Pierre-Yves David
bundle2: convey PushkeyFailed error over the wire...
r25493 raise
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 except error.Abort:
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 # The old code we moved used procutil.stderr directly.
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 # We did not change it to minimise code change.
# This need to be moved to something proper.
# Feel free to do it.
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil.stderr.write("abort: %s\n" % exc)
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 if exc.hint is not None:
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil.stderr.write("(%s)\n" % exc.hint)
procutil.stderr.flush()
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.pushres(
0, output.getvalue() if output else '')
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 except error.PushRaced:
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.pusherr(
pycompat.bytestr(exc),
output.getvalue() if output else '')
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084
bundler = bundle2.bundle20(repo.ui)
for out in getattr(exc, '_bundle2salvagedoutput', ()):
bundler.addpart(out)
try:
try:
raise
except error.PushkeyFailed as exc:
# check client caps
remotecaps = getattr(exc, '_replycaps', None)
if (remotecaps is not None
and 'pushkey' not in remotecaps.get('error', ())):
# no support remote side, fallback to Abort handler.
raise
part = bundler.newpart('error:pushkey')
part.addparam('in-reply-to', exc.partid)
if exc.namespace is not None:
part.addparam('namespace', exc.namespace,
mandatory=False)
if exc.key is not None:
part.addparam('key', exc.key, mandatory=False)
if exc.new is not None:
part.addparam('new', exc.new, mandatory=False)
if exc.old is not None:
part.addparam('old', exc.old, mandatory=False)
if exc.ret is not None:
part.addparam('ret', exc.ret, mandatory=False)
except error.BundleValueError as exc:
errpart = bundler.newpart('error:unsupportedcontent')
if exc.parttype is not None:
errpart.addparam('parttype', exc.parttype)
if exc.params:
errpart.addparam('params', '\0'.join(exc.params))
except error.Abort as exc:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 manargs = [('message', stringutil.forcebytestr(exc))]
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 advargs = []
if exc.hint is not None:
advargs.append(('hint', exc.hint))
bundler.addpart(bundle2.bundlepart('error:abort',
manargs, advargs))
except error.PushRaced as exc:
Augie Fackler
wireproto: fix lingering str(exception) with util.forcebytestr(exception)...
r36332 bundler.newpart('error:pushraced',
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 [('message', stringutil.forcebytestr(exc))])
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamreslegacy(gen=bundler.getchunks())