##// END OF EJS Templates
configitems: register the 'web.address' config
Boris Feld -
r34225:af4f0c74 default
parent child Browse files
Show More
@@ -1,604 +1,607
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11
11
12 from . import (
12 from . import (
13 error,
13 error,
14 )
14 )
15
15
16 def loadconfigtable(ui, extname, configtable):
16 def loadconfigtable(ui, extname, configtable):
17 """update config item known to the ui with the extension ones"""
17 """update config item known to the ui with the extension ones"""
18 for section, items in configtable.items():
18 for section, items in configtable.items():
19 knownitems = ui._knownconfig.setdefault(section, {})
19 knownitems = ui._knownconfig.setdefault(section, {})
20 knownkeys = set(knownitems)
20 knownkeys = set(knownitems)
21 newkeys = set(items)
21 newkeys = set(items)
22 for key in sorted(knownkeys & newkeys):
22 for key in sorted(knownkeys & newkeys):
23 msg = "extension '%s' overwrite config item '%s.%s'"
23 msg = "extension '%s' overwrite config item '%s.%s'"
24 msg %= (extname, section, key)
24 msg %= (extname, section, key)
25 ui.develwarn(msg, config='warn-config')
25 ui.develwarn(msg, config='warn-config')
26
26
27 knownitems.update(items)
27 knownitems.update(items)
28
28
29 class configitem(object):
29 class configitem(object):
30 """represent a known config item
30 """represent a known config item
31
31
32 :section: the official config section where to find this item,
32 :section: the official config section where to find this item,
33 :name: the official name within the section,
33 :name: the official name within the section,
34 :default: default value for this item,
34 :default: default value for this item,
35 :alias: optional list of tuples as alternatives.
35 :alias: optional list of tuples as alternatives.
36 """
36 """
37
37
38 def __init__(self, section, name, default=None, alias=()):
38 def __init__(self, section, name, default=None, alias=()):
39 self.section = section
39 self.section = section
40 self.name = name
40 self.name = name
41 self.default = default
41 self.default = default
42 self.alias = list(alias)
42 self.alias = list(alias)
43
43
44 coreitems = {}
44 coreitems = {}
45
45
46 def _register(configtable, *args, **kwargs):
46 def _register(configtable, *args, **kwargs):
47 item = configitem(*args, **kwargs)
47 item = configitem(*args, **kwargs)
48 section = configtable.setdefault(item.section, {})
48 section = configtable.setdefault(item.section, {})
49 if item.name in section:
49 if item.name in section:
50 msg = "duplicated config item registration for '%s.%s'"
50 msg = "duplicated config item registration for '%s.%s'"
51 raise error.ProgrammingError(msg % (item.section, item.name))
51 raise error.ProgrammingError(msg % (item.section, item.name))
52 section[item.name] = item
52 section[item.name] = item
53
53
54 # special value for case where the default is derived from other values
54 # special value for case where the default is derived from other values
55 dynamicdefault = object()
55 dynamicdefault = object()
56
56
57 # Registering actual config items
57 # Registering actual config items
58
58
59 def getitemregister(configtable):
59 def getitemregister(configtable):
60 return functools.partial(_register, configtable)
60 return functools.partial(_register, configtable)
61
61
62 coreconfigitem = getitemregister(coreitems)
62 coreconfigitem = getitemregister(coreitems)
63
63
64 coreconfigitem('auth', 'cookiefile',
64 coreconfigitem('auth', 'cookiefile',
65 default=None,
65 default=None,
66 )
66 )
67 # bookmarks.pushing: internal hack for discovery
67 # bookmarks.pushing: internal hack for discovery
68 coreconfigitem('bookmarks', 'pushing',
68 coreconfigitem('bookmarks', 'pushing',
69 default=list,
69 default=list,
70 )
70 )
71 # bundle.mainreporoot: internal hack for bundlerepo
71 # bundle.mainreporoot: internal hack for bundlerepo
72 coreconfigitem('bundle', 'mainreporoot',
72 coreconfigitem('bundle', 'mainreporoot',
73 default='',
73 default='',
74 )
74 )
75 # bundle.reorder: experimental config
75 # bundle.reorder: experimental config
76 coreconfigitem('bundle', 'reorder',
76 coreconfigitem('bundle', 'reorder',
77 default='auto',
77 default='auto',
78 )
78 )
79 coreconfigitem('censor', 'policy',
79 coreconfigitem('censor', 'policy',
80 default='abort',
80 default='abort',
81 )
81 )
82 coreconfigitem('chgserver', 'idletimeout',
82 coreconfigitem('chgserver', 'idletimeout',
83 default=3600,
83 default=3600,
84 )
84 )
85 coreconfigitem('chgserver', 'skiphash',
85 coreconfigitem('chgserver', 'skiphash',
86 default=False,
86 default=False,
87 )
87 )
88 coreconfigitem('cmdserver', 'log',
88 coreconfigitem('cmdserver', 'log',
89 default=None,
89 default=None,
90 )
90 )
91 coreconfigitem('color', 'mode',
91 coreconfigitem('color', 'mode',
92 default='auto',
92 default='auto',
93 )
93 )
94 coreconfigitem('color', 'pagermode',
94 coreconfigitem('color', 'pagermode',
95 default=dynamicdefault,
95 default=dynamicdefault,
96 )
96 )
97 coreconfigitem('commands', 'status.relative',
97 coreconfigitem('commands', 'status.relative',
98 default=False,
98 default=False,
99 )
99 )
100 coreconfigitem('commands', 'status.skipstates',
100 coreconfigitem('commands', 'status.skipstates',
101 default=[],
101 default=[],
102 )
102 )
103 coreconfigitem('commands', 'status.verbose',
103 coreconfigitem('commands', 'status.verbose',
104 default=False,
104 default=False,
105 )
105 )
106 coreconfigitem('commands', 'update.requiredest',
106 coreconfigitem('commands', 'update.requiredest',
107 default=False,
107 default=False,
108 )
108 )
109 coreconfigitem('devel', 'all-warnings',
109 coreconfigitem('devel', 'all-warnings',
110 default=False,
110 default=False,
111 )
111 )
112 coreconfigitem('devel', 'bundle2.debug',
112 coreconfigitem('devel', 'bundle2.debug',
113 default=False,
113 default=False,
114 )
114 )
115 coreconfigitem('devel', 'check-locks',
115 coreconfigitem('devel', 'check-locks',
116 default=False,
116 default=False,
117 )
117 )
118 coreconfigitem('devel', 'check-relroot',
118 coreconfigitem('devel', 'check-relroot',
119 default=False,
119 default=False,
120 )
120 )
121 coreconfigitem('devel', 'default-date',
121 coreconfigitem('devel', 'default-date',
122 default=None,
122 default=None,
123 )
123 )
124 coreconfigitem('devel', 'deprec-warn',
124 coreconfigitem('devel', 'deprec-warn',
125 default=False,
125 default=False,
126 )
126 )
127 coreconfigitem('devel', 'disableloaddefaultcerts',
127 coreconfigitem('devel', 'disableloaddefaultcerts',
128 default=False,
128 default=False,
129 )
129 )
130 coreconfigitem('devel', 'legacy.exchange',
130 coreconfigitem('devel', 'legacy.exchange',
131 default=list,
131 default=list,
132 )
132 )
133 coreconfigitem('devel', 'servercafile',
133 coreconfigitem('devel', 'servercafile',
134 default='',
134 default='',
135 )
135 )
136 coreconfigitem('devel', 'serverexactprotocol',
136 coreconfigitem('devel', 'serverexactprotocol',
137 default='',
137 default='',
138 )
138 )
139 coreconfigitem('devel', 'serverrequirecert',
139 coreconfigitem('devel', 'serverrequirecert',
140 default=False,
140 default=False,
141 )
141 )
142 coreconfigitem('devel', 'strip-obsmarkers',
142 coreconfigitem('devel', 'strip-obsmarkers',
143 default=True,
143 default=True,
144 )
144 )
145 coreconfigitem('email', 'charsets',
145 coreconfigitem('email', 'charsets',
146 default=list,
146 default=list,
147 )
147 )
148 coreconfigitem('email', 'method',
148 coreconfigitem('email', 'method',
149 default='smtp',
149 default='smtp',
150 )
150 )
151 coreconfigitem('experimental', 'bundle-phases',
151 coreconfigitem('experimental', 'bundle-phases',
152 default=False,
152 default=False,
153 )
153 )
154 coreconfigitem('experimental', 'bundle2-advertise',
154 coreconfigitem('experimental', 'bundle2-advertise',
155 default=True,
155 default=True,
156 )
156 )
157 coreconfigitem('experimental', 'bundle2-output-capture',
157 coreconfigitem('experimental', 'bundle2-output-capture',
158 default=False,
158 default=False,
159 )
159 )
160 coreconfigitem('experimental', 'bundle2.pushback',
160 coreconfigitem('experimental', 'bundle2.pushback',
161 default=False,
161 default=False,
162 )
162 )
163 coreconfigitem('experimental', 'bundle2lazylocking',
163 coreconfigitem('experimental', 'bundle2lazylocking',
164 default=False,
164 default=False,
165 )
165 )
166 coreconfigitem('experimental', 'bundlecomplevel',
166 coreconfigitem('experimental', 'bundlecomplevel',
167 default=None,
167 default=None,
168 )
168 )
169 coreconfigitem('experimental', 'changegroup3',
169 coreconfigitem('experimental', 'changegroup3',
170 default=False,
170 default=False,
171 )
171 )
172 coreconfigitem('experimental', 'clientcompressionengines',
172 coreconfigitem('experimental', 'clientcompressionengines',
173 default=list,
173 default=list,
174 )
174 )
175 coreconfigitem('experimental', 'copytrace',
175 coreconfigitem('experimental', 'copytrace',
176 default='on',
176 default='on',
177 )
177 )
178 coreconfigitem('experimental', 'crecordtest',
178 coreconfigitem('experimental', 'crecordtest',
179 default=None,
179 default=None,
180 )
180 )
181 coreconfigitem('experimental', 'editortmpinhg',
181 coreconfigitem('experimental', 'editortmpinhg',
182 default=False,
182 default=False,
183 )
183 )
184 coreconfigitem('experimental', 'stabilization',
184 coreconfigitem('experimental', 'stabilization',
185 default=list,
185 default=list,
186 alias=[('experimental', 'evolution')],
186 alias=[('experimental', 'evolution')],
187 )
187 )
188 coreconfigitem('experimental', 'stabilization.bundle-obsmarker',
188 coreconfigitem('experimental', 'stabilization.bundle-obsmarker',
189 default=False,
189 default=False,
190 alias=[('experimental', 'evolution.bundle-obsmarker')],
190 alias=[('experimental', 'evolution.bundle-obsmarker')],
191 )
191 )
192 coreconfigitem('experimental', 'stabilization.track-operation',
192 coreconfigitem('experimental', 'stabilization.track-operation',
193 default=False,
193 default=False,
194 alias=[('experimental', 'evolution.track-operation')]
194 alias=[('experimental', 'evolution.track-operation')]
195 )
195 )
196 coreconfigitem('experimental', 'exportableenviron',
196 coreconfigitem('experimental', 'exportableenviron',
197 default=list,
197 default=list,
198 )
198 )
199 coreconfigitem('experimental', 'extendedheader.index',
199 coreconfigitem('experimental', 'extendedheader.index',
200 default=None,
200 default=None,
201 )
201 )
202 coreconfigitem('experimental', 'extendedheader.similarity',
202 coreconfigitem('experimental', 'extendedheader.similarity',
203 default=False,
203 default=False,
204 )
204 )
205 coreconfigitem('experimental', 'format.compression',
205 coreconfigitem('experimental', 'format.compression',
206 default='zlib',
206 default='zlib',
207 )
207 )
208 coreconfigitem('experimental', 'graphshorten',
208 coreconfigitem('experimental', 'graphshorten',
209 default=False,
209 default=False,
210 )
210 )
211 coreconfigitem('experimental', 'hook-track-tags',
211 coreconfigitem('experimental', 'hook-track-tags',
212 default=False,
212 default=False,
213 )
213 )
214 coreconfigitem('experimental', 'httppostargs',
214 coreconfigitem('experimental', 'httppostargs',
215 default=False,
215 default=False,
216 )
216 )
217 coreconfigitem('experimental', 'manifestv2',
217 coreconfigitem('experimental', 'manifestv2',
218 default=False,
218 default=False,
219 )
219 )
220 coreconfigitem('experimental', 'mergedriver',
220 coreconfigitem('experimental', 'mergedriver',
221 default=None,
221 default=None,
222 )
222 )
223 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
223 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
224 default=False,
224 default=False,
225 )
225 )
226 coreconfigitem('experimental', 'rebase.multidest',
226 coreconfigitem('experimental', 'rebase.multidest',
227 default=False,
227 default=False,
228 )
228 )
229 coreconfigitem('experimental', 'revertalternateinteractivemode',
229 coreconfigitem('experimental', 'revertalternateinteractivemode',
230 default=True,
230 default=True,
231 )
231 )
232 coreconfigitem('experimental', 'revlogv2',
232 coreconfigitem('experimental', 'revlogv2',
233 default=None,
233 default=None,
234 )
234 )
235 coreconfigitem('experimental', 'spacemovesdown',
235 coreconfigitem('experimental', 'spacemovesdown',
236 default=False,
236 default=False,
237 )
237 )
238 coreconfigitem('experimental', 'treemanifest',
238 coreconfigitem('experimental', 'treemanifest',
239 default=False,
239 default=False,
240 )
240 )
241 coreconfigitem('experimental', 'updatecheck',
241 coreconfigitem('experimental', 'updatecheck',
242 default=None,
242 default=None,
243 )
243 )
244 coreconfigitem('format', 'aggressivemergedeltas',
244 coreconfigitem('format', 'aggressivemergedeltas',
245 default=False,
245 default=False,
246 )
246 )
247 coreconfigitem('format', 'chunkcachesize',
247 coreconfigitem('format', 'chunkcachesize',
248 default=None,
248 default=None,
249 )
249 )
250 coreconfigitem('format', 'dotencode',
250 coreconfigitem('format', 'dotencode',
251 default=True,
251 default=True,
252 )
252 )
253 coreconfigitem('format', 'generaldelta',
253 coreconfigitem('format', 'generaldelta',
254 default=False,
254 default=False,
255 )
255 )
256 coreconfigitem('format', 'manifestcachesize',
256 coreconfigitem('format', 'manifestcachesize',
257 default=None,
257 default=None,
258 )
258 )
259 coreconfigitem('format', 'maxchainlen',
259 coreconfigitem('format', 'maxchainlen',
260 default=None,
260 default=None,
261 )
261 )
262 coreconfigitem('format', 'obsstore-version',
262 coreconfigitem('format', 'obsstore-version',
263 default=None,
263 default=None,
264 )
264 )
265 coreconfigitem('format', 'usefncache',
265 coreconfigitem('format', 'usefncache',
266 default=True,
266 default=True,
267 )
267 )
268 coreconfigitem('format', 'usegeneraldelta',
268 coreconfigitem('format', 'usegeneraldelta',
269 default=True,
269 default=True,
270 )
270 )
271 coreconfigitem('format', 'usestore',
271 coreconfigitem('format', 'usestore',
272 default=True,
272 default=True,
273 )
273 )
274 coreconfigitem('hostsecurity', 'ciphers',
274 coreconfigitem('hostsecurity', 'ciphers',
275 default=None,
275 default=None,
276 )
276 )
277 coreconfigitem('hostsecurity', 'disabletls10warning',
277 coreconfigitem('hostsecurity', 'disabletls10warning',
278 default=False,
278 default=False,
279 )
279 )
280 coreconfigitem('http_proxy', 'always',
280 coreconfigitem('http_proxy', 'always',
281 default=False,
281 default=False,
282 )
282 )
283 coreconfigitem('http_proxy', 'host',
283 coreconfigitem('http_proxy', 'host',
284 default=None,
284 default=None,
285 )
285 )
286 coreconfigitem('http_proxy', 'no',
286 coreconfigitem('http_proxy', 'no',
287 default=list,
287 default=list,
288 )
288 )
289 coreconfigitem('http_proxy', 'passwd',
289 coreconfigitem('http_proxy', 'passwd',
290 default=None,
290 default=None,
291 )
291 )
292 coreconfigitem('http_proxy', 'user',
292 coreconfigitem('http_proxy', 'user',
293 default=None,
293 default=None,
294 )
294 )
295 coreconfigitem('merge', 'followcopies',
295 coreconfigitem('merge', 'followcopies',
296 default=True,
296 default=True,
297 )
297 )
298 coreconfigitem('pager', 'ignore',
298 coreconfigitem('pager', 'ignore',
299 default=list,
299 default=list,
300 )
300 )
301 coreconfigitem('patch', 'eol',
301 coreconfigitem('patch', 'eol',
302 default='strict',
302 default='strict',
303 )
303 )
304 coreconfigitem('patch', 'fuzz',
304 coreconfigitem('patch', 'fuzz',
305 default=2,
305 default=2,
306 )
306 )
307 coreconfigitem('paths', 'default',
307 coreconfigitem('paths', 'default',
308 default=None,
308 default=None,
309 )
309 )
310 coreconfigitem('paths', 'default-push',
310 coreconfigitem('paths', 'default-push',
311 default=None,
311 default=None,
312 )
312 )
313 coreconfigitem('phases', 'checksubrepos',
313 coreconfigitem('phases', 'checksubrepos',
314 default='follow',
314 default='follow',
315 )
315 )
316 coreconfigitem('phases', 'publish',
316 coreconfigitem('phases', 'publish',
317 default=True,
317 default=True,
318 )
318 )
319 coreconfigitem('profiling', 'enabled',
319 coreconfigitem('profiling', 'enabled',
320 default=False,
320 default=False,
321 )
321 )
322 coreconfigitem('profiling', 'format',
322 coreconfigitem('profiling', 'format',
323 default='text',
323 default='text',
324 )
324 )
325 coreconfigitem('profiling', 'freq',
325 coreconfigitem('profiling', 'freq',
326 default=1000,
326 default=1000,
327 )
327 )
328 coreconfigitem('profiling', 'limit',
328 coreconfigitem('profiling', 'limit',
329 default=30,
329 default=30,
330 )
330 )
331 coreconfigitem('profiling', 'nested',
331 coreconfigitem('profiling', 'nested',
332 default=0,
332 default=0,
333 )
333 )
334 coreconfigitem('profiling', 'sort',
334 coreconfigitem('profiling', 'sort',
335 default='inlinetime',
335 default='inlinetime',
336 )
336 )
337 coreconfigitem('profiling', 'statformat',
337 coreconfigitem('profiling', 'statformat',
338 default='hotpath',
338 default='hotpath',
339 )
339 )
340 coreconfigitem('progress', 'assume-tty',
340 coreconfigitem('progress', 'assume-tty',
341 default=False,
341 default=False,
342 )
342 )
343 coreconfigitem('progress', 'changedelay',
343 coreconfigitem('progress', 'changedelay',
344 default=1,
344 default=1,
345 )
345 )
346 coreconfigitem('progress', 'clear-complete',
346 coreconfigitem('progress', 'clear-complete',
347 default=True,
347 default=True,
348 )
348 )
349 coreconfigitem('progress', 'debug',
349 coreconfigitem('progress', 'debug',
350 default=False,
350 default=False,
351 )
351 )
352 coreconfigitem('progress', 'delay',
352 coreconfigitem('progress', 'delay',
353 default=3,
353 default=3,
354 )
354 )
355 coreconfigitem('progress', 'disable',
355 coreconfigitem('progress', 'disable',
356 default=False,
356 default=False,
357 )
357 )
358 coreconfigitem('progress', 'estimate',
358 coreconfigitem('progress', 'estimate',
359 default=2,
359 default=2,
360 )
360 )
361 coreconfigitem('progress', 'refresh',
361 coreconfigitem('progress', 'refresh',
362 default=0.1,
362 default=0.1,
363 )
363 )
364 coreconfigitem('progress', 'width',
364 coreconfigitem('progress', 'width',
365 default=dynamicdefault,
365 default=dynamicdefault,
366 )
366 )
367 coreconfigitem('push', 'pushvars.server',
367 coreconfigitem('push', 'pushvars.server',
368 default=False,
368 default=False,
369 )
369 )
370 coreconfigitem('server', 'bundle1',
370 coreconfigitem('server', 'bundle1',
371 default=True,
371 default=True,
372 )
372 )
373 coreconfigitem('server', 'bundle1gd',
373 coreconfigitem('server', 'bundle1gd',
374 default=None,
374 default=None,
375 )
375 )
376 coreconfigitem('server', 'compressionengines',
376 coreconfigitem('server', 'compressionengines',
377 default=list,
377 default=list,
378 )
378 )
379 coreconfigitem('server', 'concurrent-push-mode',
379 coreconfigitem('server', 'concurrent-push-mode',
380 default='strict',
380 default='strict',
381 )
381 )
382 coreconfigitem('server', 'disablefullbundle',
382 coreconfigitem('server', 'disablefullbundle',
383 default=False,
383 default=False,
384 )
384 )
385 coreconfigitem('server', 'maxhttpheaderlen',
385 coreconfigitem('server', 'maxhttpheaderlen',
386 default=1024,
386 default=1024,
387 )
387 )
388 coreconfigitem('server', 'preferuncompressed',
388 coreconfigitem('server', 'preferuncompressed',
389 default=False,
389 default=False,
390 )
390 )
391 coreconfigitem('server', 'uncompressed',
391 coreconfigitem('server', 'uncompressed',
392 default=True,
392 default=True,
393 )
393 )
394 coreconfigitem('server', 'uncompressedallowsecret',
394 coreconfigitem('server', 'uncompressedallowsecret',
395 default=False,
395 default=False,
396 )
396 )
397 coreconfigitem('server', 'validate',
397 coreconfigitem('server', 'validate',
398 default=False,
398 default=False,
399 )
399 )
400 coreconfigitem('server', 'zliblevel',
400 coreconfigitem('server', 'zliblevel',
401 default=-1,
401 default=-1,
402 )
402 )
403 coreconfigitem('smtp', 'host',
403 coreconfigitem('smtp', 'host',
404 default=None,
404 default=None,
405 )
405 )
406 coreconfigitem('smtp', 'local_hostname',
406 coreconfigitem('smtp', 'local_hostname',
407 default=None,
407 default=None,
408 )
408 )
409 coreconfigitem('smtp', 'password',
409 coreconfigitem('smtp', 'password',
410 default=None,
410 default=None,
411 )
411 )
412 coreconfigitem('smtp', 'tls',
412 coreconfigitem('smtp', 'tls',
413 default='none',
413 default='none',
414 )
414 )
415 coreconfigitem('smtp', 'username',
415 coreconfigitem('smtp', 'username',
416 default=None,
416 default=None,
417 )
417 )
418 coreconfigitem('sparse', 'missingwarning',
418 coreconfigitem('sparse', 'missingwarning',
419 default=True,
419 default=True,
420 )
420 )
421 coreconfigitem('trusted', 'groups',
421 coreconfigitem('trusted', 'groups',
422 default=list,
422 default=list,
423 )
423 )
424 coreconfigitem('trusted', 'users',
424 coreconfigitem('trusted', 'users',
425 default=list,
425 default=list,
426 )
426 )
427 coreconfigitem('ui', '_usedassubrepo',
427 coreconfigitem('ui', '_usedassubrepo',
428 default=False,
428 default=False,
429 )
429 )
430 coreconfigitem('ui', 'allowemptycommit',
430 coreconfigitem('ui', 'allowemptycommit',
431 default=False,
431 default=False,
432 )
432 )
433 coreconfigitem('ui', 'archivemeta',
433 coreconfigitem('ui', 'archivemeta',
434 default=True,
434 default=True,
435 )
435 )
436 coreconfigitem('ui', 'askusername',
436 coreconfigitem('ui', 'askusername',
437 default=False,
437 default=False,
438 )
438 )
439 coreconfigitem('ui', 'clonebundlefallback',
439 coreconfigitem('ui', 'clonebundlefallback',
440 default=False,
440 default=False,
441 )
441 )
442 coreconfigitem('ui', 'clonebundleprefers',
442 coreconfigitem('ui', 'clonebundleprefers',
443 default=list,
443 default=list,
444 )
444 )
445 coreconfigitem('ui', 'clonebundles',
445 coreconfigitem('ui', 'clonebundles',
446 default=True,
446 default=True,
447 )
447 )
448 coreconfigitem('ui', 'color',
448 coreconfigitem('ui', 'color',
449 default='auto',
449 default='auto',
450 )
450 )
451 coreconfigitem('ui', 'commitsubrepos',
451 coreconfigitem('ui', 'commitsubrepos',
452 default=False,
452 default=False,
453 )
453 )
454 coreconfigitem('ui', 'debug',
454 coreconfigitem('ui', 'debug',
455 default=False,
455 default=False,
456 )
456 )
457 coreconfigitem('ui', 'debugger',
457 coreconfigitem('ui', 'debugger',
458 default=None,
458 default=None,
459 )
459 )
460 coreconfigitem('ui', 'fallbackencoding',
460 coreconfigitem('ui', 'fallbackencoding',
461 default=None,
461 default=None,
462 )
462 )
463 coreconfigitem('ui', 'forcecwd',
463 coreconfigitem('ui', 'forcecwd',
464 default=None,
464 default=None,
465 )
465 )
466 coreconfigitem('ui', 'forcemerge',
466 coreconfigitem('ui', 'forcemerge',
467 default=None,
467 default=None,
468 )
468 )
469 coreconfigitem('ui', 'formatdebug',
469 coreconfigitem('ui', 'formatdebug',
470 default=False,
470 default=False,
471 )
471 )
472 coreconfigitem('ui', 'formatjson',
472 coreconfigitem('ui', 'formatjson',
473 default=False,
473 default=False,
474 )
474 )
475 coreconfigitem('ui', 'formatted',
475 coreconfigitem('ui', 'formatted',
476 default=None,
476 default=None,
477 )
477 )
478 coreconfigitem('ui', 'graphnodetemplate',
478 coreconfigitem('ui', 'graphnodetemplate',
479 default=None,
479 default=None,
480 )
480 )
481 coreconfigitem('ui', 'http2debuglevel',
481 coreconfigitem('ui', 'http2debuglevel',
482 default=None,
482 default=None,
483 )
483 )
484 coreconfigitem('ui', 'interactive',
484 coreconfigitem('ui', 'interactive',
485 default=None,
485 default=None,
486 )
486 )
487 coreconfigitem('ui', 'interface',
487 coreconfigitem('ui', 'interface',
488 default=None,
488 default=None,
489 )
489 )
490 coreconfigitem('ui', 'logblockedtimes',
490 coreconfigitem('ui', 'logblockedtimes',
491 default=False,
491 default=False,
492 )
492 )
493 coreconfigitem('ui', 'logtemplate',
493 coreconfigitem('ui', 'logtemplate',
494 default=None,
494 default=None,
495 )
495 )
496 coreconfigitem('ui', 'merge',
496 coreconfigitem('ui', 'merge',
497 default=None,
497 default=None,
498 )
498 )
499 coreconfigitem('ui', 'mergemarkers',
499 coreconfigitem('ui', 'mergemarkers',
500 default='basic',
500 default='basic',
501 )
501 )
502 coreconfigitem('ui', 'mergemarkertemplate',
502 coreconfigitem('ui', 'mergemarkertemplate',
503 default=('{node|short} '
503 default=('{node|short} '
504 '{ifeq(tags, "tip", "", '
504 '{ifeq(tags, "tip", "", '
505 'ifeq(tags, "", "", "{tags} "))}'
505 'ifeq(tags, "", "", "{tags} "))}'
506 '{if(bookmarks, "{bookmarks} ")}'
506 '{if(bookmarks, "{bookmarks} ")}'
507 '{ifeq(branch, "default", "", "{branch} ")}'
507 '{ifeq(branch, "default", "", "{branch} ")}'
508 '- {author|user}: {desc|firstline}')
508 '- {author|user}: {desc|firstline}')
509 )
509 )
510 coreconfigitem('ui', 'nontty',
510 coreconfigitem('ui', 'nontty',
511 default=False,
511 default=False,
512 )
512 )
513 coreconfigitem('ui', 'origbackuppath',
513 coreconfigitem('ui', 'origbackuppath',
514 default=None,
514 default=None,
515 )
515 )
516 coreconfigitem('ui', 'paginate',
516 coreconfigitem('ui', 'paginate',
517 default=True,
517 default=True,
518 )
518 )
519 coreconfigitem('ui', 'patch',
519 coreconfigitem('ui', 'patch',
520 default=None,
520 default=None,
521 )
521 )
522 coreconfigitem('ui', 'portablefilenames',
522 coreconfigitem('ui', 'portablefilenames',
523 default='warn',
523 default='warn',
524 )
524 )
525 coreconfigitem('ui', 'promptecho',
525 coreconfigitem('ui', 'promptecho',
526 default=False,
526 default=False,
527 )
527 )
528 coreconfigitem('ui', 'quiet',
528 coreconfigitem('ui', 'quiet',
529 default=False,
529 default=False,
530 )
530 )
531 coreconfigitem('ui', 'quietbookmarkmove',
531 coreconfigitem('ui', 'quietbookmarkmove',
532 default=False,
532 default=False,
533 )
533 )
534 coreconfigitem('ui', 'remotecmd',
534 coreconfigitem('ui', 'remotecmd',
535 default='hg',
535 default='hg',
536 )
536 )
537 coreconfigitem('ui', 'report_untrusted',
537 coreconfigitem('ui', 'report_untrusted',
538 default=True,
538 default=True,
539 )
539 )
540 coreconfigitem('ui', 'rollback',
540 coreconfigitem('ui', 'rollback',
541 default=True,
541 default=True,
542 )
542 )
543 coreconfigitem('ui', 'slash',
543 coreconfigitem('ui', 'slash',
544 default=False,
544 default=False,
545 )
545 )
546 coreconfigitem('ui', 'ssh',
546 coreconfigitem('ui', 'ssh',
547 default='ssh',
547 default='ssh',
548 )
548 )
549 coreconfigitem('ui', 'statuscopies',
549 coreconfigitem('ui', 'statuscopies',
550 default=False,
550 default=False,
551 )
551 )
552 coreconfigitem('ui', 'strict',
552 coreconfigitem('ui', 'strict',
553 default=False,
553 default=False,
554 )
554 )
555 coreconfigitem('ui', 'style',
555 coreconfigitem('ui', 'style',
556 default='',
556 default='',
557 )
557 )
558 coreconfigitem('ui', 'supportcontact',
558 coreconfigitem('ui', 'supportcontact',
559 default=None,
559 default=None,
560 )
560 )
561 coreconfigitem('ui', 'textwidth',
561 coreconfigitem('ui', 'textwidth',
562 default=78,
562 default=78,
563 )
563 )
564 coreconfigitem('ui', 'timeout',
564 coreconfigitem('ui', 'timeout',
565 default='600',
565 default='600',
566 )
566 )
567 coreconfigitem('ui', 'traceback',
567 coreconfigitem('ui', 'traceback',
568 default=False,
568 default=False,
569 )
569 )
570 coreconfigitem('ui', 'tweakdefaults',
570 coreconfigitem('ui', 'tweakdefaults',
571 default=False,
571 default=False,
572 )
572 )
573 coreconfigitem('ui', 'usehttp2',
573 coreconfigitem('ui', 'usehttp2',
574 default=False,
574 default=False,
575 )
575 )
576 coreconfigitem('ui', 'username',
576 coreconfigitem('ui', 'username',
577 alias=[('ui', 'user')]
577 alias=[('ui', 'user')]
578 )
578 )
579 coreconfigitem('ui', 'verbose',
579 coreconfigitem('ui', 'verbose',
580 default=False,
580 default=False,
581 )
581 )
582 coreconfigitem('verify', 'skipflags',
582 coreconfigitem('verify', 'skipflags',
583 default=None,
583 default=None,
584 )
584 )
585 coreconfigitem('web', 'accesslog',
585 coreconfigitem('web', 'accesslog',
586 default='-',
586 default='-',
587 )
587 )
588 coreconfigitem('web', 'address',
589 default='',
590 )
588 coreconfigitem('worker', 'backgroundclose',
591 coreconfigitem('worker', 'backgroundclose',
589 default=dynamicdefault,
592 default=dynamicdefault,
590 )
593 )
591 # Windows defaults to a limit of 512 open files. A buffer of 128
594 # Windows defaults to a limit of 512 open files. A buffer of 128
592 # should give us enough headway.
595 # should give us enough headway.
593 coreconfigitem('worker', 'backgroundclosemaxqueue',
596 coreconfigitem('worker', 'backgroundclosemaxqueue',
594 default=384,
597 default=384,
595 )
598 )
596 coreconfigitem('worker', 'backgroundcloseminfilecount',
599 coreconfigitem('worker', 'backgroundcloseminfilecount',
597 default=2048,
600 default=2048,
598 )
601 )
599 coreconfigitem('worker', 'backgroundclosethreadcount',
602 coreconfigitem('worker', 'backgroundclosethreadcount',
600 default=4,
603 default=4,
601 )
604 )
602 coreconfigitem('worker', 'numcpus',
605 coreconfigitem('worker', 'numcpus',
603 default=None,
606 default=None,
604 )
607 )
@@ -1,335 +1,335
1 # hgweb/server.py - The standalone hg web server.
1 # hgweb/server.py - The standalone hg web server.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import errno
11 import errno
12 import os
12 import os
13 import socket
13 import socket
14 import sys
14 import sys
15 import traceback
15 import traceback
16
16
17 from ..i18n import _
17 from ..i18n import _
18
18
19 from .. import (
19 from .. import (
20 error,
20 error,
21 pycompat,
21 pycompat,
22 util,
22 util,
23 )
23 )
24
24
25 httpservermod = util.httpserver
25 httpservermod = util.httpserver
26 socketserver = util.socketserver
26 socketserver = util.socketserver
27 urlerr = util.urlerr
27 urlerr = util.urlerr
28 urlreq = util.urlreq
28 urlreq = util.urlreq
29
29
30 from . import (
30 from . import (
31 common,
31 common,
32 )
32 )
33
33
34 def _splitURI(uri):
34 def _splitURI(uri):
35 """Return path and query that has been split from uri
35 """Return path and query that has been split from uri
36
36
37 Just like CGI environment, the path is unquoted, the query is
37 Just like CGI environment, the path is unquoted, the query is
38 not.
38 not.
39 """
39 """
40 if '?' in uri:
40 if '?' in uri:
41 path, query = uri.split('?', 1)
41 path, query = uri.split('?', 1)
42 else:
42 else:
43 path, query = uri, ''
43 path, query = uri, ''
44 return urlreq.unquote(path), query
44 return urlreq.unquote(path), query
45
45
46 class _error_logger(object):
46 class _error_logger(object):
47 def __init__(self, handler):
47 def __init__(self, handler):
48 self.handler = handler
48 self.handler = handler
49 def flush(self):
49 def flush(self):
50 pass
50 pass
51 def write(self, str):
51 def write(self, str):
52 self.writelines(str.split('\n'))
52 self.writelines(str.split('\n'))
53 def writelines(self, seq):
53 def writelines(self, seq):
54 for msg in seq:
54 for msg in seq:
55 self.handler.log_error("HG error: %s", msg)
55 self.handler.log_error("HG error: %s", msg)
56
56
57 class _httprequesthandler(httpservermod.basehttprequesthandler):
57 class _httprequesthandler(httpservermod.basehttprequesthandler):
58
58
59 url_scheme = 'http'
59 url_scheme = 'http'
60
60
61 @staticmethod
61 @staticmethod
62 def preparehttpserver(httpserver, ui):
62 def preparehttpserver(httpserver, ui):
63 """Prepare .socket of new HTTPServer instance"""
63 """Prepare .socket of new HTTPServer instance"""
64 pass
64 pass
65
65
66 def __init__(self, *args, **kargs):
66 def __init__(self, *args, **kargs):
67 self.protocol_version = 'HTTP/1.1'
67 self.protocol_version = 'HTTP/1.1'
68 httpservermod.basehttprequesthandler.__init__(self, *args, **kargs)
68 httpservermod.basehttprequesthandler.__init__(self, *args, **kargs)
69
69
70 def _log_any(self, fp, format, *args):
70 def _log_any(self, fp, format, *args):
71 fp.write("%s - - [%s] %s\n" % (self.client_address[0],
71 fp.write("%s - - [%s] %s\n" % (self.client_address[0],
72 self.log_date_time_string(),
72 self.log_date_time_string(),
73 format % args))
73 format % args))
74 fp.flush()
74 fp.flush()
75
75
76 def log_error(self, format, *args):
76 def log_error(self, format, *args):
77 self._log_any(self.server.errorlog, format, *args)
77 self._log_any(self.server.errorlog, format, *args)
78
78
79 def log_message(self, format, *args):
79 def log_message(self, format, *args):
80 self._log_any(self.server.accesslog, format, *args)
80 self._log_any(self.server.accesslog, format, *args)
81
81
82 def log_request(self, code='-', size='-'):
82 def log_request(self, code='-', size='-'):
83 xheaders = []
83 xheaders = []
84 if util.safehasattr(self, 'headers'):
84 if util.safehasattr(self, 'headers'):
85 xheaders = [h for h in self.headers.items()
85 xheaders = [h for h in self.headers.items()
86 if h[0].startswith('x-')]
86 if h[0].startswith('x-')]
87 self.log_message('"%s" %s %s%s',
87 self.log_message('"%s" %s %s%s',
88 self.requestline, str(code), str(size),
88 self.requestline, str(code), str(size),
89 ''.join([' %s:%s' % h for h in sorted(xheaders)]))
89 ''.join([' %s:%s' % h for h in sorted(xheaders)]))
90
90
91 def do_write(self):
91 def do_write(self):
92 try:
92 try:
93 self.do_hgweb()
93 self.do_hgweb()
94 except socket.error as inst:
94 except socket.error as inst:
95 if inst[0] != errno.EPIPE:
95 if inst[0] != errno.EPIPE:
96 raise
96 raise
97
97
98 def do_POST(self):
98 def do_POST(self):
99 try:
99 try:
100 self.do_write()
100 self.do_write()
101 except Exception:
101 except Exception:
102 self._start_response("500 Internal Server Error", [])
102 self._start_response("500 Internal Server Error", [])
103 self._write("Internal Server Error")
103 self._write("Internal Server Error")
104 self._done()
104 self._done()
105 tb = "".join(traceback.format_exception(*sys.exc_info()))
105 tb = "".join(traceback.format_exception(*sys.exc_info()))
106 self.log_error("Exception happened during processing "
106 self.log_error("Exception happened during processing "
107 "request '%s':\n%s", self.path, tb)
107 "request '%s':\n%s", self.path, tb)
108
108
109 def do_GET(self):
109 def do_GET(self):
110 self.do_POST()
110 self.do_POST()
111
111
112 def do_hgweb(self):
112 def do_hgweb(self):
113 path, query = _splitURI(self.path)
113 path, query = _splitURI(self.path)
114
114
115 env = {}
115 env = {}
116 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
116 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
117 env['REQUEST_METHOD'] = self.command
117 env['REQUEST_METHOD'] = self.command
118 env['SERVER_NAME'] = self.server.server_name
118 env['SERVER_NAME'] = self.server.server_name
119 env['SERVER_PORT'] = str(self.server.server_port)
119 env['SERVER_PORT'] = str(self.server.server_port)
120 env['REQUEST_URI'] = self.path
120 env['REQUEST_URI'] = self.path
121 env['SCRIPT_NAME'] = self.server.prefix
121 env['SCRIPT_NAME'] = self.server.prefix
122 env['PATH_INFO'] = path[len(self.server.prefix):]
122 env['PATH_INFO'] = path[len(self.server.prefix):]
123 env['REMOTE_HOST'] = self.client_address[0]
123 env['REMOTE_HOST'] = self.client_address[0]
124 env['REMOTE_ADDR'] = self.client_address[0]
124 env['REMOTE_ADDR'] = self.client_address[0]
125 if query:
125 if query:
126 env['QUERY_STRING'] = query
126 env['QUERY_STRING'] = query
127
127
128 if self.headers.typeheader is None:
128 if self.headers.typeheader is None:
129 env['CONTENT_TYPE'] = self.headers.type
129 env['CONTENT_TYPE'] = self.headers.type
130 else:
130 else:
131 env['CONTENT_TYPE'] = self.headers.typeheader
131 env['CONTENT_TYPE'] = self.headers.typeheader
132 length = self.headers.getheader('content-length')
132 length = self.headers.getheader('content-length')
133 if length:
133 if length:
134 env['CONTENT_LENGTH'] = length
134 env['CONTENT_LENGTH'] = length
135 for header in [h for h in self.headers.keys()
135 for header in [h for h in self.headers.keys()
136 if h not in ('content-type', 'content-length')]:
136 if h not in ('content-type', 'content-length')]:
137 hkey = 'HTTP_' + header.replace('-', '_').upper()
137 hkey = 'HTTP_' + header.replace('-', '_').upper()
138 hval = self.headers.getheader(header)
138 hval = self.headers.getheader(header)
139 hval = hval.replace('\n', '').strip()
139 hval = hval.replace('\n', '').strip()
140 if hval:
140 if hval:
141 env[hkey] = hval
141 env[hkey] = hval
142 env['SERVER_PROTOCOL'] = self.request_version
142 env['SERVER_PROTOCOL'] = self.request_version
143 env['wsgi.version'] = (1, 0)
143 env['wsgi.version'] = (1, 0)
144 env['wsgi.url_scheme'] = self.url_scheme
144 env['wsgi.url_scheme'] = self.url_scheme
145 if env.get('HTTP_EXPECT', '').lower() == '100-continue':
145 if env.get('HTTP_EXPECT', '').lower() == '100-continue':
146 self.rfile = common.continuereader(self.rfile, self.wfile.write)
146 self.rfile = common.continuereader(self.rfile, self.wfile.write)
147
147
148 env['wsgi.input'] = self.rfile
148 env['wsgi.input'] = self.rfile
149 env['wsgi.errors'] = _error_logger(self)
149 env['wsgi.errors'] = _error_logger(self)
150 env['wsgi.multithread'] = isinstance(self.server,
150 env['wsgi.multithread'] = isinstance(self.server,
151 socketserver.ThreadingMixIn)
151 socketserver.ThreadingMixIn)
152 env['wsgi.multiprocess'] = isinstance(self.server,
152 env['wsgi.multiprocess'] = isinstance(self.server,
153 socketserver.ForkingMixIn)
153 socketserver.ForkingMixIn)
154 env['wsgi.run_once'] = 0
154 env['wsgi.run_once'] = 0
155
155
156 self.saved_status = None
156 self.saved_status = None
157 self.saved_headers = []
157 self.saved_headers = []
158 self.sent_headers = False
158 self.sent_headers = False
159 self.length = None
159 self.length = None
160 self._chunked = None
160 self._chunked = None
161 for chunk in self.server.application(env, self._start_response):
161 for chunk in self.server.application(env, self._start_response):
162 self._write(chunk)
162 self._write(chunk)
163 if not self.sent_headers:
163 if not self.sent_headers:
164 self.send_headers()
164 self.send_headers()
165 self._done()
165 self._done()
166
166
167 def send_headers(self):
167 def send_headers(self):
168 if not self.saved_status:
168 if not self.saved_status:
169 raise AssertionError("Sending headers before "
169 raise AssertionError("Sending headers before "
170 "start_response() called")
170 "start_response() called")
171 saved_status = self.saved_status.split(None, 1)
171 saved_status = self.saved_status.split(None, 1)
172 saved_status[0] = int(saved_status[0])
172 saved_status[0] = int(saved_status[0])
173 self.send_response(*saved_status)
173 self.send_response(*saved_status)
174 self.length = None
174 self.length = None
175 self._chunked = False
175 self._chunked = False
176 for h in self.saved_headers:
176 for h in self.saved_headers:
177 self.send_header(*h)
177 self.send_header(*h)
178 if h[0].lower() == 'content-length':
178 if h[0].lower() == 'content-length':
179 self.length = int(h[1])
179 self.length = int(h[1])
180 if (self.length is None and
180 if (self.length is None and
181 saved_status[0] != common.HTTP_NOT_MODIFIED):
181 saved_status[0] != common.HTTP_NOT_MODIFIED):
182 self._chunked = (not self.close_connection and
182 self._chunked = (not self.close_connection and
183 self.request_version == "HTTP/1.1")
183 self.request_version == "HTTP/1.1")
184 if self._chunked:
184 if self._chunked:
185 self.send_header('Transfer-Encoding', 'chunked')
185 self.send_header('Transfer-Encoding', 'chunked')
186 else:
186 else:
187 self.send_header('Connection', 'close')
187 self.send_header('Connection', 'close')
188 self.end_headers()
188 self.end_headers()
189 self.sent_headers = True
189 self.sent_headers = True
190
190
191 def _start_response(self, http_status, headers, exc_info=None):
191 def _start_response(self, http_status, headers, exc_info=None):
192 code, msg = http_status.split(None, 1)
192 code, msg = http_status.split(None, 1)
193 code = int(code)
193 code = int(code)
194 self.saved_status = http_status
194 self.saved_status = http_status
195 bad_headers = ('connection', 'transfer-encoding')
195 bad_headers = ('connection', 'transfer-encoding')
196 self.saved_headers = [h for h in headers
196 self.saved_headers = [h for h in headers
197 if h[0].lower() not in bad_headers]
197 if h[0].lower() not in bad_headers]
198 return self._write
198 return self._write
199
199
200 def _write(self, data):
200 def _write(self, data):
201 if not self.saved_status:
201 if not self.saved_status:
202 raise AssertionError("data written before start_response() called")
202 raise AssertionError("data written before start_response() called")
203 elif not self.sent_headers:
203 elif not self.sent_headers:
204 self.send_headers()
204 self.send_headers()
205 if self.length is not None:
205 if self.length is not None:
206 if len(data) > self.length:
206 if len(data) > self.length:
207 raise AssertionError("Content-length header sent, but more "
207 raise AssertionError("Content-length header sent, but more "
208 "bytes than specified are being written.")
208 "bytes than specified are being written.")
209 self.length = self.length - len(data)
209 self.length = self.length - len(data)
210 elif self._chunked and data:
210 elif self._chunked and data:
211 data = '%x\r\n%s\r\n' % (len(data), data)
211 data = '%x\r\n%s\r\n' % (len(data), data)
212 self.wfile.write(data)
212 self.wfile.write(data)
213 self.wfile.flush()
213 self.wfile.flush()
214
214
215 def _done(self):
215 def _done(self):
216 if self._chunked:
216 if self._chunked:
217 self.wfile.write('0\r\n\r\n')
217 self.wfile.write('0\r\n\r\n')
218 self.wfile.flush()
218 self.wfile.flush()
219
219
220 class _httprequesthandlerssl(_httprequesthandler):
220 class _httprequesthandlerssl(_httprequesthandler):
221 """HTTPS handler based on Python's ssl module"""
221 """HTTPS handler based on Python's ssl module"""
222
222
223 url_scheme = 'https'
223 url_scheme = 'https'
224
224
225 @staticmethod
225 @staticmethod
226 def preparehttpserver(httpserver, ui):
226 def preparehttpserver(httpserver, ui):
227 try:
227 try:
228 from .. import sslutil
228 from .. import sslutil
229 sslutil.modernssl
229 sslutil.modernssl
230 except ImportError:
230 except ImportError:
231 raise error.Abort(_("SSL support is unavailable"))
231 raise error.Abort(_("SSL support is unavailable"))
232
232
233 certfile = ui.config('web', 'certificate')
233 certfile = ui.config('web', 'certificate')
234
234
235 # These config options are currently only meant for testing. Use
235 # These config options are currently only meant for testing. Use
236 # at your own risk.
236 # at your own risk.
237 cafile = ui.config('devel', 'servercafile')
237 cafile = ui.config('devel', 'servercafile')
238 reqcert = ui.configbool('devel', 'serverrequirecert')
238 reqcert = ui.configbool('devel', 'serverrequirecert')
239
239
240 httpserver.socket = sslutil.wrapserversocket(httpserver.socket,
240 httpserver.socket = sslutil.wrapserversocket(httpserver.socket,
241 ui,
241 ui,
242 certfile=certfile,
242 certfile=certfile,
243 cafile=cafile,
243 cafile=cafile,
244 requireclientcert=reqcert)
244 requireclientcert=reqcert)
245
245
246 def setup(self):
246 def setup(self):
247 self.connection = self.request
247 self.connection = self.request
248 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
248 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
249 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
249 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
250
250
251 try:
251 try:
252 import threading
252 import threading
253 threading.activeCount() # silence pyflakes and bypass demandimport
253 threading.activeCount() # silence pyflakes and bypass demandimport
254 _mixin = socketserver.ThreadingMixIn
254 _mixin = socketserver.ThreadingMixIn
255 except ImportError:
255 except ImportError:
256 if util.safehasattr(os, "fork"):
256 if util.safehasattr(os, "fork"):
257 _mixin = socketserver.ForkingMixIn
257 _mixin = socketserver.ForkingMixIn
258 else:
258 else:
259 class _mixin(object):
259 class _mixin(object):
260 pass
260 pass
261
261
262 def openlog(opt, default):
262 def openlog(opt, default):
263 if opt and opt != '-':
263 if opt and opt != '-':
264 return open(opt, 'a')
264 return open(opt, 'a')
265 return default
265 return default
266
266
267 class MercurialHTTPServer(_mixin, httpservermod.httpserver, object):
267 class MercurialHTTPServer(_mixin, httpservermod.httpserver, object):
268
268
269 # SO_REUSEADDR has broken semantics on windows
269 # SO_REUSEADDR has broken semantics on windows
270 if pycompat.osname == 'nt':
270 if pycompat.osname == 'nt':
271 allow_reuse_address = 0
271 allow_reuse_address = 0
272
272
273 def __init__(self, ui, app, addr, handler, **kwargs):
273 def __init__(self, ui, app, addr, handler, **kwargs):
274 httpservermod.httpserver.__init__(self, addr, handler, **kwargs)
274 httpservermod.httpserver.__init__(self, addr, handler, **kwargs)
275 self.daemon_threads = True
275 self.daemon_threads = True
276 self.application = app
276 self.application = app
277
277
278 handler.preparehttpserver(self, ui)
278 handler.preparehttpserver(self, ui)
279
279
280 prefix = ui.config('web', 'prefix', '')
280 prefix = ui.config('web', 'prefix', '')
281 if prefix:
281 if prefix:
282 prefix = '/' + prefix.strip('/')
282 prefix = '/' + prefix.strip('/')
283 self.prefix = prefix
283 self.prefix = prefix
284
284
285 alog = openlog(ui.config('web', 'accesslog'), ui.fout)
285 alog = openlog(ui.config('web', 'accesslog'), ui.fout)
286 elog = openlog(ui.config('web', 'errorlog', '-'), ui.ferr)
286 elog = openlog(ui.config('web', 'errorlog', '-'), ui.ferr)
287 self.accesslog = alog
287 self.accesslog = alog
288 self.errorlog = elog
288 self.errorlog = elog
289
289
290 self.addr, self.port = self.socket.getsockname()[0:2]
290 self.addr, self.port = self.socket.getsockname()[0:2]
291 self.fqaddr = socket.getfqdn(addr[0])
291 self.fqaddr = socket.getfqdn(addr[0])
292
292
293 class IPv6HTTPServer(MercurialHTTPServer):
293 class IPv6HTTPServer(MercurialHTTPServer):
294 address_family = getattr(socket, 'AF_INET6', None)
294 address_family = getattr(socket, 'AF_INET6', None)
295 def __init__(self, *args, **kwargs):
295 def __init__(self, *args, **kwargs):
296 if self.address_family is None:
296 if self.address_family is None:
297 raise error.RepoError(_('IPv6 is not available on this system'))
297 raise error.RepoError(_('IPv6 is not available on this system'))
298 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
298 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
299
299
300 def create_server(ui, app):
300 def create_server(ui, app):
301
301
302 if ui.config('web', 'certificate'):
302 if ui.config('web', 'certificate'):
303 handler = _httprequesthandlerssl
303 handler = _httprequesthandlerssl
304 else:
304 else:
305 handler = _httprequesthandler
305 handler = _httprequesthandler
306
306
307 if ui.configbool('web', 'ipv6'):
307 if ui.configbool('web', 'ipv6'):
308 cls = IPv6HTTPServer
308 cls = IPv6HTTPServer
309 else:
309 else:
310 cls = MercurialHTTPServer
310 cls = MercurialHTTPServer
311
311
312 # ugly hack due to python issue5853 (for threaded use)
312 # ugly hack due to python issue5853 (for threaded use)
313 try:
313 try:
314 import mimetypes
314 import mimetypes
315 mimetypes.init()
315 mimetypes.init()
316 except UnicodeDecodeError:
316 except UnicodeDecodeError:
317 # Python 2.x's mimetypes module attempts to decode strings
317 # Python 2.x's mimetypes module attempts to decode strings
318 # from Windows' ANSI APIs as ascii (fail), then re-encode them
318 # from Windows' ANSI APIs as ascii (fail), then re-encode them
319 # as ascii (clown fail), because the default Python Unicode
319 # as ascii (clown fail), because the default Python Unicode
320 # codec is hardcoded as ascii.
320 # codec is hardcoded as ascii.
321
321
322 sys.argv # unwrap demand-loader so that reload() works
322 sys.argv # unwrap demand-loader so that reload() works
323 reload(sys) # resurrect sys.setdefaultencoding()
323 reload(sys) # resurrect sys.setdefaultencoding()
324 oldenc = sys.getdefaultencoding()
324 oldenc = sys.getdefaultencoding()
325 sys.setdefaultencoding("latin1") # or any full 8-bit encoding
325 sys.setdefaultencoding("latin1") # or any full 8-bit encoding
326 mimetypes.init()
326 mimetypes.init()
327 sys.setdefaultencoding(oldenc)
327 sys.setdefaultencoding(oldenc)
328
328
329 address = ui.config('web', 'address', '')
329 address = ui.config('web', 'address')
330 port = util.getport(ui.config('web', 'port', 8000))
330 port = util.getport(ui.config('web', 'port', 8000))
331 try:
331 try:
332 return cls(ui, app, (address, port), handler)
332 return cls(ui, app, (address, port), handler)
333 except socket.error as inst:
333 except socket.error as inst:
334 raise error.Abort(_("cannot start server at '%s:%d': %s")
334 raise error.Abort(_("cannot start server at '%s:%d': %s")
335 % (address, port, inst.args[1]))
335 % (address, port, inst.args[1]))
General Comments 0
You need to be logged in to leave comments. Login now