Skip to content
Snippets Groups Projects
Commit 225920b2 authored by Georges Racinet's avatar Georges Racinet
Browse files

bootstrap: server command

The command can be launched as `hg hgitaly-serve`. Being actually
a Mercurial command means it has its help page, generated from
the docstring and command-line options declaration.

We've made some effort to support Python 2 in the command, but
currently the actual servicer code is Python 3 only, because of
type annotations.
parent e5a54fef
No related branches found
No related tags found
1 merge request!1Bootstrapping hgitaly development
......@@ -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:
......
# 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()
......@@ -12,5 +12,5 @@
license='GPLv2+',
package_data=dict(heptapod=['*.hgrc']),
packages=['hgitaly', 'hgext3rd.hgitaly'],
install_requires=[],
install_requires=['futures; python_version == "2.7"'],
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment