##// END OF EJS Templates
ssh: fix invocation of custom hgrc
marcink -
r3660:703a84f2 default
parent child Browse files
Show More
@@ -1,147 +1,147 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import os
22 22 import sys
23 23 import logging
24 24 import tempfile
25 25 import textwrap
26 26 import collections
27 27 from .base import VcsServer
28 28 from rhodecode.model.db import RhodeCodeUi
29 29 from rhodecode.model.settings import VcsSettingsModel
30 30
31 31 log = logging.getLogger(__name__)
32 32
33 33
34 34 class MercurialTunnelWrapper(object):
35 35 process = None
36 36
37 37 def __init__(self, server):
38 38 self.server = server
39 39 self.stdin = sys.stdin
40 40 self.stdout = sys.stdout
41 41 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp(prefix='hgrc_rhodecode_')
42 42
43 43 def create_hooks_env(self):
44 44 repo_name = self.server.repo_name
45 hg_flags = self.config_to_hgrc(repo_name)
45 hg_flags = self.server.config_to_hgrc(repo_name)
46 46
47 47 content = textwrap.dedent(
48 48 '''
49 49 # RhodeCode SSH hooks version=2.0.0
50 50 {custom}
51 51 '''
52 52 ).format(custom='\n'.join(hg_flags))
53 53
54 54 root = self.server.get_root_store()
55 55 hgrc_custom = os.path.join(root, repo_name, '.hg', 'hgrc_rhodecode')
56 56 hgrc_main = os.path.join(root, repo_name, '.hg', 'hgrc')
57 57
58 58 # cleanup custom hgrc file
59 59 if os.path.isfile(hgrc_custom):
60 60 with open(hgrc_custom, 'wb') as f:
61 61 f.write('')
62 62 log.debug('Cleanup custom hgrc file under %s', hgrc_custom)
63 63
64 64 # write temp
65 65 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
66 66 hooks_env_file.write(content)
67 67
68 68 return self.hooks_env_path
69 69
70 70 def remove_configs(self):
71 71 os.remove(self.hooks_env_path)
72 72
73 73 def command(self, hgrc_path):
74 74 root = self.server.get_root_store()
75 75
76 76 command = (
77 77 "cd {root}; HGRCPATH={hgrc} {hg_path} -R {root}{repo_name} "
78 78 "serve --stdio".format(
79 79 root=root, hg_path=self.server.hg_path,
80 80 repo_name=self.server.repo_name, hgrc=hgrc_path))
81 81 log.debug("Final CMD: %s", command)
82 82 return command
83 83
84 84 def run(self, extras):
85 85 # at this point we cannot tell, we do further ACL checks
86 86 # inside the hooks
87 87 action = '?'
88 88 # permissions are check via `pre_push_ssh_auth` hook
89 89 self.server.update_environment(action=action, extras=extras)
90 90 custom_hgrc_file = self.create_hooks_env()
91 91
92 92 try:
93 93 return os.system(self.command(custom_hgrc_file))
94 94 finally:
95 95 self.remove_configs()
96 96
97 97
98 98 class MercurialServer(VcsServer):
99 99 backend = 'hg'
100 100 cli_flags = ['phases', 'largefiles', 'extensions', 'experimental', 'hooks']
101 101
102 102 def __init__(self, store, ini_path, repo_name, user, user_permissions, config, env):
103 103 super(MercurialServer, self).__init__(user, user_permissions, config, env)
104 104
105 105 self.store = store
106 106 self.ini_path = ini_path
107 107 self.repo_name = repo_name
108 108 self._path = self.hg_path = config.get('app:main', 'ssh.executable.hg')
109 109 self.tunnel = MercurialTunnelWrapper(server=self)
110 110
111 111 def config_to_hgrc(self, repo_name):
112 112 ui_sections = collections.defaultdict(list)
113 113 ui = VcsSettingsModel(repo=repo_name).get_ui_settings(section=None, key=None)
114 114
115 115 # write default hooks
116 116 default_hooks = [
117 117 ('pretxnchangegroup.ssh_auth', 'python:vcsserver.hooks.pre_push_ssh_auth'),
118 118 ('pretxnchangegroup.ssh', 'python:vcsserver.hooks.pre_push_ssh'),
119 119 ('changegroup.ssh', 'python:vcsserver.hooks.post_push_ssh'),
120 120
121 121 ('preoutgoing.ssh', 'python:vcsserver.hooks.pre_pull_ssh'),
122 122 ('outgoing.ssh', 'python:vcsserver.hooks.post_pull_ssh'),
123 123 ]
124 124
125 125 for k, v in default_hooks:
126 126 ui_sections['hooks'].append((k, v))
127 127
128 128 for entry in ui:
129 129 if not entry.active:
130 130 continue
131 131 sec = entry.section
132 132 key = entry.key
133 133
134 134 if sec in self.cli_flags:
135 135 # we want only custom hooks, so we skip builtins
136 136 if sec == 'hooks' and key in RhodeCodeUi.HOOKS_BUILTIN:
137 137 continue
138 138
139 139 ui_sections[sec].append([key, entry.value])
140 140
141 141 flags = []
142 142 for _sec, key_val in ui_sections.items():
143 143 flags.append(' ')
144 144 flags.append('[{}]'.format(_sec))
145 145 for key, val in key_val:
146 146 flags.append('{}= {}'.format(key, val))
147 147 return flags
General Comments 0
You need to be logged in to leave comments. Login now