view mercurial/streamclone.py @ 26442:ef8d27f53204

streamclone: move stream_in() from localrepo Another basic content move. The underscore from the function name was removed to comply with naming standards.
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 02 Oct 2015 15:58:24 -0700
parents 56527b886d1d
children d947086d8973
line wrap: on
line source

# streamclone.py - producing and consuming streaming repository data
#
# Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
#
# 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

from .i18n import _
from . import (
    branchmap,
    error,
    exchange,
    util,
)

def streamin(repo, remote, remotereqs):
    # Save remote branchmap. We will use it later
    # to speed up branchcache creation
    rbranchmap = None
    if remote.capable("branchmap"):
        rbranchmap = remote.branchmap()

    fp = remote.stream_out()
    l = fp.readline()
    try:
        resp = int(l)
    except ValueError:
        raise error.ResponseError(
            _('unexpected response from remote server:'), l)
    if resp == 1:
        raise util.Abort(_('operation forbidden by server'))
    elif resp == 2:
        raise util.Abort(_('locking the remote repository failed'))
    elif resp != 0:
        raise util.Abort(_('the server sent an unknown error code'))

    applyremotedata(repo, remotereqs, rbranchmap, fp)
    return len(repo.heads()) + 1

def applyremotedata(repo, remotereqs, remotebranchmap, fp):
    """Apply stream clone data to a repository.

    "remotereqs" is a set of requirements to handle the incoming data.
    "remotebranchmap" is the result of a branchmap lookup on the remote. It
    can be None.
    "fp" is a file object containing the raw stream data, suitable for
    feeding into exchange.consumestreamclone.
    """
    lock = repo.lock()
    try:
        exchange.consumestreamclone(repo, fp)

        # new requirements = old non-format requirements +
        #                    new format-related remote requirements
        # requirements from the streamed-in repository
        repo.requirements = remotereqs | (
                repo.requirements - repo.supportedformats)
        repo._applyopenerreqs()
        repo._writerequirements()

        if remotebranchmap:
            rbheads = []
            closed = []
            for bheads in remotebranchmap.itervalues():
                rbheads.extend(bheads)
                for h in bheads:
                    r = repo.changelog.rev(h)
                    b, c = repo.changelog.branchinfo(r)
                    if c:
                        closed.append(h)

            if rbheads:
                rtiprev = max((int(repo.changelog.rev(node))
                        for node in rbheads))
                cache = branchmap.branchcache(remotebranchmap,
                                              repo[rtiprev].node(),
                                              rtiprev,
                                              closednodes=closed)
                # Try to stick it as low as possible
                # filter above served are unlikely to be fetch from a clone
                for candidate in ('base', 'immutable', 'served'):
                    rview = repo.filtered(candidate)
                    if cache.validfor(rview):
                        repo._branchcaches[candidate] = cache
                        cache.write(rview)
                        break
        repo.invalidate()
    finally:
        lock.release()