##// END OF EJS Templates
chg: be stricter about checking invocation of `serve` command...
chg: be stricter about checking invocation of `serve` command Few tests run serve command in form of `hg -R <repo> serve` which leads to chg thinking that it's not a serve command and failing tests. We become more stricter in checking for the serve command. This fixes test-server-view.t, test-remote-hidden.t, test-remotefilelog-http.t, test-phases-exchange.t, test-wireproto-content-redirects.t with chg.

File last commit:

r43812:2fe6121c default
r45107:1e459ac4 default
Show More
narrowbundle2.py
342 lines | 11.3 KiB | text/x-python | PythonLexer
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # narrowbundle2.py - bundle2 extensions for narrow repository support
#
# Copyright 2017 Google, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import errno
import struct
from mercurial.i18n import _
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 from mercurial.node import nullid
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 from mercurial import (
bundle2,
changegroup,
error,
exchange,
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 localrepo,
Gregory Szorc
narrowspec: move module into core...
r36178 narrowspec,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 repair,
util,
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 wireprototypes,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 )
Augie Fackler
formatting: blacken the codebase...
r43346 from mercurial.interfaces import repository
from mercurial.utils import stringutil
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _NARROWACL_SECTION = b'narrowacl'
_CHANGESPECPART = b'narrow:changespec'
_RESSPECS = b'narrow:responsespec'
_SPECPART = b'narrow:spec'
_SPECPART_INCLUDE = b'include'
_SPECPART_EXCLUDE = b'exclude'
_KILLNODESIGNAL = b'KILL'
_DONESIGNAL = b'DONE'
_ELIDEDCSHEADER = b'>20s20s20sl' # cset id, p1, p2, len(text)
_ELIDEDMFHEADER = b'>20s20s20s20sl' # manifest id, p1, p2, link id, len(text)
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER)
_MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Serve a changegroup for a client with a narrow clone.
Augie Fackler
formatting: blacken the codebase...
r43346 def getbundlechangegrouppart_narrow(
bundler,
repo,
source,
bundlecaps=None,
b2caps=None,
heads=None,
common=None,
**kwargs
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert repo.ui.configbool(b'experimental', b'narrowservebrokenellipses')
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgversions = b2caps.get(b'changegroup')
Augie Fackler
formatting: blacken the codebase...
r43346 cgversions = [
v
for v in cgversions
if v in changegroup.supportedoutgoingversions(repo)
]
Pulkit Goyal
narrow: remove unrequired compat code for old versions of hg...
r42557 if not cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(_(b'no common changegroup version'))
Pulkit Goyal
narrow: remove unrequired compat code for old versions of hg...
r42557 version = max(cgversions)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 include = sorted(filter(bool, kwargs.get('includepats', [])))
exclude = sorted(filter(bool, kwargs.get('excludepats', [])))
Augie Fackler
formatting: blacken the codebase...
r43346 generateellipsesbundle2(
bundler,
repo,
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 include,
exclude,
Augie Fackler
formatting: blacken the codebase...
r43346 version,
common,
heads,
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 kwargs.get('depth', None),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346 def generateellipsesbundle2(
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 bundler, repo, include, exclude, version, common, heads, depth,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 match = narrowspec.match(repo.root, include=include, exclude=exclude)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if depth is not None:
depth = int(depth)
if depth < 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'depth must be positive, got %d') % depth)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
heads = set(heads or repo.heads())
common = set(common or [nullid])
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 repo, common, heads, set(), match, depth=depth
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b'Found %d relevant revs\n' % len(relevant_nodes))
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if visitnodes:
Augie Fackler
formatting: blacken the codebase...
r43346 packer = changegroup.getbundler(
version,
repo,
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 matcher=match,
Augie Fackler
formatting: blacken the codebase...
r43346 ellipses=True,
shallow=depth is not None,
ellipsisroots=ellipsisroots,
fullnodes=relevant_nodes,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgdata = packer.generate(common, visitnodes, False, b'narrow_widen')
Gregory Szorc
changegroup: inline _packellipsischangegroup...
r38946
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'changegroup', data=cgdata)
part.addparam(b'version', version)
if b'treemanifest' in repo.requirements:
part.addparam(b'treemanifest', b'1')
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 def generate_ellipses_bundle2_for_widening(
Martin von Zweigbergk
widening: pass in matchers instead of patterns...
r43543 bundler, repo, oldmatch, newmatch, version, common, known,
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 ):
common = set(common or [nullid])
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 # Steps:
# 1. Send kill for "$known & ::common"
#
# 2. Send changegroup for ::common
#
# 3. Proceed.
#
# In the future, we can send kills for only the specific
# nodes we know should go away or change shape, and then
# send a data stream that tells the client something like this:
#
# a) apply this changegroup
# b) apply nodes XXX, YYY, ZZZ that you already have
# c) goto a
#
# until they've built up the full new state.
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 knownrevs = {repo.changelog.rev(n) for n in known}
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 # TODO: we could send only roots() of this set, and the
# list of nodes in common, and the client could work out
# what to strip, instead of us explicitly sending every
# single node.
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 deadrevs = knownrevs
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 def genkills():
for r in deadrevs:
yield _KILLNODESIGNAL
yield repo.changelog.node(r)
yield _DONESIGNAL
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 bundler.newpart(_CHANGESPECPART, data=genkills())
newvisit, newfull, newellipsis = exchange._computeellipsis(
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 repo, set(), common, knownrevs, newmatch
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 )
if newvisit:
packer = changegroup.getbundler(
version,
repo,
matcher=newmatch,
ellipses=True,
Martin von Zweigbergk
widening: remove "depth" argument since it's always None...
r43541 shallow=False,
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 ellipsisroots=newellipsis,
fullnodes=newfull,
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 )
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 cgdata = packer.generate(common, newvisit, False, b'narrow_widen')
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 part = bundler.newpart(b'changegroup', data=cgdata)
part.addparam(b'version', version)
if b'treemanifest' in repo.requirements:
part.addparam(b'treemanifest', b'1')
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def _handlechangespec_2(op, inpart):
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 # XXX: This bundle2 handling is buggy and should be removed after hg5.2 is
# released. New servers will send a mandatory bundle2 part named
# 'Narrowspec' and will send specs as data instead of params.
# Refer to issue5952 and 6019
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 includepats = set(inpart.params.get(_SPECPART_INCLUDE, b'').splitlines())
excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, b'').splitlines())
Gregory Szorc
narrow: validate patterns on incoming bundle2 part...
r39576 narrowspec.validatepatterns(includepats)
narrowspec.validatepatterns(excludepats)
Martin von Zweigbergk
narrow: move requirement constant from changegroup to repository...
r38871 if not repository.NARROW_REQUIREMENT in op.repo.requirements:
op.repo.requirements.add(repository.NARROW_REQUIREMENT)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 op.repo._writerequirements()
Martin von Zweigbergk
narrow: reduce depedence on narrowspec.save()...
r36487 op.repo.setnarrowpats(includepats, excludepats)
Martin von Zweigbergk
narrow: move copytonarrowspec() out of setnarrowpats()...
r41272 narrowspec.copytoworkingcopy(op.repo)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 @bundle2.parthandler(_RESSPECS)
def _handlenarrowspecs(op, inpart):
data = inpart.read()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 inc, exc = data.split(b'\0')
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 includepats = set(inc.splitlines())
excludepats = set(exc.splitlines())
narrowspec.validatepatterns(includepats)
narrowspec.validatepatterns(excludepats)
if repository.NARROW_REQUIREMENT not in op.repo.requirements:
op.repo.requirements.add(repository.NARROW_REQUIREMENT)
op.repo._writerequirements()
op.repo.setnarrowpats(includepats, excludepats)
narrowspec.copytoworkingcopy(op.repo)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 @bundle2.parthandler(_CHANGESPECPART)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def _handlechangespec(op, inpart):
repo = op.repo
cl = repo.changelog
# changesets which need to be stripped entirely. either they're no longer
# needed in the new narrow spec, or the server is sending a replacement
# in the changegroup part.
clkills = set()
# A changespec part contains all the updates to ellipsis nodes
# that will happen as a result of widening or narrowing a
# repo. All the changes that this block encounters are ellipsis
# nodes or flags to kill an existing ellipsis.
chunksignal = changegroup.readexactly(inpart, 4)
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 while chunksignal != _DONESIGNAL:
if chunksignal == _KILLNODESIGNAL:
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # a node used to be an ellipsis but isn't anymore
ck = changegroup.readexactly(inpart, 20)
if cl.hasnode(ck):
clkills.add(ck)
else:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'unexpected changespec node chunk type: %s') % chunksignal
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 chunksignal = changegroup.readexactly(inpart, 4)
if clkills:
# preserve bookmarks that repair.strip() would otherwise strip
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 op._bookmarksbackup = repo._bookmarks
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 class dummybmstore(dict):
def applychanges(self, repo, tr, changes):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 localrepo.localrepository._bookmarks.set(repo, dummybmstore())
Augie Fackler
formatting: blacken the codebase...
r43346 chgrpfile = repair.strip(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 op.ui, repo, list(clkills), backup=True, topic=b'widen'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if chgrpfile:
Kyle Lippincott
procutil: correct spelling of uninterruptable -> uninterruptible...
r41106 op._widen_uninterr = repo.ui.uninterruptible()
Augie Fackler
narrowbundle2: when we handle a widen, mark the operation as unsafe...
r38548 op._widen_uninterr.__enter__()
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # presence of _widen_bundle attribute activates widen handler later
op._widen_bundle = chgrpfile
# Set the new narrowspec if we're widening. The setnewnarrowpats() method
# will currently always be there when using the core+narrowhg server, but
# other servers may include a changespec part even when not widening (e.g.
# because we're deepening a shallow repo).
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(repo, 'setnewnarrowpats'):
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 repo.setnewnarrowpats()
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def handlechangegroup_widen(op, inpart):
"""Changegroup exchange handler which restores temporarily-stripped nodes"""
# We saved a bundle with stripped node data we must now restore.
# This approach is based on mercurial/repair.py@6ee26a53c111.
repo = op.repo
ui = op.ui
chgrpfile = op._widen_bundle
del op._widen_bundle
vfs = repo.vfs
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"adding branch\n"))
f = vfs.open(chgrpfile, b"rb")
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 try:
gen = exchange.readbundle(ui, f, chgrpfile, vfs)
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 # silence internal shuffling chatter
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 override = {(b'ui', b'quiet'): True}
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 if ui.verbose:
override = {}
with ui.configoverride(override):
if isinstance(gen, bundle2.unbundle20):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with repo.transaction(b'strip') as tr:
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 bundle2.processbundle(repo, gen, lambda: tr)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 gen.apply(
repo, b'strip', b'bundle:' + vfs.join(chgrpfile), True
)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 finally:
f.close()
# remove undo files
for undovfs, undofile in repo.undofiles():
try:
undovfs.unlink(undofile)
except OSError as e:
if e.errno != errno.ENOENT:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'error removing %s: %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (undovfs.join(undofile), stringutil.forcebytestr(e))
)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Remove partial backup only if there were no exceptions
Augie Fackler
narrowbundle2: when we handle a widen, mark the operation as unsafe...
r38548 op._widen_uninterr.__exit__(None, None, None)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 vfs.unlink(chgrpfile)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def setup():
"""Enable narrow repo support in bundle2-related extension points."""
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 getbundleargs[b'narrow'] = b'boolean'
getbundleargs[b'depth'] = b'plain'
getbundleargs[b'oldincludepats'] = b'csv'
getbundleargs[b'oldexcludepats'] = b'csv'
getbundleargs[b'known'] = b'csv'
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Extend changegroup serving to handle requests from narrow clients.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 origcgfn = exchange.getbundle2partsmapping[b'changegroup']
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def wrappedcgfn(*args, **kwargs):
repo = args[1]
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 if repo.ui.has_section(_NARROWACL_SECTION):
Gregory Szorc
exchange: make narrow ACL presence imply narrow=True...
r38843 kwargs = exchange.applynarrowacl(repo, kwargs)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if kwargs.get('narrow', False) and repo.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'narrowservebrokenellipses'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 getbundlechangegrouppart_narrow(*args, **kwargs)
else:
origcgfn(*args, **kwargs)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 exchange.getbundle2partsmapping[b'changegroup'] = wrappedcgfn
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Extend changegroup receiver so client can fixup after widen requests.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 origcghandler = bundle2.parthandlermapping[b'changegroup']
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def wrappedcghandler(op, inpart):
origcghandler(op, inpart)
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(op, '_widen_bundle'):
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 handlechangegroup_widen(op, inpart)
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(op, '_bookmarksbackup'):
Augie Fackler
formatting: blacken the codebase...
r43346 localrepo.localrepository._bookmarks.set(
op.repo, op._bookmarksbackup
)
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 del op._bookmarksbackup
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 wrappedcghandler.params = origcghandler.params
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundle2.parthandlermapping[b'changegroup'] = wrappedcghandler