##// END OF EJS Templates
fix unicode issues on logging in SCM middlewares
marcink -
r3634:336184b9 beta
parent child Browse files
Show More
@@ -1,336 +1,337 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 _set_extras
84 84 from rhodecode.lib.base import BaseVCSController
85 85 from rhodecode.lib.auth import get_container_username
86 86 from rhodecode.lib.utils import is_valid_repo, make_ui
87 87 from rhodecode.lib.compat import json
88 88 from rhodecode.model.db import User, RhodeCodeUi
89 89
90 90 log = logging.getLogger(__name__)
91 91
92 92
93 93 GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
94 94
95 95
96 96 def is_git(environ):
97 97 path_info = environ['PATH_INFO']
98 98 isgit_path = GIT_PROTO_PAT.match(path_info)
99 99 log.debug('pathinfo: %s detected as GIT %s' % (
100 100 path_info, isgit_path != None)
101 101 )
102 102 return isgit_path
103 103
104 104
105 105 class SimpleGit(BaseVCSController):
106 106
107 107 def _handle_request(self, environ, start_response):
108 108 if not is_git(environ):
109 109 return self.application(environ, start_response)
110 110 if not self._check_ssl(environ, start_response):
111 111 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)
112 112
113 113 ip_addr = self._get_ip_addr(environ)
114 114 username = None
115 115 self._git_first_op = False
116 116 # skip passing error to error controller
117 117 environ['pylons.status_code_redirect'] = True
118 118
119 119 #======================================================================
120 120 # EXTRACT REPOSITORY NAME FROM ENV
121 121 #======================================================================
122 122 try:
123 123 repo_name = self.__get_repository(environ)
124 124 log.debug('Extracted repo name is %s' % repo_name)
125 125 except Exception:
126 126 return HTTPInternalServerError()(environ, start_response)
127 127
128 128 # quick check if that dir exists...
129 129 if not is_valid_repo(repo_name, self.basepath, 'git'):
130 130 return HTTPNotFound()(environ, start_response)
131 131
132 132 #======================================================================
133 133 # GET ACTION PULL or PUSH
134 134 #======================================================================
135 135 action = self.__get_action(environ)
136 136
137 137 #======================================================================
138 138 # CHECK ANONYMOUS PERMISSION
139 139 #======================================================================
140 140 if action in ['pull', 'push']:
141 141 anonymous_user = self.__get_user('default')
142 142 username = anonymous_user.username
143 143 anonymous_perm = self._check_permission(action, anonymous_user,
144 144 repo_name, ip_addr)
145 145
146 146 if not anonymous_perm or not anonymous_user.active:
147 147 if not anonymous_perm:
148 148 log.debug('Not enough credentials to access this '
149 149 'repository as anonymous user')
150 150 if not anonymous_user.active:
151 151 log.debug('Anonymous access is disabled, running '
152 152 'authentication')
153 153 #==============================================================
154 154 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
155 155 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
156 156 #==============================================================
157 157
158 158 # Attempting to retrieve username from the container
159 159 username = get_container_username(environ, self.config)
160 160
161 161 # If not authenticated by the container, running basic auth
162 162 if not username:
163 163 self.authenticate.realm = \
164 164 safe_str(self.config['rhodecode_realm'])
165 165 result = self.authenticate(environ)
166 166 if isinstance(result, str):
167 167 AUTH_TYPE.update(environ, 'basic')
168 168 REMOTE_USER.update(environ, result)
169 169 username = result
170 170 else:
171 171 return result.wsgi_application(environ, start_response)
172 172
173 173 #==============================================================
174 174 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
175 175 #==============================================================
176 176 try:
177 177 user = self.__get_user(username)
178 178 if user is None or not user.active:
179 179 return HTTPForbidden()(environ, start_response)
180 180 username = user.username
181 181 except Exception:
182 182 log.error(traceback.format_exc())
183 183 return HTTPInternalServerError()(environ, start_response)
184 184
185 185 #check permissions for this repository
186 186 perm = self._check_permission(action, user, repo_name, ip_addr)
187 187 if not perm:
188 188 return HTTPForbidden()(environ, start_response)
189 189
190 190 # extras are injected into UI object and later available
191 191 # in hooks executed by rhodecode
192 192 from rhodecode import CONFIG
193 193 server_url = get_server_url(environ)
194 194 extras = {
195 195 'ip': ip_addr,
196 196 'username': username,
197 197 'action': action,
198 198 'repository': repo_name,
199 199 'scm': 'git',
200 200 'config': CONFIG['__file__'],
201 201 'server_url': server_url,
202 202 'make_lock': None,
203 203 'locked_by': [None, None]
204 204 }
205 205
206 206 #===================================================================
207 207 # GIT REQUEST HANDLING
208 208 #===================================================================
209 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
209 str_repo_name = safe_str(repo_name)
210 repo_path = os.path.join(safe_str(self.basepath),str_repo_name)
210 211 log.debug('Repository path is %s' % repo_path)
211 212
212 213 # CHECK LOCKING only if it's not ANONYMOUS USER
213 214 if username != User.DEFAULT_USER:
214 215 log.debug('Checking locking on repository')
215 216 (make_lock,
216 217 locked,
217 218 locked_by) = self._check_locking_state(
218 219 environ=environ, action=action,
219 220 repo=repo_name, user_id=user.user_id
220 221 )
221 222 # store the make_lock for later evaluation in hooks
222 223 extras.update({'make_lock': make_lock,
223 224 'locked_by': locked_by})
224 225 # set the environ variables for this request
225 226 os.environ['RC_SCM_DATA'] = json.dumps(extras)
226 227 fix_PATH()
227 228 log.debug('HOOKS extras is %s' % extras)
228 229 baseui = make_ui('db')
229 230 self.__inject_extras(repo_path, baseui, extras)
230 231
231 232 try:
232 233 self._handle_githooks(repo_name, action, baseui, environ)
233 234 log.info('%s action on GIT repo "%s" by "%s" from %s' %
234 (action, repo_name, username, ip_addr))
235 (action, str_repo_name, safe_str(username), ip_addr))
235 236 app = self.__make_app(repo_name, repo_path, extras)
236 237 return app(environ, start_response)
237 238 except HTTPLockedRC, e:
238 239 _code = CONFIG.get('lock_ret_code')
239 240 log.debug('Repository LOCKED ret code %s!' % (_code))
240 241 return e(environ, start_response)
241 242 except Exception:
242 243 log.error(traceback.format_exc())
243 244 return HTTPInternalServerError()(environ, start_response)
244 245 finally:
245 246 # invalidate cache on push
246 247 if action == 'push':
247 248 self._invalidate_cache(repo_name)
248 249
249 250 def __make_app(self, repo_name, repo_path, extras):
250 251 """
251 252 Make an wsgi application using dulserver
252 253
253 254 :param repo_name: name of the repository
254 255 :param repo_path: full path to the repository
255 256 """
256 257
257 258 from rhodecode.lib.middleware.pygrack import make_wsgi_app
258 259 app = make_wsgi_app(
259 260 repo_root=safe_str(self.basepath),
260 261 repo_name=repo_name,
261 262 extras=extras,
262 263 )
263 264 app = GunzipFilter(LimitedInputFilter(app))
264 265 return app
265 266
266 267 def __get_repository(self, environ):
267 268 """
268 269 Get's repository name out of PATH_INFO header
269 270
270 271 :param environ: environ where PATH_INFO is stored
271 272 """
272 273 try:
273 274 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
274 275 repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
275 276 except Exception:
276 277 log.error(traceback.format_exc())
277 278 raise
278 279
279 280 return repo_name
280 281
281 282 def __get_user(self, username):
282 283 return User.get_by_username(username)
283 284
284 285 def __get_action(self, environ):
285 286 """
286 287 Maps git request commands into a pull or push command.
287 288
288 289 :param environ:
289 290 """
290 291 service = environ['QUERY_STRING'].split('=')
291 292
292 293 if len(service) > 1:
293 294 service_cmd = service[1]
294 295 mapping = {
295 296 'git-receive-pack': 'push',
296 297 'git-upload-pack': 'pull',
297 298 }
298 299 op = mapping[service_cmd]
299 300 self._git_stored_op = op
300 301 return op
301 302 else:
302 303 # try to fallback to stored variable as we don't know if the last
303 304 # operation is pull/push
304 305 op = getattr(self, '_git_stored_op', 'pull')
305 306 return op
306 307
307 308 def _handle_githooks(self, repo_name, action, baseui, environ):
308 309 """
309 310 Handles pull action, push is handled by post-receive hook
310 311 """
311 312 from rhodecode.lib.hooks import log_pull_action
312 313 service = environ['QUERY_STRING'].split('=')
313 314
314 315 if len(service) < 2:
315 316 return
316 317
317 318 from rhodecode.model.db import Repository
318 319 _repo = Repository.get_by_repo_name(repo_name)
319 320 _repo = _repo.scm_instance
320 321
321 322 _hooks = dict(baseui.configitems('hooks')) or {}
322 323 if action == 'pull':
323 324 # stupid git, emulate pre-pull hook !
324 325 pre_pull(ui=baseui, repo=_repo._repo)
325 326 if action == 'pull' and _hooks.get(RhodeCodeUi.HOOK_PULL):
326 327 log_pull_action(ui=baseui, repo=_repo._repo)
327 328
328 329 def __inject_extras(self, repo_path, baseui, extras={}):
329 330 """
330 331 Injects some extra params into baseui instance
331 332
332 333 :param baseui: baseui instance
333 334 :param extras: dict with extra params to put into baseui
334 335 """
335 336
336 337 _set_extras(extras)
@@ -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 _set_extras
40 40 from rhodecode.lib.base import BaseVCSController
41 41 from rhodecode.lib.auth import get_container_username
42 42 from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
43 43 from rhodecode.lib.compat import json
44 44 from rhodecode.model.db import User
45 45 from rhodecode.lib.exceptions import HTTPLockedRC
46 46
47 47
48 48 log = logging.getLogger(__name__)
49 49
50 50
51 51 def is_mercurial(environ):
52 52 """
53 53 Returns True if request's target is mercurial server - header
54 54 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
55 55 """
56 56 http_accept = environ.get('HTTP_ACCEPT')
57 57 path_info = environ['PATH_INFO']
58 58 if http_accept and http_accept.startswith('application/mercurial'):
59 59 ishg_path = True
60 60 else:
61 61 ishg_path = False
62 62
63 63 log.debug('pathinfo: %s detected as HG %s' % (
64 64 path_info, ishg_path)
65 65 )
66 66 return ishg_path
67 67
68 68
69 69 class SimpleHg(BaseVCSController):
70 70
71 71 def _handle_request(self, environ, start_response):
72 72 if not is_mercurial(environ):
73 73 return self.application(environ, start_response)
74 74 if not self._check_ssl(environ, start_response):
75 75 return HTTPNotAcceptable('SSL REQUIRED !')(environ, start_response)
76 76
77 77 ip_addr = self._get_ip_addr(environ)
78 78 username = None
79 79 # skip passing error to error controller
80 80 environ['pylons.status_code_redirect'] = True
81 81
82 82 #======================================================================
83 83 # EXTRACT REPOSITORY NAME FROM ENV
84 84 #======================================================================
85 85 try:
86 86 repo_name = environ['REPO_NAME'] = self.__get_repository(environ)
87 87 log.debug('Extracted repo name is %s' % repo_name)
88 88 except Exception:
89 89 return HTTPInternalServerError()(environ, start_response)
90 90
91 91 # quick check if that dir exists...
92 92 if not is_valid_repo(repo_name, self.basepath, 'hg'):
93 93 return HTTPNotFound()(environ, start_response)
94 94
95 95 #======================================================================
96 96 # GET ACTION PULL or PUSH
97 97 #======================================================================
98 98 action = self.__get_action(environ)
99 99
100 100 #======================================================================
101 101 # CHECK ANONYMOUS PERMISSION
102 102 #======================================================================
103 103 if action in ['pull', 'push']:
104 104 anonymous_user = self.__get_user('default')
105 105 username = anonymous_user.username
106 106 anonymous_perm = self._check_permission(action, anonymous_user,
107 107 repo_name, ip_addr)
108 108
109 109 if not anonymous_perm or not anonymous_user.active:
110 110 if not anonymous_perm:
111 111 log.debug('Not enough credentials to access this '
112 112 'repository as anonymous user')
113 113 if not anonymous_user.active:
114 114 log.debug('Anonymous access is disabled, running '
115 115 'authentication')
116 116 #==============================================================
117 117 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
118 118 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
119 119 #==============================================================
120 120
121 121 # Attempting to retrieve username from the container
122 122 username = get_container_username(environ, self.config)
123 123
124 124 # If not authenticated by the container, running basic auth
125 125 if not username:
126 126 self.authenticate.realm = \
127 127 safe_str(self.config['rhodecode_realm'])
128 128 result = self.authenticate(environ)
129 129 if isinstance(result, str):
130 130 AUTH_TYPE.update(environ, 'basic')
131 131 REMOTE_USER.update(environ, result)
132 132 username = result
133 133 else:
134 134 return result.wsgi_application(environ, start_response)
135 135
136 136 #==============================================================
137 137 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
138 138 #==============================================================
139 139 try:
140 140 user = self.__get_user(username)
141 141 if user is None or not user.active:
142 142 return HTTPForbidden()(environ, start_response)
143 143 username = user.username
144 144 except Exception:
145 145 log.error(traceback.format_exc())
146 146 return HTTPInternalServerError()(environ, start_response)
147 147
148 148 #check permissions for this repository
149 149 perm = self._check_permission(action, user, repo_name, ip_addr)
150 150 if not perm:
151 151 return HTTPForbidden()(environ, start_response)
152 152
153 153 # extras are injected into mercurial UI object and later available
154 154 # in hg hooks executed by rhodecode
155 155 from rhodecode import CONFIG
156 156 server_url = get_server_url(environ)
157 157 extras = {
158 158 'ip': ip_addr,
159 159 'username': username,
160 160 'action': action,
161 161 'repository': repo_name,
162 162 'scm': 'hg',
163 163 'config': CONFIG['__file__'],
164 164 'server_url': server_url,
165 165 'make_lock': None,
166 166 'locked_by': [None, None]
167 167 }
168 168 #======================================================================
169 169 # MERCURIAL REQUEST HANDLING
170 170 #======================================================================
171 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
171 str_repo_name = safe_str(repo_name)
172 repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
172 173 log.debug('Repository path is %s' % repo_path)
173 174
174 175 # CHECK LOCKING only if it's not ANONYMOUS USER
175 176 if username != User.DEFAULT_USER:
176 177 log.debug('Checking locking on repository')
177 178 (make_lock,
178 179 locked,
179 180 locked_by) = self._check_locking_state(
180 181 environ=environ, action=action,
181 182 repo=repo_name, user_id=user.user_id
182 183 )
183 184 # store the make_lock for later evaluation in hooks
184 185 extras.update({'make_lock': make_lock,
185 186 'locked_by': locked_by})
186 187
187 188 # set the environ variables for this request
188 189 os.environ['RC_SCM_DATA'] = json.dumps(extras)
189 190 fix_PATH()
190 191 log.debug('HOOKS extras is %s' % extras)
191 192 baseui = make_ui('db')
192 193 self.__inject_extras(repo_path, baseui, extras)
193 194
194 195 try:
195 196 log.info('%s action on HG repo "%s" by "%s" from %s' %
196 (action, repo_name, username, ip_addr))
197 (action, str_repo_name, safe_str(username), ip_addr))
197 198 app = self.__make_app(repo_path, baseui, extras)
198 199 return app(environ, start_response)
199 200 except RepoError, e:
200 201 if str(e).find('not found') != -1:
201 202 return HTTPNotFound()(environ, start_response)
202 203 except HTTPLockedRC, e:
203 204 _code = CONFIG.get('lock_ret_code')
204 205 log.debug('Repository LOCKED ret code %s!' % (_code))
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 finally:
210 211 # invalidate cache on push
211 212 if action == 'push':
212 213 self._invalidate_cache(repo_name)
213 214
214 215 def __make_app(self, repo_name, baseui, extras):
215 216 """
216 217 Make an wsgi application using hgweb, and inject generated baseui
217 218 instance, additionally inject some extras into ui object
218 219 """
219 220 return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
220 221
221 222 def __get_repository(self, environ):
222 223 """
223 224 Get's repository name out of PATH_INFO header
224 225
225 226 :param environ: environ where PATH_INFO is stored
226 227 """
227 228 try:
228 229 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
229 230 repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
230 231 if repo_name.endswith('/'):
231 232 repo_name = repo_name.rstrip('/')
232 233 except Exception:
233 234 log.error(traceback.format_exc())
234 235 raise
235 236
236 237 return repo_name
237 238
238 239 def __get_user(self, username):
239 240 return User.get_by_username(username)
240 241
241 242 def __get_action(self, environ):
242 243 """
243 244 Maps mercurial request commands into a clone,pull or push command.
244 245 This should always return a valid command string
245 246
246 247 :param environ:
247 248 """
248 249 mapping = {'changegroup': 'pull',
249 250 'changegroupsubset': 'pull',
250 251 'stream_out': 'pull',
251 252 'listkeys': 'pull',
252 253 'unbundle': 'push',
253 254 'pushkey': 'push', }
254 255 for qry in environ['QUERY_STRING'].split('&'):
255 256 if qry.startswith('cmd'):
256 257 cmd = qry.split('=')[-1]
257 258 if cmd in mapping:
258 259 return mapping[cmd]
259 260
260 261 return 'pull'
261 262
262 263 raise Exception('Unable to detect pull/push action !!'
263 264 'Are you using non standard command or client ?')
264 265
265 266 def __inject_extras(self, repo_path, baseui, extras={}):
266 267 """
267 268 Injects some extra params into baseui instance
268 269
269 270 also overwrites global settings with those takes from local hgrc file
270 271
271 272 :param baseui: baseui instance
272 273 :param extras: dict with extra params to put into baseui
273 274 """
274 275
275 276 hgrc = os.path.join(repo_path, '.hg', 'hgrc')
276 277
277 278 # make our hgweb quiet so it doesn't print output
278 279 baseui.setconfig('ui', 'quiet', 'true')
279 280
280 281 repoui = make_ui('file', hgrc, False)
281 282
282 283 if repoui:
283 284 #overwrite our ui instance with the section from hgrc file
284 285 for section in ui_sections:
285 286 for k, v in repoui.configitems(section):
286 287 baseui.setconfig(section, k, v)
287 288 _set_extras(extras)
General Comments 0
You need to be logged in to leave comments. Login now