view hgext/remotefilelog/connectionpool.py @ 49781:f4a363b25859 stable

extensions: load help from hgext.__index__ as a fallback this time Prior to 843418dc0b1b, `hgext.__index__` was consulted first if present, which caused the longer help from the extension modules to be ignored, even when available. But that change causes a bunch of test failures when the pyoxidized binary bundles *.pyc in the binary, saying the there's no help topic for `hg help $disabled_extension` and suggesting the use of `--keyword`, rather than showing a summary and indicating that it is disabled. Current failures were in test-check-help.t, test-extension.t, test-help.t, and test-qrecord.t. Ideally, we would read the various *.pyc files from memory and slurp in the docstring, but I know that they used to not be readable as resources, and I can't figure out how to make it work now. So maybe 3.9 and/or the current PyOxidizer doesn't support it yet. I got closer in py2exe with `importlib.resources.open_binary("hgext", "rebase.pyc")`, but `open_binary()` on *.pyc fails in pyoxidizer.[1] Either way, the *.pyc can't be passed to `ast.parse()` as `extensions._disabledcmdtable()` is doing, so I'm setting that aside for now. [1] https://github.com/indygreg/PyOxidizer/issues/649
author Matt Harbison <matt_harbison@yahoo.com>
date Mon, 05 Dec 2022 16:05:04 -0500
parents 642e31cb55f0
children d718eddf01d9
line wrap: on
line source

# connectionpool.py - class for pooling peer connections for reuse
#
# Copyright 2017 Facebook, 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 mercurial import (
    hg,
    sshpeer,
    util,
)

_sshv1peer = sshpeer.sshv1peer


class connectionpool:
    def __init__(self, repo):
        self._repo = repo
        self._pool = dict()

    def get(self, path):
        pathpool = self._pool.get(path)
        if pathpool is None:
            pathpool = list()
            self._pool[path] = pathpool

        conn = None
        if len(pathpool) > 0:
            try:
                conn = pathpool.pop()
                peer = conn.peer
                # If the connection has died, drop it
                if isinstance(peer, _sshv1peer):
                    if peer._subprocess.poll() is not None:
                        conn = None
            except IndexError:
                pass

        if conn is None:

            peer = hg.peer(self._repo.ui, {}, path)
            if util.safehasattr(peer, '_cleanup'):

                class mypeer(peer.__class__):
                    def _cleanup(self, warn=None):
                        # close pipee first so peer.cleanup reading it won't
                        # deadlock, if there are other processes with pipeo
                        # open (i.e. us).
                        if util.safehasattr(self, 'pipee'):
                            self.pipee.close()
                        return super(mypeer, self)._cleanup()

                peer.__class__ = mypeer

            conn = connection(pathpool, peer)

        return conn

    def close(self):
        for pathpool in self._pool.values():
            for conn in pathpool:
                conn.close()
            del pathpool[:]


class connection:
    def __init__(self, pool, peer):
        self._pool = pool
        self.peer = peer

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        # Only add the connection back to the pool if there was no exception,
        # since an exception could mean the connection is not in a reusable
        # state.
        if type is None:
            self._pool.append(self)
        else:
            self.close()

    def close(self):
        if util.safehasattr(self.peer, 'cleanup'):
            self.peer.cleanup()