diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e5a54fefe3f09cc2c611eb677ab4446e8849cdc7_LmdpdGxhYi1jaS55bWw=..225920b2ad2e1c61ca62fe7dab98dd0aa4e37aca_LmdpdGxhYi1jaS55bWw= 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ stage: main image: octobus/ci-py-heptapod:py3 script: - - flake8 --exclude stub hgitaly + - flake8 --exclude stub hgitaly hgext3rd - PYTHONPATH=/ci/repos/mercurial /usr/bin/pytest-3 --cov hgitaly --cov-config=.coveragerc -v tests-hg-stable: diff --git a/hgext3rd/hgitaly/__init__.py b/hgext3rd/hgitaly/__init__.py index e5a54fefe3f09cc2c611eb677ab4446e8849cdc7_aGdleHQzcmQvaGdpdGFseS9fX2luaXRfXy5weQ==..225920b2ad2e1c61ca62fe7dab98dd0aa4e37aca_aGdleHQzcmQvaGdpdGFseS9fX2luaXRfXy5weQ== 100644 --- a/hgext3rd/hgitaly/__init__.py +++ b/hgext3rd/hgitaly/__init__.py @@ -0,0 +1,111 @@ +# Copyright 2020 Georges Racinet <georges.racinet@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import logging + +import grpc +from mercurial.i18n import _ +from mercurial import ( + error, + pycompat, + registrar, +) + +from hgitaly.stub import ( + commit_pb2_grpc, +) +from hgitaly.servicer import ( + Servicer as CommitServicer, +) + +# mercurial.urllibcompat seems to be willing to make urlparse access uniform, +# but couldn't make it work on py3 right away, and it looks like dead code +# anyway. Conditional import is way simpler, provided one does not do it by +# catching ImportError (because of the demandimport trap) +if pycompat.ispy3: + from urllib.parse import urlparse + from concurrent import futures +else: + from urlparse import urlparse + import futures + + +logger = logging.getLogger(__name__) +cmdtable = {} +command = registrar.command(cmdtable) + + +DEFAULT_LISTEN_URL = b'tcp://127.0.0.1:9237' + + +@command(b'hgitaly-serve', + [(b'', b'repositories-root', + None, + _(b'Path to the root directory for repositories storage. ' + b'Defaults to the `heptapod.repositories-root` ' + b'configuration item '), + _(b'REPOS_ROOT')), + (b'', b'listen', + [], + _(b'URL to listen on, default is %s, can be ' + b'repeated to listen on several addresses' % DEFAULT_LISTEN_URL), + _(b'ADDRESS')), + ], + _('[OPTIONS]...'), + norepo=True + ) +def serve(ui, **opts): + """Start a HGitaly server. + + By default the root of repositories is read from the + `heptapod.repositories-root` configuration item if present. + """ + listen_urls = opts['listen'] + if not listen_urls: + # Any default in the option declaration would be added to + # explicely passed values. This is not what we want, hence the late + # defaulting done here. + + # Although gRPC defaults to IPv6, existing Gitaly setups + # (GDK and monolithic Docker container) bind explicitely on IPv4 + listen_urls = [DEFAULT_LISTEN_URL] + repos_root = opts.get('repositories_root') + if repos_root is None: + repos_root = ui.config(b'heptapod', b'repositories-root') + if repos_root is None: + raise error.Abort(_( + b"No value found in configuration for " + b"'heptapod.repositories-root'. Please define it or run " + b"the command with the --repositories-root option." + )) + server = grpc.server(futures.ThreadPoolExecutor(max_workers=1)) + commit_pb2_grpc.add_CommitServiceServicer_to_server( + CommitServicer(repos_root), server) + + for url in listen_urls: + try: + parsed_url = urlparse(url) + except Exception as exc: + raise error.Abort(_( + b"Could not parse url %s: %s" % ( + url, pycompat.sysbytes(repr(exc))))) + if parsed_url.scheme != b'tcp': + raise error.Abort(_( + b"Only 'tcp://' URLs are supported for the time being " + b"to define listening addresses (got %s)" % url)) + port = server.add_insecure_port(parsed_url.netloc) + if port == 0: + raise error.Abort(_( + b"Could not bind to socket for %s. " + b"Please check that this URL is correct." % url)) + + logger.info("Listening on %r, final port is %d", + pycompat.sysstr(url), port) + + server.start() + logger.info("Server started") + server.wait_for_termination() diff --git a/setup.py b/setup.py index e5a54fefe3f09cc2c611eb677ab4446e8849cdc7_c2V0dXAucHk=..225920b2ad2e1c61ca62fe7dab98dd0aa4e37aca_c2V0dXAucHk= 100644 --- a/setup.py +++ b/setup.py @@ -12,5 +12,5 @@ license='GPLv2+', package_data=dict(heptapod=['*.hgrc']), packages=['hgitaly', 'hgext3rd.hgitaly'], - install_requires=[], + install_requires=['futures; python_version == "2.7"'], )