##// END OF EJS Templates
win32mbcs: fix a `str` type conditional for py3...
win32mbcs: fix a `str` type conditional for py3 Differential Revision: https://phab.mercurial-scm.org/D7535

File last commit:

r44158:0dbea180 default
r44181:66210a20 stable
Show More
exchange.py
3086 lines | 102.4 KiB | text/x-python | PythonLexer
Mads Kiilerich
spelling: fixes from spell checker
r21024 # exchange.py - utility to exchange data between repos.
Pierre-Yves David
exchange: extract push function from localrepo...
r20345 #
# Copyright 2005-2007 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
exchange: use absolute_import
r27523 from __future__ import absolute_import
Boris Feld
pull: use 'phase-heads' to retrieve phase information...
r34323 import collections
Augie Fackler
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1...
r29341 import hashlib
Gregory Szorc
exchange: use absolute_import
r27523
from .i18n import _
from .node import (
hex,
nullid,
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 nullrev,
Gregory Szorc
exchange: use absolute_import
r27523 )
Augie Fackler
formatting: blacken the codebase...
r43346 from .thirdparty import attr
Gregory Szorc
exchange: use absolute_import
r27523 from . import (
bookmarks as bookmod,
bundle2,
changegroup,
discovery,
error,
Gregory Szorc
exchangev2: start to implement pull with wire protocol v2...
r39665 exchangev2,
Gregory Szorc
exchange: use absolute_import
r27523 lock as lockmod,
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 logexchange,
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 narrowspec,
Gregory Szorc
exchange: use absolute_import
r27523 obsolete,
Denis Laxalde
py3: fix sorting of obsolete markers in obsutil (issue6217)...
r43858 obsutil,
Gregory Szorc
exchange: use absolute_import
r27523 phases,
pushkey,
Pulkit Goyal
py3: use pycompat.strkwargs() to convert kwargs keys to str before passing
r32896 pycompat,
Gregory Szorc
exchange: use absolute_import
r27523 scmutil,
sslutil,
streamclone,
url as urlmod,
util,
Pulkit Goyal
exchange: pass includepats and excludepats as arguments to getbundle()...
r40527 wireprototypes,
Gregory Szorc
exchange: use absolute_import
r27523 )
Augie Fackler
formatting: blacken the codebase...
r43346 from .interfaces import repository
from .utils import stringutil
Pierre-Yves David
exchange: extract push function from localrepo...
r20345
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _NARROWACL_SECTION = b'narrowacl'
Gregory Szorc
exchange: move disabling of rev-branch-cache bundle part out of narrow...
r38825
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 # Maps bundle version human names to changegroup versions.
Augie Fackler
formatting: blacken the codebase...
r43346 _bundlespeccgversions = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'v1': b'01',
b'v2': b'02',
b'packed1': b's1',
b'bundle2': b'02', # legacy
Augie Fackler
formatting: blacken the codebase...
r43346 }
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 # Maps bundle version with content opts to choose which part to bundle
_bundlespeccontentopts = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'v1': {
b'changegroup': True,
b'cg.version': b'01',
b'obsolescence': False,
b'phases': False,
b'tagsfnodescache': False,
b'revbranchcache': False,
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 },
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'v2': {
b'changegroup': True,
b'cg.version': b'02',
b'obsolescence': False,
b'phases': False,
b'tagsfnodescache': True,
b'revbranchcache': True,
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 },
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'packed1': {b'cg.version': b's1'},
Augie Fackler
formatting: blacken the codebase...
r43346 }
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _bundlespeccontentopts[b'bundle2'] = _bundlespeccontentopts[b'v2']
Augie Fackler
formatting: blacken the codebase...
r43346
_bundlespecvariants = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"streamv2": {
b"changegroup": False,
b"streamv2": True,
b"tagsfnodescache": False,
b"revbranchcache": False,
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 }
}
Boris Feld
bundlespec: add support for some variants...
r37185
Gregory Szorc
exchange: reject new compression engines for v1 bundles (issue5506)...
r31473 # Compression engines allowed in version 1. THIS SHOULD NEVER CHANGE.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _bundlespecv1compengines = {b'gzip', b'bzip2', b'none'}
Gregory Szorc
exchange: reject new compression engines for v1 bundles (issue5506)...
r31473
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181 @attr.s
class bundlespec(object):
compression = attr.ib()
Joerg Sonnenberger
bundlespec: drop externalnames flag...
r37786 wirecompression = attr.ib()
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181 version = attr.ib()
Joerg Sonnenberger
bundlespec: drop externalnames flag...
r37786 wireversion = attr.ib()
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181 params = attr.ib()
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 contentopts = attr.ib()
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
bundlespec: drop externalnames flag...
r37786 def parsebundlespec(repo, spec, strict=True):
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 """Parse a bundle string specification into parts.
Bundle specifications denote a well-defined bundle/exchange format.
The content of a given specification should not change over time in
order to ensure that bundles produced by a newer version of Mercurial are
readable from an older version.
The string currently has the form:
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 <compression>-<type>[;<parameter0>[;<parameter1>]]
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640
Where <compression> is one of the supported compression formats
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 and <type> is (currently) a version string. A ";" can follow the type and
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 all text afterwards is interpreted as URI encoded, ";" delimited key=value
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 pairs.
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 If ``strict`` is True (the default) <compression> is required. Otherwise,
it is optional.
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181 Returns a bundlespec object of (compression, version, parameters).
Compression will be ``None`` if not in strict mode and a compression isn't
defined.
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 An ``InvalidBundleSpecification`` is raised when the specification is
not syntactically well formed.
An ``UnsupportedBundleSpecification`` is raised when the compression or
bundle type/version is not recognized.
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 Note: this function will likely eventually return a more complex data
structure, including bundle2 part information.
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639 """
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 def parseparams(s):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b';' not in s:
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 return s, {}
params = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 version, paramstr = s.split(b';', 1)
for p in paramstr.split(b';'):
if b'=' not in p:
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 raise error.InvalidBundleSpecification(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'invalid bundle specification: '
b'missing "=" in parameter: %s'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% p
)
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 key, value = p.split(b'=', 1)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 key = urlreq.unquote(key)
value = urlreq.unquote(value)
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 params[key] = value
return version, params
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if strict and b'-' not in spec:
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 raise error.InvalidBundleSpecification(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'invalid bundle specification; '
b'must be prefixed with compression: %s'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% spec
)
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'-' in spec:
compression, version = spec.split(b'-', 1)
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: obtain compression engines from the registrar...
r30440 if compression not in util.compengines.supportedbundlenames:
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 raise error.UnsupportedBundleSpecification(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'%s compression is not supported') % compression
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 version, params = parseparams(version)
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 if version not in _bundlespeccgversions:
raise error.UnsupportedBundleSpecification(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'%s is not a recognized bundle version') % version
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639 else:
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 # Value could be just the compression or just the version, in which
# case some defaults are assumed (but only when not in strict mode).
assert not strict
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: support parameters in bundle specification strings...
r26759 spec, params = parseparams(spec)
Gregory Szorc
exchange: obtain compression engines from the registrar...
r30440 if spec in util.compengines.supportedbundlenames:
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 compression = spec
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 version = b'v1'
Gregory Szorc
exchange: use v2 bundles for modern compression engines (issue5506)...
r31474 # Generaldelta repos require v2.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'generaldelta' in repo.requirements:
version = b'v2'
Gregory Szorc
exchange: use v2 bundles for modern compression engines (issue5506)...
r31474 # Modern compression engines require v2.
if compression not in _bundlespecv1compengines:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 version = b'v2'
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 elif spec in _bundlespeccgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if spec == b'packed1':
compression = b'none'
Gregory Szorc
exchange: support for streaming clone bundles...
r26756 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 compression = b'bzip2'
Gregory Szorc
exchange: refactor bundle specification parsing...
r26640 version = spec
else:
raise error.UnsupportedBundleSpecification(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'%s is not a recognized bundle specification') % spec
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Gregory Szorc
exchange: reject new compression engines for v1 bundles (issue5506)...
r31473 # Bundle version 1 only supports a known set of compression engines.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if version == b'v1' and compression not in _bundlespecv1compengines:
Gregory Szorc
exchange: reject new compression engines for v1 bundles (issue5506)...
r31473 raise error.UnsupportedBundleSpecification(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'compression engine %s is not supported on v1 bundles')
Augie Fackler
formatting: blacken the codebase...
r43346 % compression
)
Gregory Szorc
exchange: reject new compression engines for v1 bundles (issue5506)...
r31473
Gregory Szorc
exchange: parse requirements from stream clone specification string...
r26760 # The specification for packed1 can optionally declare the data formats
# required to apply it. If we see this metadata, compare against what the
# repo supports and error if the bundle isn't compatible.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if version == b'packed1' and b'requirements' in params:
requirements = set(params[b'requirements'].split(b','))
Gregory Szorc
exchange: parse requirements from stream clone specification string...
r26760 missingreqs = requirements - repo.supportedformats
if missingreqs:
raise error.UnsupportedBundleSpecification(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'missing support for repository features: %s')
% b', '.join(sorted(missingreqs))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: parse requirements from stream clone specification string...
r26760
Boris Feld
bundlespec: move computing the bundle contentops in parsebundlespec...
r37182 # Compute contentopts based on the version
contentopts = _bundlespeccontentopts.get(version, {}).copy()
Boris Feld
bundlespec: add support for some variants...
r37185 # Process the variants
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b"stream" in params and params[b"stream"] == b"v2":
variant = _bundlespecvariants[b"streamv2"]
Boris Feld
bundlespec: add support for some variants...
r37185 contentopts.update(variant)
Joerg Sonnenberger
bundlespec: drop externalnames flag...
r37786 engine = util.compengines.forbundlename(compression)
compression, wirecompression = engine.bundletype()
wireversion = _bundlespeccgversions[version]
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181
Augie Fackler
formatting: blacken the codebase...
r43346 return bundlespec(
compression, wirecompression, version, wireversion, params, contentopts
)
Gregory Szorc
exchange: move bundle specification parsing from cmdutil...
r26639
Pierre-Yves David
bundle2: add a ui argument to readbundle...
r21064 def readbundle(ui, fh, fname, vfs=None):
Pierre-Yves David
bundle2: prepare readbundle to return more that one type of bundle...
r21065 header = changegroup.readexactly(fh, 4)
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063
Pierre-Yves David
bundle2: prepare readbundle to return more that one type of bundle...
r21065 alg = None
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063 if not fname:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fname = b"stream"
if not header.startswith(b'HG') and header.startswith(b'\0'):
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063 fh = changegroup.headerlessfixup(fh, header)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 header = b"HG10"
alg = b'UN'
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063 elif vfs:
fname = vfs.join(fname)
Pierre-Yves David
bundle2: prepare readbundle to return more that one type of bundle...
r21065 magic, version = header[0:2], header[2:4]
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if magic != b'HG':
raise error.Abort(_(b'%s: not a Mercurial bundle') % fname)
if version == b'10':
Pierre-Yves David
bundle2: prepare readbundle to return more that one type of bundle...
r21065 if alg is None:
alg = changegroup.readexactly(fh, 2)
Sune Foldager
changegroup: rename bundle-related functions and classes...
r22390 return changegroup.cg1unpacker(fh, alg)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif version.startswith(b'2'):
Pierre-Yves David
bundle2.getunbundler: rename "header" to "magicstring"...
r25640 return bundle2.getunbundler(ui, fh, magicstring=magic + version)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif version == b'S1':
Gregory Szorc
exchange: support for streaming clone bundles...
r26756 return streamclone.streamcloneapplier(fh)
Pierre-Yves David
bundle2: prepare readbundle to return more that one type of bundle...
r21065 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(
_(b'%s: unknown bundle version %s') % (fname, version)
)
Pierre-Yves David
bundle2: move `readbundle` into the `exchange` module...
r21063
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 def getbundlespec(ui, fh):
"""Infer the bundlespec from a bundle file handle.
The input file handle is seeked and the original seek position is not
restored.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 def speccompression(alg):
Gregory Szorc
exchange: obtain compression engines from the registrar...
r30440 try:
return util.compengines.forbundletype(alg).bundletype()[0]
except KeyError:
return None
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883
b = readbundle(ui, fh, None)
if isinstance(b, changegroup.cg1unpacker):
alg = b._type
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if alg == b'_truncatedBZ':
alg = b'BZ'
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 comp = speccompression(alg)
if not comp:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'unknown compression algorithm: %s') % alg)
return b'%s-v1' % comp
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 elif isinstance(b, bundle2.unbundle20):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'Compression' in b.params:
comp = speccompression(b.params[b'Compression'])
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 if not comp:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(
_(b'unknown compression algorithm: %s') % comp
)
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 comp = b'none'
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883
version = None
for part in b.iterparts():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if part.type == b'changegroup':
version = part.params[b'version']
if version in (b'01', b'02'):
version = b'v2'
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'changegroup version %s does not have '
b'a known bundlespec'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% version,
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 hint=_(b'try upgrading your Mercurial client'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif part.type == b'stream2' and version is None:
Boris Feld
bundlespec: add support for some variants...
r37185 # A stream2 part requires to be part of a v2 bundle
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 requirements = urlreq.unquote(part.params[b'requirements'])
Boris Feld
bundlespec: add support for some variants...
r37185 splitted = requirements.split()
params = bundle2._formatrequirementsparams(splitted)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'none-v2;stream=v2;%s' % params
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883
if not version:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'could not identify changegroup version in bundle')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'%s-%s' % (comp, version)
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 elif isinstance(b, streamclone.streamcloneapplier):
requirements = streamclone.readbundle1header(fh)[2]
Boris Feld
bundle: add the possibility to bundle a stream v2 part...
r37184 formatted = bundle2._formatrequirementsparams(requirements)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'none-packed1;%s' % formatted
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'unknown bundle type: %s') % b)
Gregory Szorc
exchange: implement function for inferring bundle specification...
r27883
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
computeoutgoing: move the function from 'changegroup' to 'exchange'...
r29808 def _computeoutgoing(repo, heads, common):
"""Computes which revs are outgoing given a set of common
and a set of heads.
This is a separate function so extensions can have access to
the logic.
Returns a discovery.outgoing object.
"""
cl = repo.changelog
if common:
hasnode = cl.hasnode
common = [n for n in common if hasnode(n)]
else:
common = [nullid]
if not heads:
heads = cl.heads()
return discovery.outgoing(repo, common, heads)
Augie Fackler
formatting: blacken the codebase...
r43346
av6
push: config option to control behavior when pushing to a publishing server...
r40803 def _checkpublish(pushop):
repo = pushop.repo
ui = repo.ui
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 behavior = ui.config(b'experimental', b'auto-publish')
if pushop.publish or behavior not in (b'warn', b'confirm', b'abort'):
av6
push: config option to control behavior when pushing to a publishing server...
r40803 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotephases = listkeys(pushop.remote, b'phases')
if not remotephases.get(b'publishing', False):
av6
push: config option to control behavior when pushing to a publishing server...
r40803 return
if pushop.revs is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 published = repo.filtered(b'served').revs(b'not public()')
av6
push: config option to control behavior when pushing to a publishing server...
r40803 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 published = repo.revs(b'::%ln - public()', pushop.revs)
av6
push: config option to control behavior when pushing to a publishing server...
r40803 if published:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if behavior == b'warn':
ui.warn(
_(b'%i changesets about to be published\n') % len(published)
)
elif behavior == b'confirm':
Augie Fackler
formatting: blacken the codebase...
r43346 if ui.promptchoice(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'push and publish %i changesets (yn)?$$ &Yes $$ &No')
Augie Fackler
formatting: blacken the codebase...
r43346 % len(published)
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'user quit'))
elif behavior == b'abort':
msg = _(b'push would publish %i changesets') % len(published)
Augie Fackler
formatting: blacken the codebase...
r43346 hint = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"use --publish or adjust 'experimental.auto-publish'"
b" config"
Augie Fackler
formatting: blacken the codebase...
r43346 )
av6
push: config option to control behavior when pushing to a publishing server...
r40803 raise error.Abort(msg, hint=hint)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: rename the _canusebundle2 method to _forcebundle1...
r29682 def _forcebundle1(op):
"""return true if a pull/push must use bundle1
Pierre-Yves David
exchange: introduce a '_canusebundle2' function...
r24650
Pierre-Yves David
bundle2: add a devel option controling bundle version used for exchange...
r29683 This function is used to allow testing of the older bundle version"""
ui = op.repo.ui
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 # The goal is this config is to allow developer to choose the bundle
Pierre-Yves David
bundle2: add a devel option controling bundle version used for exchange...
r29683 # version used during exchanged. This is especially handy during test.
# Value is a list of bundle version to be picked from, highest version
# should be used.
#
# developer config: devel.legacy.exchange
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 exchange = ui.configlist(b'devel', b'legacy.exchange')
forcebundle1 = b'bundle2' not in exchange and b'bundle1' in exchange
return forcebundle1 or not op.remote.capable(b'bundle2')
Pierre-Yves David
exchange: introduce a '_canusebundle2' function...
r24650
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: introduce a pushoperation object...
r20346 class pushoperation(object):
"""A object that represent a single push operation
Nathan Goldbaum
pushoperation: fix language issues in docstring
r28456 Its purpose is to carry push related state and very common operations.
Pierre-Yves David
push: introduce a pushoperation object...
r20346
Nathan Goldbaum
pushoperation: fix language issues in docstring
r28456 A new pushoperation should be created at the beginning of each push and
discarded afterward.
Pierre-Yves David
push: introduce a pushoperation object...
r20346 """
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self,
repo,
remote,
force=False,
revs=None,
newbranch=False,
bookmarks=(),
publish=False,
pushvars=None,
):
Pierre-Yves David
push: introduce a pushoperation object...
r20346 # repo we push from
self.repo = repo
Pierre-Yves David
push: ease access to current ui object...
r20347 self.ui = repo.ui
Pierre-Yves David
push: move `remote` argument in the push object...
r20348 # repo we push to
self.remote = remote
Pierre-Yves David
push: move `force` argument into the push object...
r20349 # force option provided
self.force = force
Pierre-Yves David
push: move `revs` argument into the push object...
r20350 # revs to be pushed (None is "all")
self.revs = revs
Pierre-Yves David
push: pass list of bookmark to `exchange.push`...
r22623 # bookmark explicitly pushed
self.bookmarks = bookmarks
Pierre-Yves David
push: move `newbranch` argument into the push object...
r20351 # allow push of new branch
self.newbranch = newbranch
Pierre-Yves David
push: add a ``pushop.stepsdone`` attribute...
r21901 # step already performed
# (used to check what steps have been already performed through bundle2)
self.stepsdone = set()
Pierre-Yves David
push: rename `pushop.ret` to `pushop.cgresult`...
r22615 # Integer version of the changegroup push result
Pierre-Yves David
push: move push return value in the push object...
r20439 # - None means nothing to push
# - 0 means HTTP error
# - 1 means we pushed and remote head count is unchanged *or*
# we have outgoing changesets but refused to push
# - other values as described by addchangegroup()
Pierre-Yves David
push: rename `pushop.ret` to `pushop.cgresult`...
r22615 self.cgresult = None
Pierre-Yves David
push: add `pushoperation.bkresult`...
r22624 # Boolean value for the bookmark push
self.bkresult = None
Mads Kiilerich
spelling: fixes from spell checker
r21024 # discover.outgoing object (contains common and outgoing data)
Pierre-Yves David
push: move outgoing object in the push object...
r20440 self.outgoing = None
push: add a way to allow concurrent pushes on unrelated heads...
r32709 # all remote topological heads before the push
Pierre-Yves David
push: move `remoteheads` into the push object...
r20462 self.remoteheads = None
push: add a way to allow concurrent pushes on unrelated heads...
r32709 # Details of the remote branch pre and post push
#
# mapping: {'branch': ([remoteheads],
# [newheads],
# [unsyncedheads],
# [discardedheads])}
# - branch: the branch name
# - remoteheads: the list of remote heads known locally
# None if the branch is new
# - newheads: the new remote heads (known locally) with outgoing pushed
# - unsyncedheads: the list of remote heads unknown locally.
# - discardedheads: the list of remote heads made obsolete by the push
self.pushbranchmap = None
Pierre-Yves David
push: move `incoming` into the push object...
r20464 # testable as a boolean indicating if any nodes are missing locally.
self.incoming = None
Boris Feld
phase: gather remote phase information in a summary object...
r34820 # summary of the remote phase situation
self.remotephases = None
Pierre-Yves David
push: perform phases discovery before the push...
r22019 # phases changes that must be pushed along side the changesets
self.outdatedphases = None
# phases changes that must be pushed if changeset push fails
self.fallbackoutdatedphases = None
Pierre-Yves David
push: move the list of obsmarker to push into the push operation...
r22034 # outgoing obsmarkers
Pierre-Yves David
push: introduce a discovery step for obsmarker...
r22035 self.outobsmarkers = set()
Valentin Gatien-Baron
exchange: avoid unnecessary conversion of bookmark nodes to hex (API)...
r43194 # outgoing bookmarks, list of (bm, oldnode | '', newnode | '')
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 self.outbookmarks = []
Eric Sumner
push: elevate phase transaction to cover entire operation...
r23437 # transaction manager
self.trmanager = None
Pierre-Yves David
push: catch and process PushkeyFailed error...
r25485 # map { pushkey partid -> callback handling failure}
# used to handle exception from mandatory pushkey part failure
self.pkfailcb = {}
Jun Wu
pushvars: do not mangle repo state...
r33886 # an iterable of pushvars or None
self.pushvars = pushvars
av6
push: add --publish flag to change phase of pushed changesets...
r40722 # publish pushed changesets
self.publish = publish
Pierre-Yves David
push: introduce a pushoperation object...
r20346
Pierre-Yves David
push: extract future heads computation into pushop...
r22014 @util.propertycache
def futureheads(self):
"""future remote heads if the changeset push succeeds"""
return self.outgoing.missingheads
Pierre-Yves David
push: extract fallback heads computation into pushop...
r22015 @util.propertycache
def fallbackheads(self):
"""future remote heads if the changeset push fails"""
if self.revs is None:
# not target to push, all common are relevant
return self.outgoing.commonheads
unfi = self.repo.unfiltered()
# I want cheads = heads(::missingheads and ::commonheads)
# (missingheads is revs with secret changeset filtered out)
#
# This can be expressed as:
# cheads = ( (missingheads and ::commonheads)
# + (commonheads and ::missingheads))"
# )
#
# while trying to push we already computed the following:
# common = (::commonheads)
# missing = ((commonheads::missingheads) - commonheads)
#
# We can pick:
# * missingheads part of common (::commonheads)
Durham Goode
exchange: allow fallbackheads to use lazy set behavior...
r26184 common = self.outgoing.common
Pierre-Yves David
push: extract fallback heads computation into pushop...
r22015 nm = self.repo.changelog.nodemap
cheads = [node for node in self.revs if nm[node] in common]
# and
# * commonheads parents on missing
Augie Fackler
formatting: blacken the codebase...
r43346 revset = unfi.set(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'%ln and parents(roots(%ln))',
Augie Fackler
formatting: blacken the codebase...
r43346 self.outgoing.commonheads,
self.outgoing.missing,
)
Pierre-Yves David
push: extract fallback heads computation into pushop...
r22015 cheads.extend(c.node() for c in revset)
return cheads
Pierre-Yves David
push: move common heads computation into pushop...
r22016 @property
def commonheads(self):
"""set of all common heads after changeset bundle push"""
Pierre-Yves David
push: rename `pushop.ret` to `pushop.cgresult`...
r22615 if self.cgresult:
Pierre-Yves David
push: move common heads computation into pushop...
r22016 return self.futureheads
else:
return self.fallbackheads
Pierre-Yves David
push: extract fallback heads computation into pushop...
r22015
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 # mapping of message used when pushing bookmark
Augie Fackler
formatting: blacken the codebase...
r43346 bookmsgmap = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'update': (
_(b"updating bookmark %s\n"),
_(b'updating bookmark %s failed!\n'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'export': (
_(b"exporting bookmark %s\n"),
_(b'exporting bookmark %s failed!\n'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'delete': (
_(b"deleting remote bookmark %s\n"),
_(b'deleting remote bookmark %s failed!\n'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
}
def push(
repo,
remote,
force=False,
revs=None,
newbranch=False,
bookmarks=(),
publish=False,
opargs=None,
):
Pierre-Yves David
exchange: extract push function from localrepo...
r20345 '''Push outgoing changesets (limited by revs) from a local
repository to remote. Return an integer:
- None means nothing to push
- 0 means HTTP error
- 1 means we pushed and remote head count is unchanged *or*
we have outgoing changesets but refused to push
- other values as described by addchangegroup()
'''
Sean Farley
exchange: add oparg to push so that extensions can wrap pushop
r26729 if opargs is None:
opargs = {}
Augie Fackler
formatting: blacken the codebase...
r43346 pushop = pushoperation(
repo,
remote,
force,
revs,
newbranch,
bookmarks,
publish,
**pycompat.strkwargs(opargs)
)
Pierre-Yves David
push: move `remote` argument in the push object...
r20348 if pushop.remote.local():
Augie Fackler
formatting: blacken the codebase...
r43346 missing = (
set(pushop.repo.requirements) - pushop.remote.local().supported
)
Pierre-Yves David
exchange: extract push function from localrepo...
r20345 if missing:
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"required features are not"
b" supported in the destination:"
b" %s"
) % (b', '.join(sorted(missing)))
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg)
Pierre-Yves David
exchange: extract push function from localrepo...
r20345
Pierre-Yves David
push: move `remote` argument in the push object...
r20348 if not pushop.remote.canpush():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"destination does not support push"))
if not pushop.remote.capable(b'unbundle'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot push: destination does not support the '
b'unbundle wire protocol command'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667
Martin von Zweigbergk
exchange: drop now-unnecessary "local" from lock name variables...
r33788 # get lock as we might write phase data
wlock = lock = None
Pierre-Yves David
exchange: extract push function from localrepo...
r20345 try:
Martin von Zweigbergk
exchange: don't take wlock if bookmarks are stored in .hg/store/...
r42513 # bundle2 push may receive a reply bundle touching bookmarks
# requiring the wlock. Take it now to ensure proper ordering.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 maypushback = pushop.ui.configbool(b'experimental', b'bundle2.pushback')
Augie Fackler
formatting: blacken the codebase...
r43346 if (
(not _forcebundle1(pushop))
and maypushback
and not bookmod.bookmarksinstore(repo)
):
Martin von Zweigbergk
exchange: drop now-unnecessary "local" from lock name variables...
r33788 wlock = pushop.repo.wlock()
lock = pushop.repo.lock()
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.trmanager = transactionmanager(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.repo, b'push-response', pushop.remote.url()
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
push: continue without locking on lock failure other than EEXIST (issue5882)...
r38111 except error.LockUnavailable as err:
Pierre-Yves David
exchange: extract push function from localrepo...
r20345 # source repo cannot be locked.
# We do not abort the push, but just disable the local phase
# synchronisation.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = b'cannot lock source repository: %s\n' % stringutil.forcebytestr(
Augie Fackler
formatting: blacken the codebase...
r43346 err
)
Pierre-Yves David
push: ease access to current ui object...
r20347 pushop.ui.debug(msg)
Martin von Zweigbergk
exchange: remove need for "locked" variable...
r33789
Augie Fackler
cleanup: prefer nested context managers to \-continuations...
r41926 with wlock or util.nullcontextmanager():
with lock or util.nullcontextmanager():
with pushop.trmanager or util.nullcontextmanager():
pushop.repo.checkpush(pushop)
_checkpublish(pushop)
_pushdiscovery(pushop)
if not _forcebundle1(pushop):
_pushbundle2(pushop)
_pushchangeset(pushop)
_pushsyncphase(pushop)
_pushobsolete(pushop)
_pushbookmark(pushop)
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo.ui.configbool(b'experimental', b'remotenames'):
Pulkit Goyal
remotenames: synchronise remotenames after push also...
r38634 logexchange.pullremotenames(repo, remote)
Pierre-Yves David
push: `exchange.push` now returns the `pushoperation` object...
r22616 return pushop
Pierre-Yves David
push: move bookmarks exchange in the exchange module...
r20352
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: make discovery extensible...
r22018 # list of steps to perform discovery before push
pushdiscoveryorder = []
# Mapping between step name and function
#
# This exists to help extensions wrap steps if necessary
pushdiscoverymapping = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: make discovery extensible...
r22018 def pushdiscovery(stepname):
"""decorator for function performing discovery before push
The function is added to the step -> function mapping and appended to the
list of steps. Beware that decorated function will be added in order (this
may matter).
You can only use this decorator for a new step, if you want to wrap a step
from an extension, change the pushdiscovery dictionary directly."""
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: make discovery extensible...
r22018 def dec(func):
assert stepname not in pushdiscoverymapping
pushdiscoverymapping[stepname] = func
pushdiscoveryorder.append(stepname)
return func
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: make discovery extensible...
r22018 return dec
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: move discovery in its own function...
r20466 def _pushdiscovery(pushop):
Pierre-Yves David
push: make discovery extensible...
r22018 """Run all discovery steps"""
for stepname in pushdiscoveryorder:
step = pushdiscoverymapping[stepname]
step(pushop)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pushdiscovery(b'changeset')
Pierre-Yves David
push: make discovery extensible...
r22018 def _pushdiscoverychangeset(pushop):
"""discover the changeset that need to be pushed"""
Pierre-Yves David
push: move discovery in its own function...
r20466 fci = discovery.findcommonincoming
Boris Feld
push: restrict common discovery to the pushed set...
r35306 if pushop.revs:
Augie Fackler
formatting: blacken the codebase...
r43346 commoninc = fci(
pushop.repo,
pushop.remote,
force=pushop.force,
ancestorsof=pushop.revs,
)
Boris Feld
push: restrict common discovery to the pushed set...
r35306 else:
commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
Pierre-Yves David
push: move discovery in its own function...
r20466 common, inc, remoteheads = commoninc
fco = discovery.findcommonoutgoing
Augie Fackler
formatting: blacken the codebase...
r43346 outgoing = fco(
pushop.repo,
pushop.remote,
onlyheads=pushop.revs,
commoninc=commoninc,
force=pushop.force,
)
Pierre-Yves David
push: move discovery in its own function...
r20466 pushop.outgoing = outgoing
pushop.remoteheads = remoteheads
pushop.incoming = inc
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pushdiscovery(b'phase')
Pierre-Yves David
push: perform phases discovery before the push...
r22019 def _pushdiscoveryphase(pushop):
"""discover the phase that needs to be pushed
(computed for both success and failure case for changesets push)"""
outgoing = pushop.outgoing
unfi = pushop.repo.unfiltered()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotephases = listkeys(pushop.remote, b'phases')
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.configbool(b'ui', b'_usedassubrepo')
Augie Fackler
formatting: blacken the codebase...
r43346 and remotephases # server supports phases
and not pushop.outgoing.missing # no changesets to be pushed
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and remotephases.get(b'publishing', False)
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
subrepo: detect issue3781 case earlier so it apply to bundle2...
r25337 # When:
# - this is a subrepo push
# - and remote support phase
# - and no changeset are to be pushed
# - and remote is publishing
Boris Feld
exchange: fix issue3781 reference in the comment...
r34818 # We may be in issue 3781 case!
Pierre-Yves David
subrepo: detect issue3781 case earlier so it apply to bundle2...
r25337 # We drop the possible phase synchronisation done by
# courtesy to publish changesets possibly locally draft
# on the remote.
Boris Feld
phase: simplify the check for issue3781 shortcut in discovery...
r34819 pushop.outdatedphases = []
pushop.fallbackoutdatedphases = []
return
Boris Feld
phase: gather remote phase information in a summary object...
r34820
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.remotephases = phases.remotephasessummary(
pushop.repo, pushop.fallbackheads, remotephases
)
Boris Feld
phase: gather remote phase information in a summary object...
r34820 droots = pushop.remotephases.draftroots
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extracond = b''
Boris Feld
phase: gather remote phase information in a summary object...
r34820 if not pushop.remotephases.publishing:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extracond = b' and public()'
revset = b'heads((%%ln::%%ln) %s)' % extracond
Pierre-Yves David
push: perform phases discovery before the push...
r22019 # Get the list of all revs draft on remote by public here.
# XXX Beware that revset break if droots is not strictly
# XXX root we may want to ensure it is but it is costly
fallback = list(unfi.set(revset, droots, pushop.fallbackheads))
av6
push: add --publish flag to change phase of pushed changesets...
r40722 if not pushop.remotephases.publishing and pushop.publish:
Augie Fackler
formatting: blacken the codebase...
r43346 future = list(
unfi.set(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'%ln and (not public() or %ln::)', pushop.futureheads, droots
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
av6
push: add --publish flag to change phase of pushed changesets...
r40722 elif not outgoing.missing:
Pierre-Yves David
push: perform phases discovery before the push...
r22019 future = fallback
else:
# adds changeset we are going to push as draft
#
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 # should not be necessary for publishing server, but because of an
Pierre-Yves David
push: perform phases discovery before the push...
r22019 # issue fixed in xxxxx we have to do it anyway.
Augie Fackler
formatting: blacken the codebase...
r43346 fdroots = list(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 unfi.set(b'roots(%ln + %ln::)', outgoing.missing, droots)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
push: perform phases discovery before the push...
r22019 fdroots = [f.node() for f in fdroots]
future = list(unfi.set(revset, fdroots, pushop.futureheads))
pushop.outdatedphases = future
pushop.fallbackoutdatedphases = fallback
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pushdiscovery(b'obsmarker')
Pierre-Yves David
push: introduce a discovery step for obsmarker...
r22035 def _pushdiscoveryobsmarkers(pushop):
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775 if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt):
return
if not pushop.repo.obsstore:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'obsolete' not in listkeys(pushop.remote, b'namespaces'):
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775 return
repo = pushop.repo
# very naive computation, that can be quite expensive on big repo.
# However: evolution is currently slow on them anyway.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nodes = (c.node() for c in repo.set(b'::%ln', pushop.futureheads))
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775 pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes)
Pierre-Yves David
push: introduce a discovery step for obsmarker...
r22035
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pushdiscovery(b'bookmarks')
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 def _pushdiscoverybookmarks(pushop):
ui = pushop.ui
repo = pushop.repo.unfiltered()
remote = pushop.remote
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b"checking for updated bookmarks\n")
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 ancestors = ()
if pushop.revs:
Yuya Nishihara
py3: fix revnums in bookmark discovery to be consumable more than once
r38623 revnums = pycompat.maplist(repo.changelog.rev, pushop.revs)
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 ancestors = repo.changelog.ancestors(revnums, inclusive=True)
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotebookmark = bookmod.unhexlifybookmarks(listkeys(remote, b'bookmarks'))
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239
Augie Fackler
formatting: blacken the codebase...
r43346 explicit = {
repo._bookmarks.expandname(bookmark) for bookmark in pushop.bookmarks
}
Pierre-Yves David
push: gather all bookmark decisions together...
r22651
Stanislau Hlebik
bookmarks: make bookmarks.comparebookmarks accept binary nodes (API)...
r30583 comp = bookmod.comparebookmarks(repo, repo._bookmarks, remotebookmark)
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956 return _processcompared(pushop, ancestors, explicit, remotebookmark, comp)
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956 def _processcompared(pushop, pushed, explicit, remotebms, comp):
Valentin Gatien-Baron
doc: fix up confusing doc comment...
r43184 """take decision on bookmarks to push to the remote repo
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956
Valentin Gatien-Baron
doc: fix up confusing doc comment...
r43184 Exists to help extensions alter this behavior.
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956 """
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
Stanislau Hlebik
bookmarks: make bookmarks.comparebookmarks accept binary nodes (API)...
r30583
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956 repo = pushop.repo
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 for b, scid, dcid in advsrc:
Pierre-Yves David
push: gather all bookmark decisions together...
r22651 if b in explicit:
explicit.remove(b)
Boris Feld
push-discovery: extract the bookmark comparison logic in its own function...
r36956 if not pushed or repo[scid].rev() in pushed:
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 pushop.outbookmarks.append((b, dcid, scid))
Pierre-Yves David
push: gather all bookmark decisions together...
r22651 # search added bookmark
for b, scid, dcid in addsrc:
if b in explicit:
explicit.remove(b)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.outbookmarks.append((b, b'', scid))
Pierre-Yves David
push: gather all bookmark decisions together...
r22651 # search for overwritten bookmark
Stanislau Hlebik
bookmarks: make bookmarks.comparebookmarks accept binary nodes (API)...
r30583 for b, scid, dcid in list(advdst) + list(diverge) + list(differ):
Pierre-Yves David
push: gather all bookmark decisions together...
r22651 if b in explicit:
explicit.remove(b)
pushop.outbookmarks.append((b, dcid, scid))
# search for bookmark to delete
for b, scid, dcid in adddst:
if b in explicit:
explicit.remove(b)
# treat as "deleted locally"
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.outbookmarks.append((b, dcid, b''))
Gregory Szorc
exchange: don't report failure from identical bookmarks...
r23082 # identical bookmarks shouldn't get reported
for b, scid, dcid in same:
if b in explicit:
explicit.remove(b)
Pierre-Yves David
push: gather all bookmark decisions together...
r22651
if explicit:
explicit = sorted(explicit)
# we should probably list all of them
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bookmark %s does not exist on the local '
b'or remote repository!\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% explicit[0]
)
Pierre-Yves David
push: gather all bookmark decisions together...
r22651 pushop.bkresult = 2
pushop.outbookmarks.sort()
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: move outgoing check logic in its own function...
r20465 def _pushcheckoutgoing(pushop):
outgoing = pushop.outgoing
unfi = pushop.repo.unfiltered()
if not outgoing.missing:
# nothing to push
scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded)
return False
# something to push
if not pushop.force:
# if repo.obsstore == False --> no obsolete
# then, save the iteration
if unfi.obsstore:
# this message are here for 80 char limit reason
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mso = _(b"push includes obsolete changeset: %s!")
mspd = _(b"push includes phase-divergent changeset: %s!")
mscd = _(b"push includes content-divergent changeset: %s!")
Augie Fackler
formatting: blacken the codebase...
r43346 mst = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"orphan": _(b"push includes orphan changeset: %s!"),
b"phase-divergent": mspd,
b"content-divergent": mscd,
Augie Fackler
formatting: blacken the codebase...
r43346 }
Pierre-Yves David
push: move outgoing check logic in its own function...
r20465 # If we are to push if there is at least one
# obsolete or unstable changeset in missing, at
# least one of the missinghead will be obsolete or
# unstable. So checking heads only is ok
for node in outgoing.missingheads:
ctx = unfi[node]
if ctx.obsolete():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(mso % ctx)
Boris Feld
context: rename troubled into isunstable...
r33696 elif ctx.isunstable():
Boris Feld
context: rename troubles into instabilities...
r33692 # TODO print more than one instability in the abort
# message
raise error.Abort(mst[ctx.instabilities()[0]] % ctx)
Matt Mackall
bookmarks: mark internal-only config option
r25836
Ryan McElroy
exchange: pass pushop to discovery.checkheads...
r26935 discovery.checkheads(pushop)
Pierre-Yves David
push: move outgoing check logic in its own function...
r20465 return True
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 # List of names of steps to perform for an outgoing bundle2, order matters.
b2partsgenorder = []
# Mapping between step name and function
#
# This exists to help extensions wrap steps if necessary
b2partsgenmapping = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: add an 'idx' argument to the 'b2partsgenerator'...
r24731 def b2partsgenerator(stepname, idx=None):
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 """decorator for function generating bundle2 part
The function is added to the step -> function mapping and appended to the
list of steps. Beware that decorated functions will be added in order
(this may matter).
You can only use this decorator for new steps, if you want to wrap a step
from an extension, attack the b2partsgenmapping dictionary directly."""
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 def dec(func):
assert stepname not in b2partsgenmapping
b2partsgenmapping[stepname] = func
Pierre-Yves David
bundle2: add an 'idx' argument to the 'b2partsgenerator'...
r24731 if idx is None:
b2partsgenorder.append(stepname)
else:
b2partsgenorder.insert(idx, stepname)
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 return func
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 return dec
Augie Fackler
formatting: blacken the codebase...
r43346
Ryan McElroy
bundle2: generate check:heads in a independent function
r26428 def _pushb2ctxcheckheads(pushop, bundler):
"""Generate race condition checking parts
Mads Kiilerich
spelling: trivial spell checking
r26781 Exists as an independent function to aid extensions
Ryan McElroy
bundle2: generate check:heads in a independent function
r26428 """
push: add a way to allow concurrent pushes on unrelated heads...
r32709 # * 'force' do not check for push race,
# * if we don't push anything, there are nothing to check.
if not pushop.force and pushop.outgoing.missingheads:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 allowunrelated = b'related' in bundler.capabilities.get(
b'checkheads', ()
)
pushrace: avoid crash on bare push when using concurrent push mode...
r33133 emptyremote = pushop.pushbranchmap is None
if not allowunrelated or emptyremote:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'check:heads', data=iter(pushop.remoteheads))
push: add a way to allow concurrent pushes on unrelated heads...
r32709 else:
affected = set()
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for branch, heads in pycompat.iteritems(pushop.pushbranchmap):
push: add a way to allow concurrent pushes on unrelated heads...
r32709 remoteheads, newheads, unsyncedheads, discardedheads = heads
if remoteheads is not None:
remote = set(remoteheads)
affected |= set(discardedheads) & remote
affected |= remote - set(newheads)
if affected:
data = iter(sorted(affected))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'check:updated-heads', data=data)
Ryan McElroy
bundle2: generate check:heads in a independent function
r26428
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
phase: generate a push-race detection part on push...
r34822 def _pushing(pushop):
"""return True if we are pushing anything"""
Augie Fackler
formatting: blacken the codebase...
r43346 return bool(
pushop.outgoing.missing
or pushop.outdatedphases
or pushop.outobsmarkers
or pushop.outbookmarks
)
Boris Feld
phase: generate a push-race detection part on push...
r34822
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @b2partsgenerator(b'check-bookmarks')
Boris Feld
push: include a 'check:bookmarks' part when possible...
r35260 def _pushb2checkbookmarks(pushop, bundler):
"""insert bookmark move checking"""
if not _pushing(pushop) or pushop.force:
return
b2caps = bundle2.bundle2caps(pushop.remote)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hasbookmarkcheck = b'bookmarks' in b2caps
Boris Feld
push: include a 'check:bookmarks' part when possible...
r35260 if not (pushop.outbookmarks and hasbookmarkcheck):
return
data = []
for book, old, new in pushop.outbookmarks:
data.append((book, old))
checkdata = bookmod.binaryencode(data)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'check:bookmarks', data=checkdata)
@b2partsgenerator(b'check-phases')
Boris Feld
phase: generate a push-race detection part on push...
r34822 def _pushb2checkphases(pushop, bundler):
"""insert phase move checking"""
if not _pushing(pushop) or pushop.force:
return
b2caps = bundle2.bundle2caps(pushop.remote)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hasphaseheads = b'heads' in b2caps.get(b'phases', ())
Boris Feld
phase: generate a push-race detection part on push...
r34822 if pushop.remotephases is not None and hasphaseheads:
# check that the remote phase has not changed
checks = [[] for p in phases.allphases]
checks[phases.public].extend(pushop.remotephases.publicheads)
checks[phases.draft].extend(pushop.remotephases.draftroots)
if any(checks):
for nodes in checks:
nodes.sort()
checkdata = phases.binaryencode(checks)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'check:phases', data=checkdata)
@b2partsgenerator(b'changeset')
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 def _pushb2ctx(pushop, bundler):
"""handle changegroup push through bundle2
Pierre-Yves David
push: rename `pushop.ret` to `pushop.cgresult`...
r22615 addchangegroup result is stored in the ``pushop.cgresult`` attribute.
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'changesets' in pushop.stepsdone:
Pierre-Yves David
push: use `stepsdone` to control changegroup push through bundle10 or bundle20...
r21902 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'changesets')
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 # Send known heads to the server for race detection.
Pierre-Yves David
bundle2-push: move changegroup push validation inside _pushb2ctx...
r21903 if not _pushcheckoutgoing(pushop):
return
Mads Kiilerich
localrepo: refactor prepushoutgoinghook to take a pushop...
r28876 pushop.repo.prepushoutgoinghooks(pushop)
Ryan McElroy
bundle2: generate check:heads in a independent function
r26428
_pushb2ctxcheckheads(pushop, bundler)
Pierre-Yves David
push: send highest changegroup format supported by both side...
r23180 b2caps = bundle2.bundle2caps(pushop.remote)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 version = b'01'
cgversions = b2caps.get(b'changegroup')
Martin von Zweigbergk
exchange: make _pushb2ctx() look more like _getbundlechangegrouppart()...
r28668 if cgversions: # 3.1 and 3.2 ship with an empty value
Augie Fackler
formatting: blacken the codebase...
r43346 cgversions = [
v
for v in cgversions
if v in changegroup.supportedoutgoingversions(pushop.repo)
]
Pierre-Yves David
push: send highest changegroup format supported by both side...
r23180 if not cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no common changegroup version'))
Pierre-Yves David
push: send highest changegroup format supported by both side...
r23180 version = max(cgversions)
Augie Fackler
formatting: blacken the codebase...
r43346 cgstream = changegroup.makestream(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.repo, pushop.outgoing, version, b'push'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgpart = bundler.newpart(b'changegroup', data=cgstream)
Martin von Zweigbergk
exchange: make _pushb2ctx() look more like _getbundlechangegrouppart()...
r28668 if cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgpart.addparam(b'version', version)
if b'treemanifest' in pushop.repo.requirements:
cgpart.addparam(b'treemanifest', b'1')
sidedata: apply basic but tight security around exchange...
r43401 if b'exp-sidedata-flag' in pushop.repo.requirements:
cgpart.addparam(b'exp-sidedata', b'1')
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 def handlereply(op):
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 """extract addchangegroup returns from server reply"""
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 cgreplies = op.records.getreplies(cgpart.id)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert len(cgreplies[b'changegroup']) == 1
pushop.cgresult = cgreplies[b'changegroup'][0][b'return']
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2-push: extract changegroup logic in its own function...
r21899 return handlereply
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @b2partsgenerator(b'phase')
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 def _pushb2phases(pushop, bundler):
"""handle phase push through bundle2"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'phases' in pushop.stepsdone:
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 return
b2caps = bundle2.bundle2caps(pushop.remote)
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837 ui = pushop.repo.ui
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 legacyphase = b'phases' in ui.configlist(b'devel', b'legacy.exchange')
haspushkey = b'pushkey' in b2caps
hasphaseheads = b'heads' in b2caps.get(b'phases', ())
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837
if hasphaseheads and not legacyphase:
Boris Feld
exchange: propagate the subfunctions return...
r34911 return _pushb2phaseheads(pushop, bundler)
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837 elif haspushkey:
Boris Feld
exchange: propagate the subfunctions return...
r34911 return _pushb2phasespushkey(pushop, bundler)
Boris Feld
phase: isolate logic to update remote phrase through bundle2 pushkey...
r34823
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837 def _pushb2phaseheads(pushop, bundler):
"""push phase information through a bundle2 - binary part"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'phases')
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837 if pushop.outdatedphases:
updates = [[] for p in phases.allphases]
updates[0].extend(h.node() for h in pushop.outdatedphases)
phasedata = phases.binaryencode(updates)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'phase-heads', data=phasedata)
Boris Feld
phase: use a binary phase part to push through bundle2 (BC)...
r34837
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
phase: isolate logic to update remote phrase through bundle2 pushkey...
r34823 def _pushb2phasespushkey(pushop, bundler):
"""push phase information through a bundle2 - pushkey part"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'phases')
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 part2node = []
Pierre-Yves David
phases: abort the whole push if phases fail to update (BC)...
r25502
def handlefailure(pushop, exc):
targetid = int(exc.partid)
for partid, node in part2node:
if partid == targetid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'updating %s to public failed') % node)
Pierre-Yves David
phases: abort the whole push if phases fail to update (BC)...
r25502
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 enc = pushkey.encode
for newremotehead in pushop.outdatedphases:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'pushkey')
part.addparam(b'namespace', enc(b'phases'))
part.addparam(b'key', enc(newremotehead.hex()))
part.addparam(b'old', enc(b'%d' % phases.draft))
part.addparam(b'new', enc(b'%d' % phases.public))
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 part2node.append((part.id, newremotehead))
Pierre-Yves David
phases: abort the whole push if phases fail to update (BC)...
r25502 pushop.pkfailcb[part.id] = handlefailure
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 def handlereply(op):
for partid, node in part2node:
partrep = op.records.getreplies(partid)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 results = partrep[b'pushkey']
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 assert len(results) <= 1
msg = None
if not results:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'server ignored update of %s to public!\n') % node
elif not int(results[0][b'return']):
msg = _(b'updating %s to public failed!\n') % node
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 if msg is not None:
pushop.ui.warn(msg)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 return handlereply
Pierre-Yves David
bundle2-push: introduce a list of part generating functions...
r21904
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @b2partsgenerator(b'obsmarkers')
Pierre-Yves David
push: use bundle2 to push obsmarkers when possible
r22347 def _pushb2obsmarkers(pushop, bundler):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'obsmarkers' in pushop.stepsdone:
Pierre-Yves David
push: use bundle2 to push obsmarkers when possible
r22347 return
remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
if obsolete.commonversion(remoteversions) is None:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'obsmarkers')
Pierre-Yves David
push: use bundle2 to push obsmarkers when possible
r22347 if pushop.outobsmarkers:
Denis Laxalde
py3: fix sorting of obsolete markers in obsutil (issue6217)...
r43858 markers = obsutil.sortedmarkers(pushop.outobsmarkers)
bundle2: move function building obsmarker-part in the bundle2 module...
r32515 bundle2.buildobsmarkerspart(bundler, markers)
Pierre-Yves David
push: use bundle2 to push obsmarkers when possible
r22347
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @b2partsgenerator(b'bookmarks')
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 def _pushb2bookmarks(pushop, bundler):
Martin von Zweigbergk
exchange: s/phase/bookmark/ in _pushb2bookmarks()
r25895 """handle bookmark push through bundle2"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'bookmarks' in pushop.stepsdone:
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 return
b2caps = bundle2.bundle2caps(pushop.remote)
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 legacy = pushop.repo.ui.configlist(b'devel', b'legacy.exchange')
legacybooks = b'bookmarks' in legacy
if not legacybooks and b'bookmarks' in b2caps:
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 return _pushb2bookmarkspart(pushop, bundler)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif b'pushkey' in b2caps:
Boris Feld
push: move bundle2-pushkey based bookmarks exchange in its own function...
r35263 return _pushb2bookmarkspushkey(pushop, bundler)
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 def _bmaction(old, new):
"""small utility for bookmark pushing"""
if not old:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'export'
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 elif not new:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'delete'
return b'update'
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
exchange: abort on pushing bookmarks pointing to secret changesets (issue6159)...
r43082 def _abortonsecretctx(pushop, node, b):
"""abort if a given bookmark points to a secret changeset"""
if node and pushop.repo[node].phase() == phases.secret:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'cannot push bookmark %s as it points to a secret changeset') % b
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
exchange: abort on pushing bookmarks pointing to secret changesets (issue6159)...
r43082
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 def _pushb2bookmarkspart(pushop, bundler):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'bookmarks')
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 if not pushop.outbookmarks:
return
allactions = []
data = []
for book, old, new in pushop.outbookmarks:
Navaneeth Suresh
exchange: abort on pushing bookmarks pointing to secret changesets (issue6159)...
r43082 _abortonsecretctx(pushop, new, book)
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265 data.append((book, new))
allactions.append((book, _bmaction(old, new)))
checkdata = bookmod.binaryencode(data)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'bookmarks', data=checkdata)
Boris Feld
bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165)...
r35265
def handlereply(op):
ui = pushop.ui
# if success
for book, action in allactions:
ui.status(bookmsgmap[action][0] % book)
return handlereply
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
push: move bundle2-pushkey based bookmarks exchange in its own function...
r35263 def _pushb2bookmarkspushkey(pushop, bundler):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'bookmarks')
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 part2book = []
enc = pushkey.encode
Pierre-Yves David
bookmarks: abort the whole push if bookmarks fails to update (BC)...
r25501
def handlefailure(pushop, exc):
targetid = int(exc.partid)
for partid, book, action in part2book:
if partid == targetid:
raise error.Abort(bookmsgmap[action][1].rstrip() % book)
# we should not be called for part we did not generated
assert False
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 for book, old, new in pushop.outbookmarks:
Navaneeth Suresh
exchange: abort on pushing bookmarks pointing to secret changesets (issue6159)...
r43082 _abortonsecretctx(pushop, new, book)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'pushkey')
part.addparam(b'namespace', enc(b'bookmarks'))
part.addparam(b'key', enc(book))
part.addparam(b'old', enc(hex(old)))
part.addparam(b'new', enc(hex(new)))
action = b'update'
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 if not old:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action = b'export'
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 elif not new:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action = b'delete'
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 part2book.append((part.id, book, action))
Pierre-Yves David
bookmarks: abort the whole push if bookmarks fails to update (BC)...
r25501 pushop.pkfailcb[part.id] = handlefailure
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 def handlereply(op):
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 ui = pushop.ui
for partid, book, action in part2book:
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 partrep = op.records.getreplies(partid)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 results = partrep[b'pushkey']
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 assert len(results) <= 1
if not results:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.warn(_(b'server ignored bookmark %s update\n') % book)
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ret = int(results[0][b'return'])
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 if ret:
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 ui.status(bookmsgmap[action][0] % book)
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 else:
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 ui.warn(bookmsgmap[action][1] % book)
Pierre-Yves David
push: set bkresult when pushing bookmarks through bundle2
r22649 if pushop.bkresult is not None:
pushop.bkresult = 1
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242 return handlereply
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @b2partsgenerator(b'pushvars', idx=0)
Pulkit Goyal
pushvars: move fb extension pushvars to core...
r33656 def _getbundlesendvars(pushop, bundler):
'''send shellvars via bundle2'''
Jun Wu
pushvars: do not mangle repo state...
r33886 pushvars = pushop.pushvars
if pushvars:
shellvars = {}
for raw in pushvars:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'=' not in raw:
Augie Fackler
formatting: blacken the codebase...
r43346 msg = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"unable to parse variable '%s', should follow "
b"'KEY=VALUE' or 'KEY=' format"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
pushvars: do not mangle repo state...
r33886 raise error.Abort(msg % raw)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 k, v = raw.split(b'=', 1)
Jun Wu
pushvars: do not mangle repo state...
r33886 shellvars[k] = v
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'pushvars')
Pulkit Goyal
pushvars: move fb extension pushvars to core...
r33656
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for key, value in pycompat.iteritems(shellvars):
Pulkit Goyal
pushvars: move fb extension pushvars to core...
r33656 part.addparam(key, value, mandatory=False)
Pierre-Yves David
push: add bookmarks to the unified bundle2 push...
r22242
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: allow using bundle2 for push...
r21061 def _pushbundle2(pushop):
"""push data to the remote using bundle2
The only currently supported type of data is changegroup but this will
evolve in the future."""
Pierre-Yves David
bundle2: introduce a bundle2caps function...
r21644 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
Augie Fackler
formatting: blacken the codebase...
r43346 pushback = pushop.trmanager and pushop.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'bundle2.pushback'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Eric Sumner
bundle2-push: provide transaction to reply unbundler...
r23439
Pierre-Yves David
bundle2: include client capabilities in the pushed bundle...
r21142 # create reply capability
Augie Fackler
formatting: blacken the codebase...
r43346 capsblob = bundle2.encodecaps(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundle2.getrepocaps(pushop.repo, allowpushback=pushback, role=b'client')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'replycaps', data=capsblob)
Pierre-Yves David
bundle2-push: introduce a list of part generating functions...
r21904 replyhandlers = []
Pierre-Yves David
push: rework the bundle2partsgenerators logic...
r22017 for partgenname in b2partsgenorder:
partgen = b2partsgenmapping[partgenname]
Pierre-Yves David
bundle2-push: introduce a list of part generating functions...
r21904 ret = partgen(pushop, bundler)
Pierre-Yves David
bundle2: only use callable return as reply handler...
r21941 if callable(ret):
replyhandlers.append(ret)
Pierre-Yves David
bundle2-push: introduce a list of part generating functions...
r21904 # do not push if nothing to push
Pierre-Yves David
bundle2-push: move changegroup push validation inside _pushb2ctx...
r21903 if bundler.nbparts <= 1:
return
Pierre-Yves David
bundle2: allow using bundle2 for push...
r21061 stream = util.chunkbuffer(bundler.getchunks())
Pierre-Yves David
bundle2: catch UnknownPartError during local push...
r21182 try:
Pierre-Yves David
push: catch and process PushkeyFailed error...
r25485 try:
Gregory Szorc
wireproto: use command executor for unbundle...
r37664 with pushop.remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 reply = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unbundle',
Augie Fackler
formatting: blacken the codebase...
r43346 {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bundle': stream,
b'heads': [b'force'],
b'url': pushop.remote.url(),
Augie Fackler
formatting: blacken the codebase...
r43346 },
).result()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.BundleValueError as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'missing support for %s') % exc)
Pierre-Yves David
push: catch and process PushkeyFailed error...
r25485 try:
trgetter = None
if pushback:
trgetter = pushop.trmanager.transaction
op = bundle2.processbundle(pushop.repo, reply, trgetter)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.BundleValueError as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'missing support for %s') % exc)
Gregory Szorc
bundle2: attribute remote failures to remote (issue4788)...
r26829 except bundle2.AbortFromPart as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.status(_(b'remote: %s\n') % exc)
Pierre-Yves David
bundle2: keep hint close to the primary message when remote abort...
r30908 if exc.hint is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.status(_(b'remote: %s\n') % (b'(%s)' % exc.hint))
raise error.Abort(_(b'push failed on remote'))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.PushkeyFailed as exc:
Pierre-Yves David
push: catch and process PushkeyFailed error...
r25485 partid = int(exc.partid)
if partid not in pushop.pkfailcb:
raise
pushop.pkfailcb[partid](pushop, exc)
Pierre-Yves David
bundle2-push: introduce a list of part generating functions...
r21904 for rephand in replyhandlers:
rephand(op)
Pierre-Yves David
bundle2: allow using bundle2 for push...
r21061
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: move changeset push logic in its own function...
r20463 def _pushchangeset(pushop):
"""Make the actual push of changeset bundle to remote repo"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'changesets' in pushop.stepsdone:
Pierre-Yves David
push: use `stepsdone` to control changegroup push through bundle10 or bundle20...
r21902 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'changesets')
Pierre-Yves David
bundle2-push: move changegroup push validation inside _pushb2ctx...
r21903 if not _pushcheckoutgoing(pushop):
return
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667
# Should have verified this in push().
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert pushop.remote.capable(b'unbundle')
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667
Mads Kiilerich
localrepo: refactor prepushoutgoinghook to take a pushop...
r28876 pushop.repo.prepushoutgoinghooks(pushop)
Pierre-Yves David
push: move changeset push logic in its own function...
r20463 outgoing = pushop.outgoing
# TODO: get bundlecaps from remote
bundlecaps = None
# create a changegroup from local
Augie Fackler
formatting: blacken the codebase...
r43346 if pushop.revs is None and not (
outgoing.excluded or pushop.repo.changelog.filteredrevs
):
Pierre-Yves David
push: move changeset push logic in its own function...
r20463 # push everything,
# use the fast path, no race possible on push
Augie Fackler
formatting: blacken the codebase...
r43346 cg = changegroup.makechangegroup(
pushop.repo,
outgoing,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'01',
b'push',
Augie Fackler
formatting: blacken the codebase...
r43346 fastpath=True,
bundlecaps=bundlecaps,
)
Pierre-Yves David
push: move changeset push logic in its own function...
r20463 else:
Augie Fackler
formatting: blacken the codebase...
r43346 cg = changegroup.makechangegroup(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.repo, outgoing, b'01', b'push', bundlecaps=bundlecaps
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
push: move changeset push logic in its own function...
r20463
# apply changegroup to remote
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667 # local repo finds heads on server, finds out what
# revs it must push. once revs transferred, if server
# finds it has different heads (someone else won
# commit/push race), server aborts.
if pushop.force:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remoteheads = [b'force']
Pierre-Yves David
push: move changeset push logic in its own function...
r20463 else:
Gregory Szorc
exchange: drop support for lock-based unbundling (BC)...
r33667 remoteheads = pushop.remoteheads
# ssh: return remote's addchangegroup()
# http: return remote's addchangegroup() or 0 for error
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads, pushop.repo.url())
Pierre-Yves David
push: move changeset push logic in its own function...
r20463
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 def _pushsyncphase(pushop):
Mads Kiilerich
spelling: fixes from spell checker
r21024 """synchronise phase information locally and remotely"""
Pierre-Yves David
push: extract new common set computation from phase synchronisation...
r20468 cheads = pushop.commonheads
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 # even when we don't push, exchanging phase data is useful
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotephases = listkeys(pushop.remote, b'phases')
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.configbool(b'ui', b'_usedassubrepo')
Augie Fackler
formatting: blacken the codebase...
r43346 and remotephases # server supports phases
and pushop.cgresult is None # nothing was pushed
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and remotephases.get(b'publishing', False)
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 # When:
# - this is a subrepo push
# - and remote support phase
# - and no changeset was pushed
# - and remote is publishing
# We may be in issue 3871 case!
# We drop the possible phase synchronisation done by
# courtesy to publish changesets possibly locally draft
# on the remote.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotephases = {b'publishing': b'True'}
Augie Fackler
formatting: blacken the codebase...
r43346 if not remotephases: # old server or public only reply from non-publishing
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 _localphasemove(pushop, cheads)
# don't push any phase data as there is nothing to push
else:
Augie Fackler
formatting: blacken the codebase...
r43346 ana = phases.analyzeremotephases(pushop.repo, cheads, remotephases)
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 pheads, droots = ana
### Apply remote phase on local
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if remotephases.get(b'publishing', False):
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 _localphasemove(pushop, cheads)
Augie Fackler
formatting: blacken the codebase...
r43346 else: # publish = False
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441 _localphasemove(pushop, pheads)
_localphasemove(pushop, cheads, phases.draft)
### Apply local phase on remote
Pierre-Yves David
push: rename `pushop.ret` to `pushop.cgresult`...
r22615 if pushop.cgresult:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'phases' in pushop.stepsdone:
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020 # phases already pushed though bundle2
return
Pierre-Yves David
push: perform phases discovery before the push...
r22019 outdated = pushop.outdatedphases
else:
outdated = pushop.fallbackoutdatedphases
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'phases')
Pierre-Yves David
push: include phase push in the unified bundle2 push...
r22020
Pierre-Yves David
push: perform phases discovery before the push...
r22019 # filter heads already turned public by the push
outdated = [c for c in outdated if c.node() not in pheads]
Pierre-Yves David
push: stop independent usage of bundle2 in syncphase (issue4454)...
r23376 # fallback to independent pushkey command
for newremotehead in outdated:
Gregory Szorc
exchange: use command executor for pushkey...
r37665 with pushop.remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 r = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pushkey',
Augie Fackler
formatting: blacken the codebase...
r43346 {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'namespace': b'phases',
b'key': newremotehead.hex(),
b'old': b'%d' % phases.draft,
b'new': b'%d' % phases.public,
Augie Fackler
formatting: blacken the codebase...
r43346 },
).result()
Gregory Szorc
exchange: use command executor for pushkey...
r37665
Pierre-Yves David
push: stop independent usage of bundle2 in syncphase (issue4454)...
r23376 if not r:
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'updating %s to public failed!\n') % newremotehead
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
push: move phases synchronisation function in its own function...
r20441
Pierre-Yves David
push: move local phase move in a normal function...
r20438 def _localphasemove(pushop, nodes, phase=phases.public):
"""move <nodes> to <phase> in the local source repo"""
Eric Sumner
push: elevate phase transaction to cover entire operation...
r23437 if pushop.trmanager:
Augie Fackler
formatting: blacken the codebase...
r43346 phases.advanceboundary(
pushop.repo, pushop.trmanager.transaction(), phase, nodes
)
Pierre-Yves David
push: move local phase move in a normal function...
r20438 else:
# repo is not locked, do not change any phases!
# Informs the user that phases should have been moved when
# applicable.
actualmoves = [n for n in nodes if phase < pushop.repo[n].phase()]
phasestr = phases.phasenames[phase]
if actualmoves:
Augie Fackler
formatting: blacken the codebase...
r43346 pushop.ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot lock source repo, skipping '
b'local %s phase update\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% phasestr
)
Pierre-Yves David
push: move local phase move in a normal function...
r20438
Pierre-Yves David
push: feed pushoperation object to _pushobsolete function...
r20433 def _pushobsolete(pushop):
Pierre-Yves David
push: drop now outdated comment...
r20434 """utility function to push obsolete markers to a remote"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'obsmarkers' in pushop.stepsdone:
Pierre-Yves David
push: use stepsdone for obsmarkers push...
r22036 return
Pierre-Yves David
push: feed pushoperation object to _pushobsolete function...
r20433 repo = pushop.repo
remote = pushop.remote
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'obsmarkers')
Pierre-Yves David
push: only push obsmarkers relevant to the "pushed subset"...
r22350 if pushop.outobsmarkers:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.ui.debug(b'try to push obsolete markers to remote\n')
Pierre-Yves David
push: move obsolescence marker exchange in the exchange module...
r20432 rslts = []
Denis Laxalde
py3: fix sorting of obsolete markers in obsutil (issue6217)...
r43858 markers = obsutil.sortedmarkers(pushop.outobsmarkers)
Denis Laxalde
py3: fix sorting of obsolete markers during push...
r43572 remotedata = obsolete._pushkeyescape(markers)
Pierre-Yves David
push: move obsolescence marker exchange in the exchange module...
r20432 for key in sorted(remotedata, reverse=True):
# reverse sort to ensure we end with dump0
data = remotedata[key]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rslts.append(remote.pushkey(b'obsolete', key, b'', data))
Pierre-Yves David
push: move obsolescence marker exchange in the exchange module...
r20432 if [r for r in rslts if not r]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'failed to push some obsolete markers!\n')
Pierre-Yves David
push: move obsolescence marker exchange in the exchange module...
r20432 repo.ui.warn(msg)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
push: feed pushoperation object to _pushbookmark function...
r20431 def _pushbookmark(pushop):
Pierre-Yves David
push: move bookmarks exchange in the exchange module...
r20352 """Update bookmark position on remote"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pushop.cgresult == 0 or b'bookmarks' in pushop.stepsdone:
Pierre-Yves David
pushbookmark: do not attempt to update bookmarks if the push failed (BC)...
r22228 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pushop.stepsdone.add(b'bookmarks')
Pierre-Yves David
push: feed pushoperation object to _pushbookmark function...
r20431 ui = pushop.ui
remote = pushop.remote
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650
Pierre-Yves David
push: move bookmark discovery with other discovery steps...
r22239 for b, old, new in pushop.outbookmarks:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action = b'update'
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 if not old:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action = b'export'
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 elif not new:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action = b'delete'
Gregory Szorc
exchange: use command executor for pushkey...
r37665
with remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 r = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pushkey',
Augie Fackler
formatting: blacken the codebase...
r43346 {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'namespace': b'bookmarks',
b'key': b,
b'old': hex(old),
b'new': hex(new),
Augie Fackler
formatting: blacken the codebase...
r43346 },
).result()
Gregory Szorc
exchange: use command executor for pushkey...
r37665
if r:
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 ui.status(bookmsgmap[action][0] % b)
Pierre-Yves David
push: move bookmarks exchange in the exchange module...
r20352 else:
Pierre-Yves David
push: prepare the issue of multiple kinds of messages...
r22650 ui.warn(bookmsgmap[action][1] % b)
# discovery can have set the value form invalid entry
if pushop.bkresult is not None:
pushop.bkresult = 1
Pierre-Yves David
exchange: extract pull function from localrepo...
r20469
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: introduce a pulloperation object...
r20472 class pulloperation(object):
"""A object that represent a single pull operation
Mike Edgar
exchange: swap "push" for "pull" in pulloperation docstring
r23219 It purpose is to carry pull related state and very common operation.
Pierre-Yves David
pull: introduce a pulloperation object...
r20472
Mads Kiilerich
spelling: fixes from spell checker
r21024 A new should be created at the beginning of each pull and discarded
Pierre-Yves David
pull: introduce a pulloperation object...
r20472 afterward.
"""
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self,
repo,
remote,
heads=None,
force=False,
bookmarks=(),
remotebookmarks=None,
streamclonerequested=None,
includepats=None,
excludepats=None,
depth=None,
):
Siddharth Agarwal
exchange: fix docs for pulloperation...
r20596 # repo we pull into
Pierre-Yves David
pull: introduce a pulloperation object...
r20472 self.repo = repo
Siddharth Agarwal
exchange: fix docs for pulloperation...
r20596 # repo we pull from
Pierre-Yves David
pull: move `remote` argument into pull object...
r20473 self.remote = remote
Pierre-Yves David
pull: move `heads` argument into pull object...
r20474 # revision we try to pull (None is "all")
self.heads = heads
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654 # bookmark pulled explicitly
Augie Fackler
formatting: blacken the codebase...
r43346 self.explicitbookmarks = [
repo._bookmarks.expandname(bookmark) for bookmark in bookmarks
]
Pierre-Yves David
pull: move `force` argument into pull object...
r20475 # do we force pull?
self.force = force
Gregory Szorc
exchange: teach pull about requested stream clones...
r26448 # whether a streaming clone was requested
self.streamclonerequested = streamclonerequested
Eric Sumner
pull: extract transaction logic into separate object...
r23436 # transaction manager
self.trmanager = None
Pierre-Yves David
pull: make pulled subset a propertycache of the pull object...
r20487 # set of common changeset between local and remote before pull
self.common = None
# set of pulled head
self.rheads = None
Mads Kiilerich
spelling: fixes from spell checker
r21024 # list of missing changeset to fetch remotely
Pierre-Yves David
pull: move `fetch` subset into the object...
r20488 self.fetch = None
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654 # remote bookmarks data
Pierre-Yves David
pull: prevent race condition in bookmark update when using -B (issue4689)...
r25446 self.remotebookmarks = remotebookmarks
Mads Kiilerich
spelling: fixes from spell checker
r21024 # result of changegroup pulling (used as return code by pull)
Pierre-Yves David
pull: move return code in the pull operation object...
r20898 self.cgresult = None
Pierre-Yves David
pull: use `stepsdone` instead of `todosteps`...
r22937 # list of step already done
self.stepsdone = set()
Gregory Szorc
exchange: record that we attempted to fetch a clone bundle...
r26689 # Whether we attempted a clone from pre-generated bundles.
self.clonebundleattempted = False
Gregory Szorc
exchange: support defining narrow file patterns for pull...
r39589 # Set of file patterns to include.
self.includepats = includepats
# Set of file patterns to exclude.
self.excludepats = excludepats
Gregory Szorc
exchange: support declaring pull depth...
r40367 # Number of ancestor changesets to pull from each pulled head.
self.depth = depth
Pierre-Yves David
pull: make pulled subset a propertycache of the pull object...
r20487
@util.propertycache
def pulledsubset(self):
"""heads of the set of changeset target by the pull"""
# compute target subset
if self.heads is None:
# We pulled every thing possible
# sync on everything common
Pierre-Yves David
pull: prevent duplicated entry in `op.pulledsubset`...
r20878 c = set(self.common)
ret = list(self.common)
for n in self.rheads:
if n not in c:
ret.append(n)
return ret
Pierre-Yves David
pull: make pulled subset a propertycache of the pull object...
r20487 else:
# We pulled a specific subset
# sync on this subset
return self.heads
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477
Gregory Szorc
exchange: expose bundle2 capabilities on pulloperation...
r26464 @util.propertycache
Gregory Szorc
exchange: expose bundle2 availability on pulloperation...
r26465 def canusebundle2(self):
Pierre-Yves David
bundle2: rename the _canusebundle2 method to _forcebundle1...
r29682 return not _forcebundle1(self)
Gregory Szorc
exchange: expose bundle2 availability on pulloperation...
r26465
@util.propertycache
Gregory Szorc
exchange: expose bundle2 capabilities on pulloperation...
r26464 def remotebundle2caps(self):
return bundle2.bundle2caps(self.remote)
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477 def gettransaction(self):
Eric Sumner
pull: extract transaction logic into separate object...
r23436 # deprecated; talk to trmanager directly
return self.trmanager.transaction()
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
util: add base class for transactional context managers...
r33790 class transactionmanager(util.transactional):
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23543 """An object to manage the life cycle of a transaction
Eric Sumner
pull: extract transaction logic into separate object...
r23436
It creates the transaction on demand and calls the appropriate hooks when
closing the transaction."""
Augie Fackler
formatting: blacken the codebase...
r43346
Eric Sumner
pull: extract transaction logic into separate object...
r23436 def __init__(self, repo, source, url):
self.repo = repo
self.source = source
self.url = url
self._tr = None
def transaction(self):
"""Return an open transaction object, constructing if necessary"""
if not self._tr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 trname = b'%s\n%s' % (self.source, util.hidepassword(self.url))
Eric Sumner
pull: extract transaction logic into separate object...
r23436 self._tr = self.repo.transaction(trname)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._tr.hookargs[b'source'] = self.source
self._tr.hookargs[b'url'] = self.url
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477 return self._tr
Eric Sumner
pull: extract transaction logic into separate object...
r23436 def close(self):
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477 """close transaction if created"""
if self._tr is not None:
Pierre-Yves David
exchange: use the postclose API on transaction...
r23222 self._tr.close()
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477
Eric Sumner
pull: extract transaction logic into separate object...
r23436 def release(self):
Pierre-Yves David
pull: move transaction logic into the pull object...
r20477 """release transaction if created"""
if self._tr is not None:
self._tr.release()
Pierre-Yves David
exchange: extract pull function from localrepo...
r20469
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775 def listkeys(remote, namespace):
with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return e.callcommand(b'listkeys', {b'namespace': namespace}).result()
Gregory Szorc
exchange: use command executor interface for calling listkeys...
r37775
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 def _fullpullbundle2(repo, pullop):
# The server may send a partial reply, i.e. when inlining
# pre-computed bundles. In that case, update the common
# set based on the results and pull another bundle.
#
# There are two indicators that the process is finished:
# - no changeset has been added, or
# - all remote heads are known locally.
# The head check must use the unfiltered view as obsoletion
# markers can hide heads.
unfi = repo.unfiltered()
unficl = unfi.changelog
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 def headsofdiff(h1, h2):
"""Returns heads(h1 % h2)"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 res = unfi.set(b'heads(%ln %% %ln)', h1, h2)
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 return set(ctx.node() for ctx in res)
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 def headsofunion(h1, h2):
"""Returns heads((h1 + h2) - null)"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 res = unfi.set(b'heads((%ln + %ln - null))', h1, h2)
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 return set(ctx.node() for ctx in res)
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 while True:
old_heads = unficl.heads()
clstart = len(unficl)
_pullbundle2(pullop)
Martin von Zweigbergk
narrow: move requirement constant from changegroup to repository...
r38871 if repository.NARROW_REQUIREMENT in repo.requirements:
Joerg Sonnenberger
wireproto: support for pullbundles...
r37516 # XXX narrow clones filter the heads on the server side during
# XXX getbundle and result in partial replies as well.
# XXX Disable pull bundles in this case as band aid to avoid
# XXX extra round trips.
break
if clstart == len(unficl):
break
if all(unficl.hasnode(n) for n in pullop.rheads):
break
new_heads = headsofdiff(unficl.heads(), old_heads)
pullop.common = headsofunion(new_heads, pullop.common)
pullop.rheads = set(pullop.rheads) - pullop.common
Augie Fackler
formatting: blacken the codebase...
r43346
def pull(
repo,
remote,
heads=None,
force=False,
bookmarks=(),
opargs=None,
streamclonerequested=None,
includepats=None,
excludepats=None,
depth=None,
):
Gregory Szorc
exchange: add docstring to pull()...
r26440 """Fetch repository data from a remote.
This is the main function used to retrieve data from a remote repository.
``repo`` is the local repository to clone into.
``remote`` is a peer instance.
``heads`` is an iterable of revisions we want to pull. ``None`` (the
default) means to pull everything from the remote.
``bookmarks`` is an iterable of bookmarks requesting to be pulled. By
default, all remote bookmarks are pulled.
``opargs`` are additional keyword arguments to pass to ``pulloperation``
initialization.
Gregory Szorc
exchange: teach pull about requested stream clones...
r26448 ``streamclonerequested`` is a boolean indicating whether a "streaming
clone" is requested. A "streaming clone" is essentially a raw file copy
of revlogs from the server. This only works when the local repository is
empty. The default value of ``None`` means to respect the server
configuration for preferring stream clones.
Gregory Szorc
exchange: support defining narrow file patterns for pull...
r39589 ``includepats`` and ``excludepats`` define explicit file patterns to
include and exclude in storage, respectively. If not defined, narrow
patterns from the repo instance are used, if available.
Gregory Szorc
exchange: support declaring pull depth...
r40367 ``depth`` is an integer indicating the DAG depth of history we're
interested in. If defined, for each revision specified in ``heads``, we
will fetch up to this many of its ancestors and data associated with them.
Gregory Szorc
exchange: add docstring to pull()...
r26440
Returns the ``pulloperation`` created for this pull.
"""
Pierre-Yves David
pull: allow a generic way to pass parameters to the pull operation...
r25445 if opargs is None:
opargs = {}
Gregory Szorc
exchange: support defining narrow file patterns for pull...
r39589
# We allow the narrow patterns to be passed in explicitly to provide more
# flexibility for API consumers.
if includepats or excludepats:
includepats = includepats or set()
excludepats = excludepats or set()
else:
includepats, excludepats = repo.narrowpats
narrowspec.validatepatterns(includepats)
narrowspec.validatepatterns(excludepats)
Augie Fackler
formatting: blacken the codebase...
r43346 pullop = pulloperation(
repo,
remote,
heads,
force,
bookmarks=bookmarks,
streamclonerequested=streamclonerequested,
includepats=includepats,
excludepats=excludepats,
depth=depth,
**pycompat.strkwargs(opargs)
)
Gregory Szorc
exchange: access requirements on repo instead of peer...
r33668
peerlocal = pullop.remote.local()
if peerlocal:
missing = set(peerlocal.requirements) - pullop.repo.supported
Pierre-Yves David
exchange: extract pull function from localrepo...
r20469 if missing:
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"required features are not"
b" supported in the destination:"
b" %s"
) % (b', '.join(sorted(missing)))
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg)
Pierre-Yves David
exchange: extract pull function from localrepo...
r20469
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.trmanager = transactionmanager(repo, b'pull', remote.url())
Martin von Zweigbergk
exchange: don't take wlock if bookmarks are stored in .hg/store/...
r42513 wlock = util.nullcontextmanager()
if not bookmod.bookmarksinstore(repo):
wlock = repo.wlock()
with wlock, repo.lock(), pullop.trmanager:
Gregory Szorc
exchangev2: start to implement pull with wire protocol v2...
r39665 # Use the modern wire protocol, if available.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if remote.capable(b'command-changesetdata'):
Gregory Szorc
exchangev2: start to implement pull with wire protocol v2...
r39665 exchangev2.pull(pullop)
else:
# This should ideally be in _pullbundle2(). However, it needs to run
# before discovery to avoid extra work.
_maybeapplyclonebundle(pullop)
streamclone.maybeperformlegacystreamclone(pullop)
_pulldiscovery(pullop)
if pullop.canusebundle2:
_fullpullbundle2(repo, pullop)
_pullchangeset(pullop)
_pullphase(pullop)
_pullbookmarks(pullop)
_pullobsolete(pullop)
Pierre-Yves David
exchange: extract pull function from localrepo...
r20469
Pulkit Goyal
remotenames: move function to pull remotenames from the remoterepo to core...
r35236 # storing remotenames
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo.ui.configbool(b'experimental', b'remotenames'):
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 logexchange.pullremotenames(repo, remote)
Pulkit Goyal
remotenames: move function to pull remotenames from the remoterepo to core...
r35236
Pierre-Yves David
exchange: have `pull` return the pulloperation object...
r22693 return pullop
Pierre-Yves David
pull: move obsolescence marker exchange in the exchange module...
r20476
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: make discovery phase extensible...
r22936 # list of steps to perform discovery before pull
pulldiscoveryorder = []
# Mapping between step name and function
#
# This exists to help extensions wrap steps if necessary
pulldiscoverymapping = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: make discovery phase extensible...
r22936 def pulldiscovery(stepname):
"""decorator for function performing discovery before pull
The function is added to the step -> function mapping and appended to the
list of steps. Beware that decorated function will be added in order (this
may matter).
You can only use this decorator for a new step, if you want to wrap a step
from an extension, change the pulldiscovery dictionary directly."""
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: make discovery phase extensible...
r22936 def dec(func):
assert stepname not in pulldiscoverymapping
pulldiscoverymapping[stepname] = func
pulldiscoveryorder.append(stepname)
return func
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: make discovery phase extensible...
r22936 return dec
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: put discovery step in its own function...
r20900 def _pulldiscovery(pullop):
Pierre-Yves David
pull: make discovery phase extensible...
r22936 """Run all discovery steps"""
for stepname in pulldiscoveryorder:
step = pulldiscoverymapping[stepname]
step(pullop)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pulldiscovery(b'b1:bookmarks')
Pierre-Yves David
pull: only prefetch bookmarks when using bundle1...
r25369 def _pullbookmarkbundle1(pullop):
"""fetch bookmark data in bundle1 case
If not using bundle2, we have to fetch bookmarks before changeset
discovery to reduce the chance and impact of race conditions."""
Pierre-Yves David
pull: skip pulling remote bookmarks with bundle1 if a value already exist...
r25443 if pullop.remotebookmarks is not None:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pullop.canusebundle2 and b'listkeys' in pullop.remotebundle2caps:
Pierre-Yves David
bundle2: pull bookmark the old way if no bundle2 listkeys support (issue4701)...
r25479 # all known bundle2 servers now support listkeys, but lets be nice with
# new implementation.
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 books = listkeys(pullop.remote, b'bookmarks')
Boris Feld
pull: store binary node in pullop.remotebookmarks...
r35030 pullop.remotebookmarks = bookmod.unhexlifybookmarks(books)
Pierre-Yves David
pull: only prefetch bookmarks when using bundle1...
r25369
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pulldiscovery(b'changegroup')
Pierre-Yves David
pull: make discovery phase extensible...
r22936 def _pulldiscoverychangegroup(pullop):
Pierre-Yves David
pull: put discovery step in its own function...
r20900 """discovery phase for the pull
Current handle changeset discovery only, will change handle all discovery
at some point."""
Augie Fackler
formatting: blacken the codebase...
r43346 tmp = discovery.findcommonincoming(
pullop.repo, pullop.remote, heads=pullop.heads, force=pullop.force
)
Pierre-Yves David
discovery: run discovery on filtered repository...
r23848 common, fetch, rheads = tmp
nm = pullop.repo.unfiltered().changelog.nodemap
if fetch and rheads:
Boris Feld
discovery: avoid dropping remote heads hidden locally...
r34318 # If a remote heads is filtered locally, put in back in common.
Pierre-Yves David
discovery: run discovery on filtered repository...
r23848 #
# This is a hackish solution to catch most of "common but locally
# hidden situation". We do not performs discovery on unfiltered
# repository because it end up doing a pathological amount of round
# trip for w huge amount of changeset we do not care about.
#
# If a set of such "common but filtered" changeset exist on the server
# but are not including a remote heads, we'll not be able to detect it,
scommon = set(common)
for n in rheads:
Pierre-Yves David
discovery: properly exclude locally known but filtered heads...
r23975 if n in nm:
if n not in scommon:
common.append(n)
Boris Feld
discovery: avoid dropping remote heads hidden locally...
r34318 if set(rheads).issubset(set(common)):
Pierre-Yves David
discovery: run discovery on filtered repository...
r23848 fetch = []
pullop.common = common
pullop.fetch = fetch
pullop.rheads = rheads
Pierre-Yves David
pull: put discovery step in its own function...
r20900
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: allow pulling changegroups using bundle2...
r20955 def _pullbundle2(pullop):
"""pull data using bundle2
For now, the only supported data are changegroup."""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs = {b'bundlecaps': caps20to10(pullop.repo, role=b'client')}
Gregory Szorc
exchange: add "streaming all changes" to bundle2 pulling...
r26471
Boris Feld
pull: reorganize bundle2 argument bundling...
r35779 # make ui easier to access
ui = pullop.repo.ui
Siddharth Agarwal
bundle2: don't check for whether we can do stream clones...
r32257 # At the moment we don't do stream clones over bundle2. If that is
# implemented then here's where the check for that will go.
Boris Feld
streamclone: add support for bundle2 based stream clone...
r35781 streaming = streamclone.canperformstreamclone(pullop, bundle2=True)[0]
Gregory Szorc
exchange: add "streaming all changes" to bundle2 pulling...
r26471
Boris Feld
pull: reorganize bundle2 argument bundling...
r35779 # declare pull perimeters
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'common'] = pullop.common
kwargs[b'heads'] = pullop.heads or pullop.rheads
Boris Feld
pull: reorganize bundle2 argument bundling...
r35779
Pulkit Goyal
exchange: pass includepats and excludepats as arguments to getbundle()...
r40527 # check server supports narrow and then adding includepats and excludepats
servernarrow = pullop.remote.capable(wireprototypes.NARROWCAP)
if servernarrow and pullop.includepats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'includepats'] = pullop.includepats
Pulkit Goyal
exchange: pass includepats and excludepats as arguments to getbundle()...
r40527 if servernarrow and pullop.excludepats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'excludepats'] = pullop.excludepats
Pulkit Goyal
exchange: pass includepats and excludepats as arguments to getbundle()...
r40527
Boris Feld
streamclone: add support for bundle2 based stream clone...
r35781 if streaming:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'cg'] = False
kwargs[b'stream'] = True
pullop.stepsdone.add(b'changegroup')
pullop.stepsdone.add(b'phases')
Boris Feld
streamclone: add support for bundle2 based stream clone...
r35781
else:
Boris Feld
pull: preindent some code...
r35780 # pulling changegroup
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'changegroup')
kwargs[b'cg'] = pullop.fetch
legacyphase = b'phases' in ui.configlist(b'devel', b'legacy.exchange')
hasbinaryphase = b'heads' in pullop.remotebundle2caps.get(b'phases', ())
Augie Fackler
formatting: blacken the codebase...
r43346 if not legacyphase and hasbinaryphase:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'phases'] = True
pullop.stepsdone.add(b'phases')
if b'listkeys' in pullop.remotebundle2caps:
if b'phases' not in pullop.stepsdone:
kwargs[b'listkeys'] = [b'phases']
Boris Feld
pull: reorganize bundle2 argument bundling...
r35779
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 bookmarksrequested = False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 legacybookmark = b'bookmarks' in ui.configlist(b'devel', b'legacy.exchange')
hasbinarybook = b'bookmarks' in pullop.remotebundle2caps
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269
if pullop.remotebookmarks is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'request-bookmarks')
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'request-bookmarks' not in pullop.stepsdone
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 and pullop.remotebookmarks is None
Augie Fackler
formatting: blacken the codebase...
r43346 and not legacybookmark
and hasbinarybook
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'bookmarks'] = True
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 bookmarksrequested = True
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'listkeys' in pullop.remotebundle2caps:
if b'request-bookmarks' not in pullop.stepsdone:
Pierre-Yves David
pull: skip pulling remote bookmarks with bundle2 if a value already exists...
r25444 # make sure to always includes bookmark data when migrating
# `hg incoming --bundle` to using this function.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'request-bookmarks')
kwargs.setdefault(b'listkeys', []).append(b'bookmarks')
Gregory Szorc
exchange: advertise if a clone bundle was attempted...
r26690
# If this is a full pull / clone and the server supports the clone bundles
# feature, tell the server whether we attempted a clone bundle. The
# presence of this flag indicates the client supports clone bundles. This
# will enable the server to treat clients that support clone bundles
# differently from those that don't.
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.remote.capable(b'clonebundles')
Augie Fackler
formatting: blacken the codebase...
r43346 and pullop.heads is None
and list(pullop.common) == [nullid]
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'cbattempted'] = pullop.clonebundleattempted
Gregory Szorc
exchange: advertise if a clone bundle was attempted...
r26690
Gregory Szorc
exchange: add "streaming all changes" to bundle2 pulling...
r26471 if streaming:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b'streaming all changes\n'))
Gregory Szorc
exchange: add "streaming all changes" to bundle2 pulling...
r26471 elif not pullop.fetch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b"no changes found\n"))
Pierre-Yves David
exchange: fix bad indentation...
r21258 pullop.cgresult = 0
Pierre-Yves David
bundle2: allow pulling changegroups using bundle2...
r20955 else:
if pullop.heads is None and list(pullop.common) == [nullid]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b"requesting all changes\n"))
Durham Goode
obsolete: add exchange option...
r22953 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
Gregory Szorc
exchange: expose bundle2 capabilities on pulloperation...
r26464 remoteversions = bundle2.obsmarkersversion(pullop.remotebundle2caps)
Pierre-Yves David
bundle2: pull obsmarkers relevant to the pulled set through bundle2...
r22354 if obsolete.commonversion(remoteversions) is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'obsmarkers'] = True
pullop.stepsdone.add(b'obsmarkers')
Pierre-Yves David
bundle2: allow extensions to extend the getbundle request...
r21159 _pullbundle2extraprepare(pullop, kwargs)
Gregory Szorc
exchange: use command executor for getbundle...
r37666
with pullop.remote.commandexecutor() as e:
args = dict(kwargs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args[b'source'] = b'pull'
bundle = e.callcommand(b'getbundle', args).result()
Gregory Szorc
exchange: use command executor for getbundle...
r37666
try:
Augie Fackler
formatting: blacken the codebase...
r43346 op = bundle2.bundleoperation(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo, pullop.gettransaction, source=b'pull'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 op.modes[b'bookmarks'] = b'records'
Gregory Szorc
exchange: use command executor for getbundle...
r37666 bundle2.processbundle(pullop.repo, bundle, op=op)
except bundle2.AbortFromPart as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b'remote: abort: %s\n') % exc)
raise error.Abort(_(b'pull failed on remote'), hint=exc.hint)
Gregory Szorc
exchange: use command executor for getbundle...
r37666 except error.BundleValueError as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'missing support for %s') % exc)
Durham Goode
bundle2: fix bundle2 pulling all revs on empty pulls...
r21259
if pullop.fetch:
Martin von Zweigbergk
bundle: make combinechangegroupresults() take a bundleoperation...
r33037 pullop.cgresult = bundle2.combinechangegroupresults(op)
Pierre-Yves David
bundle2: allow pulling changegroups using bundle2...
r20955
Pierre-Yves David
pull: when remote supports it, pull phase data alongside changesets...
r21658 # processing phases change
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for namespace, value in op.records[b'listkeys']:
if namespace == b'phases':
Pierre-Yves David
pull: when remote supports it, pull phase data alongside changesets...
r21658 _pullapplyphases(pullop, value)
Pierre-Yves David
pull: retrieve bookmarks through bundle2...
r22656 # processing bookmark update
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 if bookmarksrequested:
books = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for record in op.records[b'bookmarks']:
books[record[b'bookmark']] = record[b"node"]
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 pullop.remotebookmarks = books
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for namespace, value in op.records[b'listkeys']:
if namespace == b'bookmarks':
Boris Feld
pull: retrieve bookmarks through the binary part when possible...
r35269 pullop.remotebookmarks = bookmod.unhexlifybookmarks(value)
Pierre-Yves David
pull: skip pulling remote bookmarks with bundle2 if a value already exists...
r25444
# bookmark data were either already there or pulled in the bundle
if pullop.remotebookmarks is not None:
_pullbookmarks(pullop)
Pierre-Yves David
pull: retrieve bookmarks through bundle2...
r22656
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: allow extensions to extend the getbundle request...
r21159 def _pullbundle2extraprepare(pullop, kwargs):
"""hook function so that extensions can extend the getbundle call"""
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 def _pullchangeset(pullop):
"""pull changeset from unbundle into the local repo"""
# We delay the open of the transaction as late as possible so we
# don't open transaction for nothing or you break future useful
# rollback call
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'changegroup' in pullop.stepsdone:
Pierre-Yves David
pull: perform the todostep inside functions handling old way of pulling...
r22653 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'changegroup')
Pierre-Yves David
pull: move the cgresult logic in _pullchangeset...
r20899 if not pullop.fetch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b"no changes found\n"))
Mike Edgar
exchange: fix indentation in _pullchangeset
r23217 pullop.cgresult = 0
return
Martin von Zweigbergk
changegroup: let callers pass in transaction to apply() (API)...
r32930 tr = pullop.gettransaction()
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 if pullop.heads is None and list(pullop.common) == [nullid]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.status(_(b"requesting all changes\n"))
elif pullop.heads is None and pullop.remote.capable(b'changegroupsubset'):
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 # issue1320, avoid a race if remote changed after discovery
pullop.heads = pullop.rheads
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pullop.remote.capable(b'getbundle'):
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 # TODO: get bundlecaps from remote
Augie Fackler
formatting: blacken the codebase...
r43346 cg = pullop.remote.getbundle(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pull', common=pullop.common, heads=pullop.heads or pullop.rheads
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 elif pullop.heads is None:
Gregory Szorc
wireproto: convert legacy commands to command executor...
r37653 with pullop.remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 cg = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'changegroup', {b'nodes': pullop.fetch, b'source': b'pull',}
Augie Fackler
formatting: blacken the codebase...
r43346 ).result()
Gregory Szorc
wireproto: convert legacy commands to command executor...
r37653
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif not pullop.remote.capable(b'changegroupsubset'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"partial pull cannot be done because "
b"other repository doesn't support "
b"changegroupsubset."
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489 else:
Gregory Szorc
wireproto: convert legacy commands to command executor...
r37653 with pullop.remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 cg = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'changegroupsubset',
Augie Fackler
formatting: blacken the codebase...
r43346 {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bases': pullop.fetch,
b'heads': pullop.heads,
b'source': b'pull',
Augie Fackler
formatting: blacken the codebase...
r43346 },
).result()
bundleop = bundle2.applybundle(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo, cg, tr, b'pull', pullop.remote.url()
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
bundle: make applybundle1() return a bundleoperation...
r33040 pullop.cgresult = bundle2.combinechangegroupresults(bundleop)
Pierre-Yves David
pull: move changeset pulling in its own function...
r20489
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: move phases synchronisation in its own function...
r20486 def _pullphase(pullop):
# Get remote phases data from remote
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'phases' in pullop.stepsdone:
Pierre-Yves David
pull: perform the todostep inside functions handling old way of pulling...
r22653 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotephases = listkeys(pullop.remote, b'phases')
Pierre-Yves David
pull: split remote phases retrieval from actual application...
r21654 _pullapplyphases(pullop, remotephases)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: split remote phases retrieval from actual application...
r21654 def _pullapplyphases(pullop, remotephases):
"""apply phase movement from observed remote state"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'phases' in pullop.stepsdone:
Pierre-Yves David
pull: use `stepsdone` instead of `todosteps`...
r22937 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'phases')
publishing = bool(remotephases.get(b'publishing', False))
Pierre-Yves David
pull: move phases synchronisation in its own function...
r20486 if remotephases and not publishing:
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 # remote is new and non-publishing
Augie Fackler
formatting: blacken the codebase...
r43346 pheads, _dr = phases.analyzeremotephases(
pullop.repo, pullop.pulledsubset, remotephases
)
Pierre-Yves David
pull: pre-filter remote phases before moving local ones...
r22068 dheads = pullop.pulledsubset
Pierre-Yves David
pull: move phases synchronisation in its own function...
r20486 else:
# Remote is old or publishing all common changesets
# should be seen as public
Pierre-Yves David
pull: pre-filter remote phases before moving local ones...
r22068 pheads = pullop.pulledsubset
dheads = []
unfi = pullop.repo.unfiltered()
phase = unfi._phasecache.phase
rev = unfi.changelog.nodemap.get
public = phases.public
draft = phases.draft
# exclude changesets already public locally and update the others
pheads = [pn for pn in pheads if phase(unfi, rev(pn)) > public]
if pheads:
Pierre-Yves David
phase: add a transaction argument to advanceboundary...
r22069 tr = pullop.gettransaction()
phases.advanceboundary(pullop.repo, tr, public, pheads)
Pierre-Yves David
pull: pre-filter remote phases before moving local ones...
r22068
# exclude changesets already draft locally and update the others
dheads = [pn for pn in dheads if phase(unfi, rev(pn)) > draft]
if dheads:
Pierre-Yves David
phase: add a transaction argument to advanceboundary...
r22069 tr = pullop.gettransaction()
phases.advanceboundary(pullop.repo, tr, draft, dheads)
Pierre-Yves David
pull: move phases synchronisation in its own function...
r20486
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654 def _pullbookmarks(pullop):
"""process the remote bookmark information to update the local one"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'bookmarks' in pullop.stepsdone:
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'bookmarks')
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654 repo = pullop.repo
remotebookmarks = pullop.remotebookmarks
Augie Fackler
formatting: blacken the codebase...
r43346 bookmod.updatefromremote(
repo.ui,
repo,
remotebookmarks,
pullop.remote.url(),
pullop.gettransaction,
explicit=pullop.explicitbookmarks,
)
Pierre-Yves David
pull: move bookmark pulling into its own function...
r22654
Pierre-Yves David
push: feed pulloperation object to _pullobsolete function...
r20478 def _pullobsolete(pullop):
Pierre-Yves David
pull: move obsolescence marker exchange in the exchange module...
r20476 """utility function to pull obsolete markers from a remote
The `gettransaction` is function that return the pull transaction, creating
one if necessary. We return the transaction to inform the calling code that
a new transaction have been created (when applicable).
Exists mostly to allow overriding for experimentation purpose"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'obsmarkers' in pullop.stepsdone:
Pierre-Yves David
pull: perform the todostep inside functions handling old way of pulling...
r22653 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.stepsdone.add(b'obsmarkers')
Pierre-Yves David
pull: move obsolescence marker exchange in the exchange module...
r20476 tr = None
Durham Goode
obsolete: add exchange option...
r22953 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pullop.repo.ui.debug(b'fetching remote obsolete markers\n')
remoteobs = listkeys(pullop.remote, b'obsolete')
if b'dump0' in remoteobs:
Pierre-Yves David
push: feed pulloperation object to _pullobsolete function...
r20478 tr = pullop.gettransaction()
Matt Mackall
pull: make a single call to obsstore.add (issue5006)...
r27558 markers = []
Pierre-Yves David
pull: move obsolescence marker exchange in the exchange module...
r20476 for key in sorted(remoteobs, reverse=True):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if key.startswith(b'dump'):
Yuya Nishihara
base85: proxy through util module...
r32200 data = util.b85decode(remoteobs[key])
Matt Mackall
pull: make a single call to obsstore.add (issue5006)...
r27558 version, newmarks = obsolete._readmarkers(data)
markers += newmarks
if markers:
pullop.repo.obsstore.add(tr, markers)
Pierre-Yves David
push: feed pulloperation object to _pullobsolete function...
r20478 pullop.repo.invalidatevolatilesets()
Pierre-Yves David
pull: move obsolescence marker exchange in the exchange module...
r20476 return tr
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 def applynarrowacl(repo, kwargs):
"""Apply narrow fetch access control.
This massages the named arguments for getbundle wire protocol commands
so requested data is filtered through access control rules.
"""
ui = repo.ui
# TODO this assumes existence of HTTP and is a layering violation.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 username = ui.shortuser(ui.environ.get(b'REMOTE_USER') or ui.username())
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 user_includes = ui.configlist(
Augie Fackler
formatting: blacken the codebase...
r43346 _NARROWACL_SECTION,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 username + b'.includes',
ui.configlist(_NARROWACL_SECTION, b'default.includes'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 user_excludes = ui.configlist(
Augie Fackler
formatting: blacken the codebase...
r43346 _NARROWACL_SECTION,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 username + b'.excludes',
ui.configlist(_NARROWACL_SECTION, b'default.excludes'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 if not user_includes:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"{} configuration for user {} is empty").format(
Augie Fackler
formatting: blacken the codebase...
r43346 _NARROWACL_SECTION, username
)
)
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826
user_includes = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'path:.' if p == b'*' else b'path:' + p for p in user_includes
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 user_excludes = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'path:.' if p == b'*' else b'path:' + p for p in user_excludes
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826
req_includes = set(kwargs.get(r'includepats', []))
req_excludes = set(kwargs.get(r'excludepats', []))
req_includes, req_excludes, invalid_includes = narrowspec.restrictpatterns(
Augie Fackler
formatting: blacken the codebase...
r43346 req_includes, req_excludes, user_includes, user_excludes
)
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826
if invalid_includes:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"The following includes are not accessible for {}: {}").format(
Augie Fackler
formatting: blacken the codebase...
r43346 username, invalid_includes
)
)
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826
new_args = {}
new_args.update(kwargs)
Gregory Szorc
exchange: make narrow ACL presence imply narrow=True...
r38843 new_args[r'narrow'] = True
Pulkit Goyal
narrow: only send the narrowspecs back if ACL in play...
r40373 new_args[r'narrow_acl'] = True
Gregory Szorc
exchange: make narrow ACL presence imply narrow=True...
r38843 new_args[r'includepats'] = req_includes
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 if req_excludes:
Gregory Szorc
exchange: make narrow ACL presence imply narrow=True...
r38843 new_args[r'excludepats'] = req_excludes
Gregory Szorc
exchange: move narrow acl functionality into core...
r38826 return new_args
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 def _computeellipsis(repo, common, heads, known, match, depth=None):
"""Compute the shape of a narrowed DAG.
Args:
repo: The repository we're transferring.
common: The roots of the DAG range we're transferring.
May be just [nullid], which means all ancestors of heads.
heads: The heads of the DAG range we're transferring.
match: The narrowmatcher that allows us to identify relevant changes.
depth: If not None, only consider nodes to be full nodes if they are at
most depth changesets away from one of heads.
Returns:
A tuple of (visitnodes, relevant_nodes, ellipsisroots) where:
visitnodes: The list of nodes (either full or ellipsis) which
need to be sent to the client.
relevant_nodes: The set of changelog nodes which change a file inside
the narrowspec. The client needs these as non-ellipsis nodes.
ellipsisroots: A dict of {rev: parents} that is used in
narrowchangegroup to produce ellipsis nodes with the
correct parents.
"""
cl = repo.changelog
mfl = repo.manifestlog
Gregory Szorc
exchange: don't use dagutil...
r39194 clrev = cl.rev
commonrevs = {clrev(n) for n in common} | {nullrev}
headsrevs = {clrev(n) for n in heads}
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 if depth:
revdepth = {h: 0 for h in headsrevs}
ellipsisheads = collections.defaultdict(set)
ellipsisroots = collections.defaultdict(set)
def addroot(head, curchange):
"""Add a root to an ellipsis head, splitting heads with 3 roots."""
ellipsisroots[head].add(curchange)
# Recursively split ellipsis heads with 3 roots by finding the
# roots' youngest common descendant which is an elided merge commit.
# That descendant takes 2 of the 3 roots as its own, and becomes a
# root of the head.
while len(ellipsisroots[head]) > 2:
child, roots = splithead(head)
splitroots(head, child, roots)
head = child # Recurse in case we just added a 3rd root
def splitroots(head, child, roots):
ellipsisroots[head].difference_update(roots)
ellipsisroots[head].add(child)
ellipsisroots[child].update(roots)
ellipsisroots[child].discard(child)
def splithead(head):
r1, r2, r3 = sorted(ellipsisroots[head])
for nr1, nr2 in ((r2, r3), (r1, r3), (r1, r2)):
Augie Fackler
formatting: blacken the codebase...
r43346 mid = repo.revs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'sort(merge() & %d::%d & %d::%d, -rev)', nr1, head, nr2, head
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 for j in mid:
if j == nr2:
return nr2, (nr1, nr2)
if j not in ellipsisroots or len(ellipsisroots[j]) < 2:
return j, (nr1, nr2)
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(
b'Failed to split up ellipsis node! head: %d, '
b'roots: %d %d %d'
)
Augie Fackler
formatting: blacken the codebase...
r43346 % (head, r1, r2, r3)
)
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827
missing = list(cl.findmissingrevs(common=commonrevs, heads=headsrevs))
visit = reversed(missing)
relevant_nodes = set()
visitnodes = [cl.node(m) for m in missing]
required = set(headsrevs) | known
for rev in visit:
clrev = cl.changelogrevision(rev)
Gregory Szorc
exchange: don't use dagutil...
r39194 ps = [prev for prev in cl.parentrevs(rev) if prev != nullrev]
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 if depth is not None:
curdepth = revdepth[rev]
for p in ps:
revdepth[p] = min(curdepth + 1, revdepth.get(p, depth + 1))
needed = False
shallow_enough = depth is None or revdepth[rev] <= depth
if shallow_enough:
curmf = mfl[clrev.manifest].read()
if ps:
# We choose to not trust the changed files list in
# changesets because it's not always correct. TODO: could
# we trust it for the non-merge case?
p1mf = mfl[cl.changelogrevision(ps[0]).manifest].read()
needed = bool(curmf.diff(p1mf, match))
if not needed and len(ps) > 1:
# For merge changes, the list of changed files is not
# helpful, since we need to emit the merge if a file
# in the narrow spec has changed on either side of the
# merge. As a result, we do a manifest diff to check.
p2mf = mfl[cl.changelogrevision(ps[1]).manifest].read()
needed = bool(curmf.diff(p2mf, match))
else:
# For a root node, we need to include the node if any
# files in the node match the narrowspec.
needed = any(curmf.walk(match))
if needed:
for head in ellipsisheads[rev]:
addroot(head, rev)
for p in ps:
required.add(p)
relevant_nodes.add(cl.node(rev))
else:
if not ps:
ps = [nullrev]
if rev in required:
for head in ellipsisheads[rev]:
addroot(head, rev)
for p in ps:
ellipsisheads[p].add(rev)
else:
for p in ps:
ellipsisheads[p] |= ellipsisheads[rev]
# add common changesets as roots of their reachable ellipsis heads
for c in commonrevs:
for head in ellipsisheads[c]:
addroot(head, c)
return visitnodes, relevant_nodes, ellipsisroots
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
bundle2: specify what capabilities will be used for...
r35801 def caps20to10(repo, role):
Pierre-Yves David
bundle2: introduce a ``caps20to10`` function...
r21645 """return a set with appropriate options to use bundle20 during getbundle"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 caps = {b'HG20'}
Gregory Szorc
bundle2: specify what capabilities will be used for...
r35801 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role=role))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 caps.add(b'bundle2=' + urlreq.quote(capsblob))
Pierre-Yves David
bundle2: introduce a ``caps20to10`` function...
r21645 return caps
Augie Fackler
formatting: blacken the codebase...
r43346
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 # List of names of steps to perform for a bundle2 for getbundle, order matters.
getbundle2partsorder = []
# Mapping between step name and function
#
# This exists to help extensions wrap steps if necessary
getbundle2partsmapping = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: add an 'idx' argument to the 'getbundle2partsgenerator'...
r24732 def getbundle2partsgenerator(stepname, idx=None):
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 """decorator for function generating bundle2 part for getbundle
The function is added to the step -> function mapping and appended to the
list of steps. Beware that decorated functions will be added in order
(this may matter).
You can only use this decorator for new steps, if you want to wrap a step
from an extension, attack the getbundle2partsmapping dictionary directly."""
Augie Fackler
formatting: blacken the codebase...
r43346
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 def dec(func):
assert stepname not in getbundle2partsmapping
getbundle2partsmapping[stepname] = func
Pierre-Yves David
bundle2: add an 'idx' argument to the 'getbundle2partsgenerator'...
r24732 if idx is None:
getbundle2partsorder.append(stepname)
else:
getbundle2partsorder.insert(idx, stepname)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 return func
Augie Fackler
formatting: blacken the codebase...
r43346
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 return dec
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: standalone function to determine if bundle2 is requested...
r27244 def bundle2requested(bundlecaps):
if bundlecaps is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return any(cap.startswith(b'HG2') for cap in bundlecaps)
Gregory Szorc
exchange: standalone function to determine if bundle2 is requested...
r27244 return False
Augie Fackler
formatting: blacken the codebase...
r43346
def getbundlechunks(
repo, source, heads=None, common=None, bundlecaps=None, **kwargs
):
Gregory Szorc
exchange: refactor APIs to obtain bundle data (API)...
r30187 """Return chunks constituting a bundle's raw data.
Pierre-Yves David
bundle2: add an exchange.getbundle function...
r20954
Pierre-Yves David
bundle2: rename format, parts and config to final names...
r24686 Could be a bundle HG10 or a bundle HG20 depending on bundlecaps
Gregory Szorc
exchange: refactor APIs to obtain bundle data (API)...
r30187 passed.
Pierre-Yves David
bundle2: add an exchange.getbundle function...
r20954
Gregory Szorc
exchange: return bundle info from getbundlechunks() (API)...
r35803 Returns a 2-tuple of a dict with metadata about the generated bundle
and an iterator over raw chunks (of varying sizes).
Pierre-Yves David
bundle2: add an exchange.getbundle function...
r20954 """
Pulkit Goyal
py3: convert kwargs keys' back to bytes using pycompat.byteskwargs()
r33016 kwargs = pycompat.byteskwargs(kwargs)
Gregory Szorc
exchange: return bundle info from getbundlechunks() (API)...
r35803 info = {}
Gregory Szorc
exchange: standalone function to determine if bundle2 is requested...
r27244 usebundle2 = bundle2requested(bundlecaps)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 # bundle10 case
Pierre-Yves David
bundle2: detect bundle2 stream/request on /HG2./ instead of /HG2Y/...
r24649 if not usebundle2:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if bundlecaps and not kwargs.get(b'cg', True):
raise ValueError(
_(b'request for bundle10 must include changegroup')
)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
Pierre-Yves David
getbundle: raise error if extra arguments are provided for bundle10...
r21656 if kwargs:
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'unsupported getbundle arguments: %s')
% b', '.join(sorted(kwargs.keys()))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
computeoutgoing: move the function from 'changegroup' to 'exchange'...
r29808 outgoing = _computeoutgoing(repo, heads, common)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info[b'bundleversion'] = 1
Augie Fackler
formatting: blacken the codebase...
r43346 return (
info,
changegroup.makestream(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo, outgoing, b'01', source, bundlecaps=bundlecaps
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
# bundle20 case
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info[b'bundleversion'] = 2
Pierre-Yves David
bundle2: transmit capabilities to getbundle during pull...
r21143 b2caps = {}
for bcaps in bundlecaps:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if bcaps.startswith(b'bundle2='):
blob = urlreq.unquote(bcaps[len(b'bundle2=') :])
Pierre-Yves David
bundle2: transmit capabilities to getbundle during pull...
r21143 b2caps.update(bundle2.decodecaps(blob))
bundler = bundle2.bundle20(repo.ui, b2caps)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kwargs[b'heads'] = heads
kwargs[b'common'] = common
Mike Edgar
exchange: prepare kwargs for bundle2 part generation exactly once
r23218
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 for name in getbundle2partsorder:
func = getbundle2partsmapping[name]
Augie Fackler
formatting: blacken the codebase...
r43346 func(
bundler,
repo,
source,
bundlecaps=bundlecaps,
b2caps=b2caps,
**pycompat.strkwargs(kwargs)
)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info[b'prefercompressed'] = bundler.prefercompressed
Gregory Szorc
exchange: send bundle2 stream clones uncompressed...
r35805
Gregory Szorc
exchange: return bundle info from getbundlechunks() (API)...
r35803 return info, bundler.getchunks()
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'stream2')
Boris Feld
bundle: add the possibility to bundle a stream v2 part...
r37184 def _getbundlestream2(bundler, repo, *args, **kwargs):
return bundle2.addpartbundlestream2(bundler, repo, **kwargs)
Boris Feld
bundle2: add support for a 'stream' parameter to 'getbundle'...
r35777
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'changegroup')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundlechangegrouppart(
bundler,
repo,
source,
bundlecaps=None,
b2caps=None,
heads=None,
common=None,
**kwargs
):
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 """add a changegroup part to the requested bundle"""
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 if not kwargs.get(r'cg', True):
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 version = b'01'
cgversions = b2caps.get(b'changegroup')
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 if cgversions: # 3.1 and 3.2 ship with an empty value
Augie Fackler
formatting: blacken the codebase...
r43346 cgversions = [
v
for v in cgversions
if v in changegroup.supportedoutgoingversions(repo)
]
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 if not cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no common changegroup version'))
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 version = max(cgversions)
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 outgoing = _computeoutgoing(repo, heads, common)
if not outgoing.missing:
return
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844 if kwargs.get(r'narrow', False):
include = sorted(filter(bool, kwargs.get(r'includepats', [])))
exclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
Martin von Zweigbergk
narrow: when widening, don't include manifests the client already has...
r40380 matcher = narrowspec.match(repo.root, include=include, exclude=exclude)
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844 else:
Martin von Zweigbergk
narrow: when widening, don't include manifests the client already has...
r40380 matcher = None
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844
Augie Fackler
formatting: blacken the codebase...
r43346 cgstream = changegroup.makestream(
repo, outgoing, version, source, bundlecaps=bundlecaps, matcher=matcher
)
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'changegroup', data=cgstream)
Gregory Szorc
exchange: refactor control flow of _getbundlechangegrouppart()...
r38828 if cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part.addparam(b'version', version)
part.addparam(b'nbchanges', b'%d' % len(outgoing.missing), mandatory=False)
if b'treemanifest' in repo.requirements:
part.addparam(b'treemanifest', b'1')
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542
sidedata: apply basic but tight security around exchange...
r43401 if b'exp-sidedata-flag' in repo.requirements:
part.addparam(b'exp-sidedata', b'1')
Augie Fackler
formatting: blacken the codebase...
r43346 if (
kwargs.get(r'narrow', False)
and kwargs.get(r'narrow_acl', False)
and (include or exclude)
):
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 # this is mandatory because otherwise ACL clients won't work
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 narrowspecpart = bundler.newpart(b'Narrow:responsespec')
narrowspecpart.data = b'%s\0%s' % (
b'\n'.join(include),
b'\n'.join(exclude),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'bookmarks')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundlebookmarkpart(
bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
):
Boris Feld
getbundle: add support for 'bookmarks' boolean argument...
r35268 """add a bookmark part to the requested bundle"""
Pulkit Goyal
py3: handle keyword arguments correctly in exchange.py...
r35356 if not kwargs.get(r'bookmarks', False):
Boris Feld
getbundle: add support for 'bookmarks' boolean argument...
r35268 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'bookmarks' not in b2caps:
raise error.Abort(_(b'no common bookmarks exchange method'))
Augie Fackler
formatting: blacken the codebase...
r43346 books = bookmod.listbinbookmarks(repo)
Boris Feld
getbundle: add support for 'bookmarks' boolean argument...
r35268 data = bookmod.binaryencode(books)
if data:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'bookmarks', data=data)
@getbundle2partsgenerator(b'listkeys')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundlelistkeysparts(
bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
):
Mike Hommey
bundle2: separate bundle10 and bundle2 cases in getbundle()...
r22542 """add parts containing listkeys namespaces to the requested bundle"""
Pulkit Goyal
py3: handle keyword arguments correctly in exchange.py...
r35356 listkeys = kwargs.get(r'listkeys', ())
Pierre-Yves David
getbundle: support of listkeys argument when bundle2 is used...
r21657 for namespace in listkeys:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'listkeys')
part.addparam(b'namespace', namespace)
Pierre-Yves David
getbundle: support of listkeys argument when bundle2 is used...
r21657 keys = repo.listkeys(namespace).items()
part.data = pushkey.encodekeys(keys)
Pierre-Yves David
unbundle: extract checkheads in its own function...
r20967
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'obsmarkers')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundleobsmarkerpart(
bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs
):
Mike Hommey
bundle2: pass b2caps down to functions adding bundle2 parts for getbundle
r22541 """add an obsolescence markers part to the requested bundle"""
Pulkit Goyal
py3: handle keyword arguments correctly in exchange.py...
r35356 if kwargs.get(r'obsmarkers', False):
Pierre-Yves David
getbundle: add `obsmarkers` argument to getbundle...
r22353 if heads is None:
heads = repo.heads()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 subset = [c.node() for c in repo.set(b'::%ln', heads)]
Pierre-Yves David
getbundle: add `obsmarkers` argument to getbundle...
r22353 markers = repo.obsstore.relevantmarkers(subset)
Denis Laxalde
py3: fix sorting of obsolete markers in obsutil (issue6217)...
r43858 markers = obsutil.sortedmarkers(markers)
bundle2: move function building obsmarker-part in the bundle2 module...
r32515 bundle2.buildobsmarkerspart(bundler, markers)
Pierre-Yves David
getbundle: add `obsmarkers` argument to getbundle...
r22353
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'phases')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundlephasespart(
bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs
):
Boris Feld
pull: use 'phase-heads' to retrieve phase information...
r34323 """add phase heads part to the requested bundle"""
Pulkit Goyal
py3: handle keyword arguments correctly in exchange.py...
r35356 if kwargs.get(r'phases', False):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not b'heads' in b2caps.get(b'phases'):
raise error.Abort(_(b'no common phases exchange method'))
Boris Feld
pull: use 'phase-heads' to retrieve phase information...
r34323 if heads is None:
heads = repo.heads()
headsbyphase = collections.defaultdict(set)
if repo.publishing():
headsbyphase[phases.public] = heads
else:
# find the appropriate heads to move
phase = repo._phasecache.phase
node = repo.changelog.node
rev = repo.changelog.rev
for h in heads:
headsbyphase[phase(repo, rev(h))].add(h)
seenphases = list(headsbyphase.keys())
# We do not handle anything but public and draft phase for now)
if seenphases:
assert max(seenphases) <= phases.draft
# if client is pulling non-public changesets, we need to find
# intermediate public heads.
draftheads = headsbyphase.get(phases.draft, set())
if draftheads:
publicheads = headsbyphase.get(phases.public, set())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revset = b'heads(only(%ln, %ln) and public())'
Boris Feld
pull: use 'phase-heads' to retrieve phase information...
r34323 extraheads = repo.revs(revset, draftheads, publicheads)
for r in extraheads:
headsbyphase[phases.public].add(node(r))
# transform data in a format used by the encoding function
phasemapping = []
for phase in phases.allphases:
phasemapping.append(sorted(headsbyphase[phase]))
# generate the actual part
phasedata = phases.binaryencode(phasemapping)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundler.newpart(b'phase-heads', data=phasedata)
@getbundle2partsgenerator(b'hgtagsfnodes')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundletagsfnodes(
bundler,
repo,
source,
bundlecaps=None,
b2caps=None,
heads=None,
common=None,
**kwargs
):
Gregory Szorc
exchange: support transferring .hgtags fnodes mapping...
r25402 """Transfer the .hgtags filenodes mapping.
Only values for heads in this bundle will be transferred.
The part data consists of pairs of 20 byte changeset node and .hgtags
filenodes raw values.
"""
# Don't send unless:
# - changeset are being exchanged,
# - the client supports it.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not (kwargs.get(r'cg', True) and b'hgtagsfnodes' in b2caps):
Gregory Szorc
exchange: support transferring .hgtags fnodes mapping...
r25402 return
Pierre-Yves David
computeoutgoing: move the function from 'changegroup' to 'exchange'...
r29808 outgoing = _computeoutgoing(repo, heads, common)
bundle2: move tagsfnodecache generation in a generic function...
r32217 bundle2.addparttagsfnodescache(repo, bundler, outgoing)
Gregory Szorc
exchange: support transferring .hgtags fnodes mapping...
r25402
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @getbundle2partsgenerator(b'cache:rev-branch-cache')
Augie Fackler
formatting: blacken the codebase...
r43346 def _getbundlerevbranchcache(
bundler,
repo,
source,
bundlecaps=None,
b2caps=None,
heads=None,
common=None,
**kwargs
):
Boris Feld
revbranchcache: add the necessary bit to send 'rbc' data over bundle2...
r36984 """Transfer the rev-branch-cache mapping
The payload is a series of data related to each branch
1) branch name length
2) number of open heads
3) number of closed heads
4) open heads nodes
5) closed heads nodes
"""
# Don't send unless:
# - changeset are being exchanged,
# - the client supports it.
Gregory Szorc
exchange: move disabling of rev-branch-cache bundle part out of narrow...
r38825 # - narrow bundle isn't in play (not currently compatible).
Augie Fackler
formatting: blacken the codebase...
r43346 if (
not kwargs.get(r'cg', True)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or b'rev-branch-cache' not in b2caps
Gregory Szorc
exchange: move disabling of rev-branch-cache bundle part out of narrow...
r38825 or kwargs.get(r'narrow', False)
Augie Fackler
formatting: blacken the codebase...
r43346 or repo.ui.has_section(_NARROWACL_SECTION)
):
Boris Feld
revbranchcache: add the necessary bit to send 'rbc' data over bundle2...
r36984 return
Gregory Szorc
exchange: move disabling of rev-branch-cache bundle part out of narrow...
r38825
Boris Feld
revbranchcache: add the necessary bit to send 'rbc' data over bundle2...
r36984 outgoing = _computeoutgoing(repo, heads, common)
bundle2.addpartrevbranchcache(repo, bundler, outgoing)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
unbundle: extract checkheads in its own function...
r20967 def check_heads(repo, their_heads, context):
"""check if the heads of a repo have been modified
Used by peer for unbundling.
"""
heads = repo.heads()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 heads_hash = hashlib.sha1(b''.join(sorted(heads))).digest()
Augie Fackler
formatting: blacken the codebase...
r43346 if not (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 their_heads == [b'force']
Augie Fackler
formatting: blacken the codebase...
r43346 or their_heads == heads
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or their_heads == [b'hashed', heads_hash]
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
unbundle: extract checkheads in its own function...
r20967 # someone else committed/pushed/unbundled while we
# were transferring data
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.PushRaced(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'repository changed while %s - please try again' % context
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968
def unbundle(repo, cg, heads, source, url):
"""Apply a bundle to a repo.
this function makes sure the repo is locked during the application and have
Mads Kiilerich
spelling: fixes from spell checker
r21024 mechanism to check that no push race occurred between the creation of the
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968 bundle and its application.
If the push was raced as PushRaced exception is raised."""
r = 0
Pierre-Yves David
bundle2: allow using bundle2 for push...
r21061 # need a transaction when processing a bundle2 stream
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 # [wlock, lock, tr] - needs to be an array so nested functions can modify it
lockandtr = [None, None, None]
Pierre-Yves David
bundle2: capture transaction rollback message output (issue4614)...
r24847 recordout = None
Pierre-Yves David
bundle2: disable ouput capture unless we use http (issue4613 issue4615)...
r24878 # quick fix for output mismatch with bundle2 in 3.4
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 captureoutput = repo.ui.configbool(
b'experimental', b'bundle2-output-capture'
)
if url.startswith(b'remote:http:') or url.startswith(b'remote:https:'):
Pierre-Yves David
bundle2: disable ouput capture unless we use http (issue4613 issue4615)...
r24878 captureoutput = True
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968 try:
Pierre-Yves David
unbundle: add a small comment to clarify the 'check_heads' call...
r30868 # note: outside bundle1, 'heads' is expected to be empty and this
# 'check_heads' call wil be a no-op
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 check_heads(repo, heads, b'uploading changes')
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968 # push can proceed
Martin von Zweigbergk
exchange: switch to usual way of testing for bundle2-ness...
r32891 if not isinstance(cg, bundle2.unbundle20):
Pierre-Yves David
unbundle: swap conditional branches for clarity...
r30870 # legacy case: bundle1 (changegroup 01)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 txnname = b"\n".join([source, util.hidepassword(url)])
Martin von Zweigbergk
changegroup: let callers pass in transaction to apply() (API)...
r32930 with repo.lock(), repo.transaction(txnname) as tr:
Martin von Zweigbergk
bundle: make applybundle() delegate v1 bundles to applybundle1()
r33043 op = bundle2.applybundle(repo, cg, tr, source, url)
Martin von Zweigbergk
bundle: make applybundle1() return a bundleoperation...
r33040 r = bundle2.combinechangegroupresults(op)
Pierre-Yves David
unbundle: swap conditional branches for clarity...
r30870 else:
Pierre-Yves David
bundle2: store the salvaged output on the exception object...
r24795 r = None
Pierre-Yves David
bundle2: gracefully handle hook abort...
r21187 try:
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 def gettransaction():
if not lockandtr[2]:
Martin von Zweigbergk
exchange: don't take wlock if bookmarks are stored in .hg/store/...
r42513 if not bookmod.bookmarksinstore(repo):
lockandtr[0] = repo.wlock()
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 lockandtr[1] = repo.lock()
lockandtr[2] = repo.transaction(source)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lockandtr[2].hookargs[b'source'] = source
lockandtr[2].hookargs[b'url'] = url
lockandtr[2].hookargs[b'bundle2'] = b'1'
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 return lockandtr[2]
# Do greedy locking by default until we're satisfied with lazy
# locking.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.ui.configbool(
b'experimental', b'bundle2lazylocking'
):
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 gettransaction()
Augie Fackler
formatting: blacken the codebase...
r43346 op = bundle2.bundleoperation(
repo,
gettransaction,
captureoutput=captureoutput,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 source=b'push',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
bundle2: also save output when error happens during part processing...
r24851 try:
Martin von Zweigbergk
exchange: fix dead assignment...
r25896 op = bundle2.processbundle(repo, cg, op=op)
Pierre-Yves David
bundle2: also save output when error happens during part processing...
r24851 finally:
r = op.reply
Pierre-Yves David
bundle2: disable ouput capture unless we use http (issue4613 issue4615)...
r24878 if captureoutput and r is not None:
Pierre-Yves David
bundle2: also save output when error happens during part processing...
r24851 repo.ui.pushbuffer(error=True, subproc=True)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: also save output when error happens during part processing...
r24851 def recordout(output):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 r.newpart(b'output', data=output, mandatory=False)
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 if lockandtr[2] is not None:
lockandtr[2].close()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except BaseException as exc:
Pierre-Yves David
bundle2: gracefully handle hook abort...
r21187 exc.duringunbundle2 = True
Pierre-Yves David
bundle2: disable ouput capture unless we use http (issue4613 issue4615)...
r24878 if captureoutput and r is not None:
Pierre-Yves David
bundle2: capture transaction rollback message output (issue4614)...
r24847 parts = exc._bundle2salvagedoutput = r.salvageoutput()
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: capture transaction rollback message output (issue4614)...
r24847 def recordout(output):
Augie Fackler
formatting: blacken the codebase...
r43346 part = bundle2.bundlepart(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'output', data=output, mandatory=False
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
bundle2: capture transaction rollback message output (issue4614)...
r24847 parts.append(part)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
bundle2: gracefully handle hook abort...
r21187 raise
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968 finally:
Durham Goode
bundle2: allow lazily acquiring the lock...
r26566 lockmod.release(lockandtr[2], lockandtr[1], lockandtr[0])
Pierre-Yves David
bundle2: capture transaction rollback message output (issue4614)...
r24847 if recordout is not None:
recordout(repo.ui.popbuffer())
Pierre-Yves David
unbundle: extract the core logic in another function...
r20968 return r
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 def _maybeapplyclonebundle(pullop):
"""Apply a clone bundle from a remote, if possible."""
repo = pullop.repo
remote = pullop.remote
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.ui.configbool(b'ui', b'clonebundles'):
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 return
Gregory Szorc
exchange: do not attempt clone bundle if local repo is non-empty (issue4932)
r26855 # Only run if local repo is empty.
if len(repo):
return
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 if pullop.heads:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not remote.capable(b'clonebundles'):
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 return
Gregory Szorc
wireproto: properly call clonebundles command...
r37667 with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 res = e.callcommand(b'clonebundles', {}).result()
Gregory Szorc
exchange: record that we attempted to fetch a clone bundle...
r26689
# If we call the wire protocol command, that's good enough to record the
# attempt.
pullop.clonebundleattempted = True
Gregory Szorc
exchange: extract bundle specification components into own attributes...
r26647 entries = parseclonebundlesmanifest(repo, res)
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 if not entries:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.note(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'no clone bundles available on remote; '
b'falling back to regular clone\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 return
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360 entries = filterclonebundleentries(
Augie Fackler
formatting: blacken the codebase...
r43346 repo, entries, streamclonerequested=pullop.streamclonerequested
)
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 if not entries:
# There is a thundering herd concern here. However, if a server
# operator doesn't advertise bundles appropriate for its clients,
# they deserve what's coming. Furthermore, from a client's
# perspective, no automatic fallback would mean not being able to
# clone!
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'no compatible clone bundles available on server; '
b'falling back to regular clone\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
repo.ui.warn(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'(you may want to report this to the server operator)\n')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 return
Gregory Szorc
exchange: support sorting URLs by client-side preferences...
r26648 entries = sortclonebundleentries(repo.ui, entries)
Gregory Szorc
clonebundles: filter on bundle specification...
r26644
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 url = entries[0][b'URL']
repo.ui.status(_(b'applying clone bundle from %s\n') % url)
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 if trypullbundlefromurl(repo.ui, repo, url):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b'finished applying clone bundle\n'))
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 # Bundle failed.
#
# We abort by default to avoid the thundering herd of
# clients flooding a server that was expecting expensive
# clone load to be offloaded.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif repo.ui.configbool(b'ui', b'clonebundlefallback'):
repo.ui.warn(_(b'falling back to normal clone\n'))
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'error applying bundle'),
Augie Fackler
formatting: blacken the codebase...
r43346 hint=_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'if this error persists, consider contacting '
b'the server operator or disable clone '
b'bundles via '
b'"--config ui.clonebundles=false"'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623
Gregory Szorc
exchange: extract bundle specification components into own attributes...
r26647 def parseclonebundlesmanifest(repo, s):
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 """Parses the raw text of a clone bundles manifest.
Returns a list of dicts. The dicts have a ``URL`` key corresponding
to the URL and other keys are the attributes for the entry.
"""
m = []
for line in s.splitlines():
fields = line.split()
if not fields:
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 attrs = {b'URL': fields[0]}
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 for rawattr in fields[1:]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 key, value = rawattr.split(b'=', 1)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 key = urlreq.unquote(key)
value = urlreq.unquote(value)
Gregory Szorc
exchange: extract bundle specification components into own attributes...
r26647 attrs[key] = value
# Parse BUNDLESPEC into components. This makes client-side
# preferences easier to specify since you can prefer a single
# component of the BUNDLESPEC.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if key == b'BUNDLESPEC':
Gregory Szorc
exchange: extract bundle specification components into own attributes...
r26647 try:
Joerg Sonnenberger
bundlespec: drop externalnames flag...
r37786 bundlespec = parsebundlespec(repo, value)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 attrs[b'COMPRESSION'] = bundlespec.compression
attrs[b'VERSION'] = bundlespec.version
Gregory Szorc
exchange: extract bundle specification components into own attributes...
r26647 except error.InvalidBundleSpecification:
pass
except error.UnsupportedBundleSpecification:
pass
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623
m.append(attrs)
return m
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
streamclonebundle: make sure we accept new stream clone bundle spec...
r37187 def isstreamclonespec(bundlespec):
# Stream clone v1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if bundlespec.wirecompression == b'UN' and bundlespec.wireversion == b's1':
Boris Feld
streamclonebundle: make sure we accept new stream clone bundle spec...
r37187 return True
# Stream clone v2
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundlespec.wirecompression == b'UN'
and bundlespec.wireversion == b'02'
and bundlespec.contentopts.get(b'streamv2')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Boris Feld
streamclonebundle: make sure we accept new stream clone bundle spec...
r37187 return True
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360 def filterclonebundleentries(repo, entries, streamclonerequested=False):
Gregory Szorc
exchange: document filterclonebundleentries
r26687 """Remove incompatible clone bundle manifest entries.
Accepts a list of entries parsed with ``parseclonebundlesmanifest``
and returns a new list consisting of only the entries that this client
should be able to apply.
There is no guarantee we'll be able to apply all returned entries because
the metadata we use to filter on may be missing or wrong.
"""
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 newentries = []
for entry in entries:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 spec = entry.get(b'BUNDLESPEC')
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 if spec:
try:
Boris Feld
bundlespec: introduce an attr-based class for bundlespec...
r37181 bundlespec = parsebundlespec(repo, spec, strict=True)
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360
# If a stream clone was requested, filter out non-streamclone
# entries.
Boris Feld
streamclonebundle: make sure we accept new stream clone bundle spec...
r37187 if streamclonerequested and not isstreamclonespec(bundlespec):
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filtering %s because not a stream clone\n'
% entry[b'URL']
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360 continue
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 except error.InvalidBundleSpecification as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(stringutil.forcebytestr(e) + b'\n')
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 continue
except error.UnsupportedBundleSpecification as e:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filtering %s because unsupported bundle '
b'spec: %s\n' % (entry[b'URL'], stringutil.forcebytestr(e))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 continue
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360 # If we don't have a spec and requested a stream clone, we don't know
# what the entry is so don't attempt to apply it.
elif streamclonerequested:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filtering %s because cannot determine if a stream '
b'clone bundle\n' % entry[b'URL']
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
exchange: perform stream clone with clone bundle with --uncompressed...
r34360 continue
Gregory Szorc
clonebundles: filter on bundle specification...
r26644
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'REQUIRESNI' in entry and not sslutil.hassni:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filtering %s because SNI not supported\n' % entry[b'URL']
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
clonebundles: filter on SNI requirement...
r26645 continue
Gregory Szorc
clonebundles: filter on bundle specification...
r26644 newentries.append(entry)
return newentries
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 class clonebundleentry(object):
"""Represents an item in a clone bundles manifest.
This rich class is needed to support sorting since sorted() in Python 3
doesn't support ``cmp`` and our comparison is complex enough that ``key=``
won't work.
"""
Gregory Szorc
exchange: support sorting URLs by client-side preferences...
r26648
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 def __init__(self, value, prefers):
self.value = value
self.prefers = prefers
Gregory Szorc
exchange: support sorting URLs by client-side preferences...
r26648
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 def _cmp(self, other):
for prefkey, prefvalue in self.prefers:
avalue = self.value.get(prefkey)
bvalue = other.value.get(prefkey)
Gregory Szorc
exchange: support sorting URLs by client-side preferences...
r26648
# Special case for b missing attribute and a matches exactly.
if avalue is not None and bvalue is None and avalue == prefvalue:
return -1
# Special case for a missing attribute and b matches exactly.
if bvalue is not None and avalue is None and bvalue == prefvalue:
return 1
# We can't compare unless attribute present on both.
if avalue is None or bvalue is None:
continue
# Same values should fall back to next attribute.
if avalue == bvalue:
continue
# Exact matches come first.
if avalue == prefvalue:
return -1
if bvalue == prefvalue:
return 1
# Fall back to next attribute.
continue
# If we got here we couldn't sort by attributes and prefers. Fall
# back to index order.
return 0
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 def __lt__(self, other):
return self._cmp(other) < 0
def __gt__(self, other):
return self._cmp(other) > 0
def __eq__(self, other):
return self._cmp(other) == 0
def __le__(self, other):
return self._cmp(other) <= 0
def __ge__(self, other):
return self._cmp(other) >= 0
def __ne__(self, other):
return self._cmp(other) != 0
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 def sortclonebundleentries(ui, entries):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefers = ui.configlist(b'ui', b'clonebundleprefers')
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685 if not prefers:
return list(entries)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefers = [p.split(b'=', 1) for p in prefers]
Gregory Szorc
exchange: use rich class for sorting clone bundle entries...
r30685
items = sorted(clonebundleentry(v, prefers) for v in entries)
return [i.value for i in items]
Gregory Szorc
exchange: support sorting URLs by client-side preferences...
r26648
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 def trypullbundlefromurl(ui, repo, url):
"""Attempt to apply a bundle from a URL."""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with repo.lock(), repo.transaction(b'bundleurl') as tr:
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623 try:
Martin von Zweigbergk
clonebundle: use context managers for lock and transaction
r32843 fh = urlmod.open(ui, url)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cg = readbundle(ui, fh, b'stream')
Gregory Szorc
clonebundle: support bundle2...
r26643
Martin von Zweigbergk
bundle: make applybundle() delegate v1 bundles to applybundle1()
r33043 if isinstance(cg, streamclone.streamcloneapplier):
Martin von Zweigbergk
clonebundle: use context managers for lock and transaction
r32843 cg.apply(repo)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundle2.applybundle(repo, cg, tr, b'clonebundles', url)
Martin von Zweigbergk
clonebundle: use context managers for lock and transaction
r32843 return True
except urlerr.httperror as e:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'HTTP error fetching bundle: %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % stringutil.forcebytestr(e)
)
Martin von Zweigbergk
clonebundle: use context managers for lock and transaction
r32843 except urlerr.urlerror as e:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'error fetching bundle: %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % stringutil.forcebytestr(e.reason)
)
Gregory Szorc
clonebundles: support for seeding clones from pre-generated bundles...
r26623
Martin von Zweigbergk
clonebundle: use context managers for lock and transaction
r32843 return False