Mercurial: fix ssh-server support for UI objects

- fixed evolve/topic usage
- fixed propagation of publishing and extension flags
This commit is contained in:
Marcin Kuzminski 2019-04-07 13:39:06 +02:00
parent d621ac19ee
commit d693a556b4
3 changed files with 65 additions and 46 deletions

View file

@ -20,12 +20,12 @@
import os
import sys
import shutil
import logging
import tempfile
import textwrap
import collections
from .base import VcsServer
from rhodecode.model.settings import VcsSettingsModel
log = logging.getLogger(__name__)
@ -37,14 +37,15 @@ class MercurialTunnelWrapper(object):
self.server = server
self.stdin = sys.stdin
self.stdout = sys.stdout
self.svn_conf_fd, self.svn_conf_path = tempfile.mkstemp()
self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp()
self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp(prefix='hgrc_rhodecode_')
def create_hooks_env(self):
repo_name = self.server.repo_name
hg_flags = self.config_to_hgrc(repo_name)
content = textwrap.dedent(
'''
# SSH hooks version=1.0.0
# SSH hooks version=2.0.0
[hooks]
pretxnchangegroup.ssh_auth=python:vcsserver.hooks.pre_push_ssh_auth
pretxnchangegroup.ssh=python:vcsserver.hooks.pre_push_ssh
@ -53,46 +54,38 @@ class MercurialTunnelWrapper(object):
preoutgoing.ssh=python:vcsserver.hooks.pre_pull_ssh
outgoing.ssh=python:vcsserver.hooks.post_pull_ssh
# Custom Config version=2.0.0
{custom}
'''
)
).format(custom='\n'.join(hg_flags))
root = self.server.get_root_store()
hgrc_custom = os.path.join(root, repo_name, '.hg', 'hgrc_rhodecode')
hgrc_main = os.path.join(root, repo_name, '.hg', 'hgrc')
# cleanup custom hgrc file
if os.path.isfile(hgrc_custom):
with open(hgrc_custom, 'wb') as f:
f.write('')
log.debug('Cleanup custom hgrc file under %s', hgrc_custom)
# write temp
with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
hooks_env_file.write(content)
root = self.server.get_root_store()
hgrc_custom = os.path.join(
root, self.server.repo_name, '.hg', 'hgrc_rhodecode')
log.debug('Wrote custom hgrc file under %s', hgrc_custom)
shutil.move(
self.hooks_env_path, hgrc_custom)
return self.hooks_env_path
hgrc_main = os.path.join(
root, self.server.repo_name, '.hg', 'hgrc')
include_marker = '%include hgrc_rhodecode'
def remove_configs(self):
os.remove(self.hooks_env_path)
if not os.path.isfile(hgrc_main):
os.mknod(hgrc_main)
with open(hgrc_main, 'rb') as f:
data = f.read()
has_marker = include_marker in data
if not has_marker:
log.debug('Adding include marker for hooks')
with open(hgrc_main, 'wa') as f:
f.write(textwrap.dedent('''
# added by RhodeCode
{}
'''.format(include_marker)))
def command(self):
def command(self, hgrc_path):
root = self.server.get_root_store()
command = (
"cd {root}; {hg_path} -R {root}{repo_name} "
"cd {root}; HGRCPATH={hgrc} {hg_path} -R {root}{repo_name} "
"serve --stdio".format(
root=root, hg_path=self.server.hg_path,
repo_name=self.server.repo_name))
repo_name=self.server.repo_name, hgrc=hgrc_path))
log.debug("Final CMD: %s", command)
return command
@ -102,22 +95,43 @@ class MercurialTunnelWrapper(object):
action = '?'
# permissions are check via `pre_push_ssh_auth` hook
self.server.update_environment(action=action, extras=extras)
self.create_hooks_env()
return os.system(self.command())
custom_hgrc_file = self.create_hooks_env()
try:
return os.system(self.command(custom_hgrc_file))
finally:
self.remove_configs()
class MercurialServer(VcsServer):
backend = 'hg'
cli_flags = ['phases', 'largefiles', 'extensions', 'experimental']
def __init__(self, store, ini_path, repo_name,
user, user_permissions, config, env):
super(MercurialServer, self).\
__init__(user, user_permissions, config, env)
def __init__(self, store, ini_path, repo_name, user, user_permissions, config, env):
super(MercurialServer, self).__init__(user, user_permissions, config, env)
self.store = store
self.ini_path = ini_path
self.repo_name = repo_name
self._path = self.hg_path = config.get(
'app:main', 'ssh.executable.hg')
self._path = self.hg_path = config.get('app:main', 'ssh.executable.hg')
self.tunnel = MercurialTunnelWrapper(server=self)
def config_to_hgrc(self, repo_name):
ui_sections = collections.defaultdict(list)
ui = VcsSettingsModel(repo=repo_name).get_ui_settings(section=None, key=None)
for entry in ui:
if not entry.active:
continue
sec = entry.section
if sec in self.cli_flags:
ui_sections[sec].append([entry.key, entry.value])
flags = []
for _sec, key_val in ui_sections.items():
flags.append(' ')
flags.append('[{}]'.format(_sec))
for key, val in key_val:
flags.append('{}= {}'.format(key, val))
return flags

View file

@ -18,6 +18,7 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import os
import mock
import pytest
@ -68,14 +69,16 @@ def hg_server(app):
class TestMercurialServer(object):
def test_command(self, hg_server):
def test_command(self, hg_server, tmpdir):
server = hg_server.create()
custom_hgrc = os.path.join(str(tmpdir), 'hgrc')
expected_command = (
'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio'.format(
root=hg_server.root, hg_path=hg_server.hg_path,
'cd {root}; HGRCPATH={custom_hgrc} {hg_path} -R {root}{repo_name} serve --stdio'.format(
root=hg_server.root, custom_hgrc=custom_hgrc, hg_path=hg_server.hg_path,
repo_name=hg_server.repo_name)
)
assert expected_command == server.tunnel.command()
server_command = server.tunnel.command(custom_hgrc)
assert expected_command == server_command
@pytest.mark.parametrize('permissions, action, code', [
({}, 'pull', -2),

View file

@ -449,6 +449,7 @@ class VcsSettingsModel(object):
('extensions', 'evolve'),
('extensions', 'topic'),
('experimental', 'evolution'),
('experimental', 'evolution.exchange'),
)
GIT_SETTINGS = (
('vcs_git_lfs', 'enabled'),
@ -461,6 +462,7 @@ class VcsSettingsModel(object):
('extensions', 'evolve'),
('extensions', 'topic'),
('experimental', 'evolution'),
('experimental', 'evolution.exchange'),
)
GLOBAL_GIT_SETTINGS = (