##// END OF EJS Templates
logging: include more info in action logging...
Mads Kiilerich -
r3135:e7ba6928 beta
parent child Browse files
Show More
@@ -1,340 +1,341 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.middleware.simplegit
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 SimpleGit middleware for handling git protocol request (push/clone etc.)
7 7 It's implemented with basic auth function
8 8
9 9 :created_on: Apr 28, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 import re
29 29 import logging
30 30 import traceback
31 31
32 32 from dulwich import server as dulserver
33 33 from dulwich.web import LimitedInputFilter, GunzipFilter
34 34 from rhodecode.lib.exceptions import HTTPLockedRC
35 35 from rhodecode.lib.hooks import pre_pull
36 36
37 37
38 38 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
39 39
40 40 def handle(self):
41 41 write = lambda x: self.proto.write_sideband(1, x)
42 42
43 43 graph_walker = dulserver.ProtocolGraphWalker(self,
44 44 self.repo.object_store,
45 45 self.repo.get_peeled)
46 46 objects_iter = self.repo.fetch_objects(
47 47 graph_walker.determine_wants, graph_walker, self.progress,
48 48 get_tagged=self.get_tagged)
49 49
50 50 # Did the process short-circuit (e.g. in a stateless RPC call)? Note
51 51 # that the client still expects a 0-object pack in most cases.
52 52 if objects_iter is None:
53 53 return
54 54
55 55 self.progress("counting objects: %d, done.\n" % len(objects_iter))
56 56 dulserver.write_pack_objects(dulserver.ProtocolFile(None, write),
57 57 objects_iter)
58 58 messages = []
59 59 messages.append('thank you for using rhodecode')
60 60
61 61 for msg in messages:
62 62 self.progress(msg + "\n")
63 63 # we are done
64 64 self.proto.write("0000")
65 65
66 66
67 67 dulserver.DEFAULT_HANDLERS = {
68 68 #git-ls-remote, git-clone, git-fetch and git-pull
69 69 'git-upload-pack': SimpleGitUploadPackHandler,
70 70 #git-push
71 71 'git-receive-pack': dulserver.ReceivePackHandler,
72 72 }
73 73
74 74 # not used for now until dulwich get's fixed
75 75 #from dulwich.repo import Repo
76 76 #from dulwich.web import make_wsgi_chain
77 77
78 78 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
79 79 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
80 80 HTTPBadRequest, HTTPNotAcceptable
81 81
82 82 from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url
83 83 from rhodecode.lib.base import BaseVCSController
84 84 from rhodecode.lib.auth import get_container_username
85 85 from rhodecode.lib.utils import is_valid_repo, make_ui
86 86 from rhodecode.lib.compat import json
87 87 from rhodecode.model.db import User, RhodeCodeUi
88 88
89 89 log = logging.getLogger(__name__)
90 90
91 91
92 92 GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
93 93
94 94
95 95 def is_git(environ):
96 96 path_info = environ['PATH_INFO']
97 97 isgit_path = GIT_PROTO_PAT.match(path_info)
98 98 log.debug('pathinfo: %s detected as GIT %s' % (
99 99 path_info, isgit_path != None)
100 100 )
101 101 return isgit_path
102 102
103 103
104 104 class SimpleGit(BaseVCSController):
105 105
106 106 def _handle_request(self, environ, start_response):
107 107 if not is_git(environ):
108 108 return self.application(environ, start_response)
109 109 if not self._check_ssl(environ, start_response):
110 110 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)
111 111
112 112 ip_addr = self._get_ip_addr(environ)
113 113 username = None
114 114 self._git_first_op = False
115 115 # skip passing error to error controller
116 116 environ['pylons.status_code_redirect'] = True
117 117
118 118 #======================================================================
119 119 # EXTRACT REPOSITORY NAME FROM ENV
120 120 #======================================================================
121 121 try:
122 122 repo_name = self.__get_repository(environ)
123 123 log.debug('Extracted repo name is %s' % repo_name)
124 124 except:
125 125 return HTTPInternalServerError()(environ, start_response)
126 126
127 127 # quick check if that dir exists...
128 128 if is_valid_repo(repo_name, self.basepath, 'git') is False:
129 129 return HTTPNotFound()(environ, start_response)
130 130
131 131 #======================================================================
132 132 # GET ACTION PULL or PUSH
133 133 #======================================================================
134 134 action = self.__get_action(environ)
135 135
136 136 #======================================================================
137 137 # CHECK ANONYMOUS PERMISSION
138 138 #======================================================================
139 139 if action in ['pull', 'push']:
140 140 anonymous_user = self.__get_user('default')
141 141 username = anonymous_user.username
142 142 anonymous_perm = self._check_permission(action, anonymous_user,
143 143 repo_name, ip_addr)
144 144
145 145 if anonymous_perm is not True or anonymous_user.active is False:
146 146 if anonymous_perm is not True:
147 147 log.debug('Not enough credentials to access this '
148 148 'repository as anonymous user')
149 149 if anonymous_user.active is False:
150 150 log.debug('Anonymous access is disabled, running '
151 151 'authentication')
152 152 #==============================================================
153 153 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
154 154 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
155 155 #==============================================================
156 156
157 157 # Attempting to retrieve username from the container
158 158 username = get_container_username(environ, self.config)
159 159
160 160 # If not authenticated by the container, running basic auth
161 161 if not username:
162 162 self.authenticate.realm = \
163 163 safe_str(self.config['rhodecode_realm'])
164 164 result = self.authenticate(environ)
165 165 if isinstance(result, str):
166 166 AUTH_TYPE.update(environ, 'basic')
167 167 REMOTE_USER.update(environ, result)
168 168 username = result
169 169 else:
170 170 return result.wsgi_application(environ, start_response)
171 171
172 172 #==============================================================
173 173 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
174 174 #==============================================================
175 175 try:
176 176 user = self.__get_user(username)
177 177 if user is None or not user.active:
178 178 return HTTPForbidden()(environ, start_response)
179 179 username = user.username
180 180 except:
181 181 log.error(traceback.format_exc())
182 182 return HTTPInternalServerError()(environ, start_response)
183 183
184 184 #check permissions for this repository
185 185 perm = self._check_permission(action, user, repo_name, ip_addr)
186 186 if perm is not True:
187 187 return HTTPForbidden()(environ, start_response)
188 188
189 189 # extras are injected into UI object and later available
190 190 # in hooks executed by rhodecode
191 191 from rhodecode import CONFIG
192 192 server_url = get_server_url(environ)
193 193 extras = {
194 194 'ip': ip_addr,
195 195 'username': username,
196 196 'action': action,
197 197 'repository': repo_name,
198 198 'scm': 'git',
199 199 'config': CONFIG['__file__'],
200 200 'server_url': server_url,
201 201 'make_lock': None,
202 202 'locked_by': [None, None]
203 203 }
204 204
205 205 #===================================================================
206 206 # GIT REQUEST HANDLING
207 207 #===================================================================
208 208 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
209 209 log.debug('Repository path is %s' % repo_path)
210 210
211 211 # CHECK LOCKING only if it's not ANONYMOUS USER
212 212 if username != User.DEFAULT_USER:
213 213 log.debug('Checking locking on repository')
214 214 (make_lock,
215 215 locked,
216 216 locked_by) = self._check_locking_state(
217 217 environ=environ, action=action,
218 218 repo=repo_name, user_id=user.user_id
219 219 )
220 220 # store the make_lock for later evaluation in hooks
221 221 extras.update({'make_lock': make_lock,
222 222 'locked_by': locked_by})
223 223 # set the environ variables for this request
224 224 os.environ['RC_SCM_DATA'] = json.dumps(extras)
225 225 fix_PATH()
226 226 log.debug('HOOKS extras is %s' % extras)
227 227 baseui = make_ui('db')
228 228 self.__inject_extras(repo_path, baseui, extras)
229 229
230 230 try:
231 231 # invalidate cache on push
232 232 if action == 'push':
233 233 self._invalidate_cache(repo_name)
234 234 self._handle_githooks(repo_name, action, baseui, environ)
235 235
236 log.info('%s action on GIT repo "%s"' % (action, repo_name))
236 log.info('%s action on GIT repo "%s" by "%s" from %s' %
237 (action, repo_name, username, ip_addr))
237 238 app = self.__make_app(repo_name, repo_path, extras)
238 239 return app(environ, start_response)
239 240 except HTTPLockedRC, e:
240 log.debug('Repositry LOCKED ret code 423!')
241 log.debug('Repository LOCKED ret code 423!')
241 242 return e(environ, start_response)
242 243 except Exception:
243 244 log.error(traceback.format_exc())
244 245 return HTTPInternalServerError()(environ, start_response)
245 246
246 247 def __make_app(self, repo_name, repo_path, extras):
247 248 """
248 249 Make an wsgi application using dulserver
249 250
250 251 :param repo_name: name of the repository
251 252 :param repo_path: full path to the repository
252 253 """
253 254
254 255 from rhodecode.lib.middleware.pygrack import make_wsgi_app
255 256 app = make_wsgi_app(
256 257 repo_root=safe_str(self.basepath),
257 258 repo_name=repo_name,
258 259 extras=extras,
259 260 )
260 261 app = GunzipFilter(LimitedInputFilter(app))
261 262 return app
262 263
263 264 def __get_repository(self, environ):
264 265 """
265 266 Get's repository name out of PATH_INFO header
266 267
267 268 :param environ: environ where PATH_INFO is stored
268 269 """
269 270 try:
270 271 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
271 272 repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
272 273 except:
273 274 log.error(traceback.format_exc())
274 275 raise
275 276
276 277 return repo_name
277 278
278 279 def __get_user(self, username):
279 280 return User.get_by_username(username)
280 281
281 282 def __get_action(self, environ):
282 283 """
283 284 Maps git request commands into a pull or push command.
284 285
285 286 :param environ:
286 287 """
287 288 service = environ['QUERY_STRING'].split('=')
288 289
289 290 if len(service) > 1:
290 291 service_cmd = service[1]
291 292 mapping = {
292 293 'git-receive-pack': 'push',
293 294 'git-upload-pack': 'pull',
294 295 }
295 296 op = mapping[service_cmd]
296 297 self._git_stored_op = op
297 298 return op
298 299 else:
299 300 # try to fallback to stored variable as we don't know if the last
300 301 # operation is pull/push
301 302 op = getattr(self, '_git_stored_op', 'pull')
302 303 return op
303 304
304 305 def _handle_githooks(self, repo_name, action, baseui, environ):
305 306 """
306 307 Handles pull action, push is handled by post-receive hook
307 308 """
308 309 from rhodecode.lib.hooks import log_pull_action
309 310 service = environ['QUERY_STRING'].split('=')
310 311
311 312 if len(service) < 2:
312 313 return
313 314
314 315 from rhodecode.model.db import Repository
315 316 _repo = Repository.get_by_repo_name(repo_name)
316 317 _repo = _repo.scm_instance
317 318 _repo._repo.ui = baseui
318 319
319 320 _hooks = dict(baseui.configitems('hooks')) or {}
320 321 if action == 'pull':
321 322 # stupid git, emulate pre-pull hook !
322 323 pre_pull(ui=baseui, repo=_repo._repo)
323 324 if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL):
324 325 log_pull_action(ui=baseui, repo=_repo._repo)
325 326
326 327 def __inject_extras(self, repo_path, baseui, extras={}):
327 328 """
328 329 Injects some extra params into baseui instance
329 330
330 331 :param baseui: baseui instance
331 332 :param extras: dict with extra params to put into baseui
332 333 """
333 334
334 335 # make our hgweb quiet so it doesn't print output
335 336 baseui.setconfig('ui', 'quiet', 'true')
336 337
337 338 #inject some additional parameters that will be available in ui
338 339 #for hooks
339 340 for k, v in extras.items():
340 341 baseui.setconfig('rhodecode_extras', k, v)
@@ -1,287 +1,288 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.middleware.simplehg
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 SimpleHG middleware for handling mercurial protocol request
7 7 (push/clone etc.). It's implemented with basic auth function
8 8
9 9 :created_on: Apr 28, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 import logging
29 29 import traceback
30 30
31 31 from mercurial.error import RepoError
32 32 from mercurial.hgweb import hgweb_mod
33 33
34 34 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
35 35 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
36 36 HTTPBadRequest, HTTPNotAcceptable
37 37
38 38 from rhodecode.lib.utils2 import safe_str, fix_PATH, get_server_url
39 39 from rhodecode.lib.base import BaseVCSController
40 40 from rhodecode.lib.auth import get_container_username
41 41 from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
42 42 from rhodecode.lib.compat import json
43 43 from rhodecode.model.db import User
44 44 from rhodecode.lib.exceptions import HTTPLockedRC
45 45
46 46
47 47 log = logging.getLogger(__name__)
48 48
49 49
50 50 def is_mercurial(environ):
51 51 """
52 52 Returns True if request's target is mercurial server - header
53 53 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
54 54 """
55 55 http_accept = environ.get('HTTP_ACCEPT')
56 56 path_info = environ['PATH_INFO']
57 57 if http_accept and http_accept.startswith('application/mercurial'):
58 58 ishg_path = True
59 59 else:
60 60 ishg_path = False
61 61
62 62 log.debug('pathinfo: %s detected as HG %s' % (
63 63 path_info, ishg_path)
64 64 )
65 65 return ishg_path
66 66
67 67
68 68 class SimpleHg(BaseVCSController):
69 69
70 70 def _handle_request(self, environ, start_response):
71 71 if not is_mercurial(environ):
72 72 return self.application(environ, start_response)
73 73 if not self._check_ssl(environ, start_response):
74 74 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)
75 75
76 76 ip_addr = self._get_ip_addr(environ)
77 77 username = None
78 78 # skip passing error to error controller
79 79 environ['pylons.status_code_redirect'] = True
80 80
81 81 #======================================================================
82 82 # EXTRACT REPOSITORY NAME FROM ENV
83 83 #======================================================================
84 84 try:
85 85 repo_name = environ['REPO_NAME'] = self.__get_repository(environ)
86 86 log.debug('Extracted repo name is %s' % repo_name)
87 87 except:
88 88 return HTTPInternalServerError()(environ, start_response)
89 89
90 90 # quick check if that dir exists...
91 91 if is_valid_repo(repo_name, self.basepath, 'hg') is False:
92 92 return HTTPNotFound()(environ, start_response)
93 93
94 94 #======================================================================
95 95 # GET ACTION PULL or PUSH
96 96 #======================================================================
97 97 action = self.__get_action(environ)
98 98
99 99 #======================================================================
100 100 # CHECK ANONYMOUS PERMISSION
101 101 #======================================================================
102 102 if action in ['pull', 'push']:
103 103 anonymous_user = self.__get_user('default')
104 104 username = anonymous_user.username
105 105 anonymous_perm = self._check_permission(action, anonymous_user,
106 106 repo_name, ip_addr)
107 107
108 108 if anonymous_perm is not True or anonymous_user.active is False:
109 109 if anonymous_perm is not True:
110 110 log.debug('Not enough credentials to access this '
111 111 'repository as anonymous user')
112 112 if anonymous_user.active is False:
113 113 log.debug('Anonymous access is disabled, running '
114 114 'authentication')
115 115 #==============================================================
116 116 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
117 117 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
118 118 #==============================================================
119 119
120 120 # Attempting to retrieve username from the container
121 121 username = get_container_username(environ, self.config)
122 122
123 123 # If not authenticated by the container, running basic auth
124 124 if not username:
125 125 self.authenticate.realm = \
126 126 safe_str(self.config['rhodecode_realm'])
127 127 result = self.authenticate(environ)
128 128 if isinstance(result, str):
129 129 AUTH_TYPE.update(environ, 'basic')
130 130 REMOTE_USER.update(environ, result)
131 131 username = result
132 132 else:
133 133 return result.wsgi_application(environ, start_response)
134 134
135 135 #==============================================================
136 136 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
137 137 #==============================================================
138 138 try:
139 139 user = self.__get_user(username)
140 140 if user is None or not user.active:
141 141 return HTTPForbidden()(environ, start_response)
142 142 username = user.username
143 143 except:
144 144 log.error(traceback.format_exc())
145 145 return HTTPInternalServerError()(environ, start_response)
146 146
147 147 #check permissions for this repository
148 148 perm = self._check_permission(action, user, repo_name, ip_addr)
149 149 if perm is not True:
150 150 return HTTPForbidden()(environ, start_response)
151 151
152 152 # extras are injected into mercurial UI object and later available
153 153 # in hg hooks executed by rhodecode
154 154 from rhodecode import CONFIG
155 155 server_url = get_server_url(environ)
156 156 extras = {
157 157 'ip': ip_addr,
158 158 'username': username,
159 159 'action': action,
160 160 'repository': repo_name,
161 161 'scm': 'hg',
162 162 'config': CONFIG['__file__'],
163 163 'server_url': server_url,
164 164 'make_lock': None,
165 165 'locked_by': [None, None]
166 166 }
167 167 #======================================================================
168 168 # MERCURIAL REQUEST HANDLING
169 169 #======================================================================
170 170 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
171 171 log.debug('Repository path is %s' % repo_path)
172 172
173 173 # CHECK LOCKING only if it's not ANONYMOUS USER
174 174 if username != User.DEFAULT_USER:
175 175 log.debug('Checking locking on repository')
176 176 (make_lock,
177 177 locked,
178 178 locked_by) = self._check_locking_state(
179 179 environ=environ, action=action,
180 180 repo=repo_name, user_id=user.user_id
181 181 )
182 182 # store the make_lock for later evaluation in hooks
183 183 extras.update({'make_lock': make_lock,
184 184 'locked_by': locked_by})
185 185
186 186 # set the environ variables for this request
187 187 os.environ['RC_SCM_DATA'] = json.dumps(extras)
188 188 fix_PATH()
189 189 log.debug('HOOKS extras is %s' % extras)
190 190 baseui = make_ui('db')
191 191 self.__inject_extras(repo_path, baseui, extras)
192 192
193 193 try:
194 194 # invalidate cache on push
195 195 if action == 'push':
196 196 self._invalidate_cache(repo_name)
197 log.info('%s action on HG repo "%s"' % (action, repo_name))
197 log.info('%s action on HG repo "%s" by "%s" from %s' %
198 (action, repo_name, username, ip_addr))
198 199 app = self.__make_app(repo_path, baseui, extras)
199 200 return app(environ, start_response)
200 201 except RepoError, e:
201 202 if str(e).find('not found') != -1:
202 203 return HTTPNotFound()(environ, start_response)
203 204 except HTTPLockedRC, e:
204 log.debug('Repositry LOCKED ret code 423!')
205 log.debug('Repository LOCKED ret code 423!')
205 206 return e(environ, start_response)
206 207 except Exception:
207 208 log.error(traceback.format_exc())
208 209 return HTTPInternalServerError()(environ, start_response)
209 210
210 211 def __make_app(self, repo_name, baseui, extras):
211 212 """
212 213 Make an wsgi application using hgweb, and inject generated baseui
213 214 instance, additionally inject some extras into ui object
214 215 """
215 216 return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
216 217
217 218 def __get_repository(self, environ):
218 219 """
219 220 Get's repository name out of PATH_INFO header
220 221
221 222 :param environ: environ where PATH_INFO is stored
222 223 """
223 224 try:
224 225 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
225 226 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
226 227 if repo_name.endswith('/'):
227 228 repo_name = repo_name.rstrip('/')
228 229 except:
229 230 log.error(traceback.format_exc())
230 231 raise
231 232
232 233 return repo_name
233 234
234 235 def __get_user(self, username):
235 236 return User.get_by_username(username)
236 237
237 238 def __get_action(self, environ):
238 239 """
239 240 Maps mercurial request commands into a clone,pull or push command.
240 241 This should always return a valid command string
241 242
242 243 :param environ:
243 244 """
244 245 mapping = {'changegroup': 'pull',
245 246 'changegroupsubset': 'pull',
246 247 'stream_out': 'pull',
247 248 'listkeys': 'pull',
248 249 'unbundle': 'push',
249 250 'pushkey': 'push', }
250 251 for qry in environ['QUERY_STRING'].split('&'):
251 252 if qry.startswith('cmd'):
252 253 cmd = qry.split('=')[-1]
253 254 if cmd in mapping:
254 255 return mapping[cmd]
255 256
256 257 return 'pull'
257 258
258 259 raise Exception('Unable to detect pull/push action !!'
259 260 'Are you using non standard command or client ?')
260 261
261 262 def __inject_extras(self, repo_path, baseui, extras={}):
262 263 """
263 264 Injects some extra params into baseui instance
264 265
265 266 also overwrites global settings with those takes from local hgrc file
266 267
267 268 :param baseui: baseui instance
268 269 :param extras: dict with extra params to put into baseui
269 270 """
270 271
271 272 hgrc = os.path.join(repo_path, '.hg', 'hgrc')
272 273
273 274 # make our hgweb quiet so it doesn't print output
274 275 baseui.setconfig('ui', 'quiet', 'true')
275 276
276 277 #inject some additional parameters that will be available in ui
277 278 #for hooks
278 279 for k, v in extras.items():
279 280 baseui.setconfig('rhodecode_extras', k, v)
280 281
281 282 repoui = make_ui('file', hgrc, False)
282 283
283 284 if repoui:
284 285 #overwrite our ui instance with the section from hgrc file
285 286 for section in ui_sections:
286 287 for k, v in repoui.configitems(section):
287 288 baseui.setconfig(section, k, v)
General Comments 0
You need to be logged in to leave comments. Login now