##// END OF EJS Templates
configitems: register the 'web.push_ssl' config
Boris Feld -
r34586:f28c85e2 default
parent child Browse files
Show More
@@ -1,770 +1,773 b''
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 encoding,
13 encoding,
14 error,
14 error,
15 )
15 )
16
16
17 def loadconfigtable(ui, extname, configtable):
17 def loadconfigtable(ui, extname, configtable):
18 """update config item known to the ui with the extension ones"""
18 """update config item known to the ui with the extension ones"""
19 for section, items in configtable.items():
19 for section, items in configtable.items():
20 knownitems = ui._knownconfig.setdefault(section, {})
20 knownitems = ui._knownconfig.setdefault(section, {})
21 knownkeys = set(knownitems)
21 knownkeys = set(knownitems)
22 newkeys = set(items)
22 newkeys = set(items)
23 for key in sorted(knownkeys & newkeys):
23 for key in sorted(knownkeys & newkeys):
24 msg = "extension '%s' overwrite config item '%s.%s'"
24 msg = "extension '%s' overwrite config item '%s.%s'"
25 msg %= (extname, section, key)
25 msg %= (extname, section, key)
26 ui.develwarn(msg, config='warn-config')
26 ui.develwarn(msg, config='warn-config')
27
27
28 knownitems.update(items)
28 knownitems.update(items)
29
29
30 class configitem(object):
30 class configitem(object):
31 """represent a known config item
31 """represent a known config item
32
32
33 :section: the official config section where to find this item,
33 :section: the official config section where to find this item,
34 :name: the official name within the section,
34 :name: the official name within the section,
35 :default: default value for this item,
35 :default: default value for this item,
36 :alias: optional list of tuples as alternatives.
36 :alias: optional list of tuples as alternatives.
37 """
37 """
38
38
39 def __init__(self, section, name, default=None, alias=()):
39 def __init__(self, section, name, default=None, alias=()):
40 self.section = section
40 self.section = section
41 self.name = name
41 self.name = name
42 self.default = default
42 self.default = default
43 self.alias = list(alias)
43 self.alias = list(alias)
44
44
45 coreitems = {}
45 coreitems = {}
46
46
47 def _register(configtable, *args, **kwargs):
47 def _register(configtable, *args, **kwargs):
48 item = configitem(*args, **kwargs)
48 item = configitem(*args, **kwargs)
49 section = configtable.setdefault(item.section, {})
49 section = configtable.setdefault(item.section, {})
50 if item.name in section:
50 if item.name in section:
51 msg = "duplicated config item registration for '%s.%s'"
51 msg = "duplicated config item registration for '%s.%s'"
52 raise error.ProgrammingError(msg % (item.section, item.name))
52 raise error.ProgrammingError(msg % (item.section, item.name))
53 section[item.name] = item
53 section[item.name] = item
54
54
55 # special value for case where the default is derived from other values
55 # special value for case where the default is derived from other values
56 dynamicdefault = object()
56 dynamicdefault = object()
57
57
58 # Registering actual config items
58 # Registering actual config items
59
59
60 def getitemregister(configtable):
60 def getitemregister(configtable):
61 return functools.partial(_register, configtable)
61 return functools.partial(_register, configtable)
62
62
63 coreconfigitem = getitemregister(coreitems)
63 coreconfigitem = getitemregister(coreitems)
64
64
65 coreconfigitem('auth', 'cookiefile',
65 coreconfigitem('auth', 'cookiefile',
66 default=None,
66 default=None,
67 )
67 )
68 # bookmarks.pushing: internal hack for discovery
68 # bookmarks.pushing: internal hack for discovery
69 coreconfigitem('bookmarks', 'pushing',
69 coreconfigitem('bookmarks', 'pushing',
70 default=list,
70 default=list,
71 )
71 )
72 # bundle.mainreporoot: internal hack for bundlerepo
72 # bundle.mainreporoot: internal hack for bundlerepo
73 coreconfigitem('bundle', 'mainreporoot',
73 coreconfigitem('bundle', 'mainreporoot',
74 default='',
74 default='',
75 )
75 )
76 # bundle.reorder: experimental config
76 # bundle.reorder: experimental config
77 coreconfigitem('bundle', 'reorder',
77 coreconfigitem('bundle', 'reorder',
78 default='auto',
78 default='auto',
79 )
79 )
80 coreconfigitem('censor', 'policy',
80 coreconfigitem('censor', 'policy',
81 default='abort',
81 default='abort',
82 )
82 )
83 coreconfigitem('chgserver', 'idletimeout',
83 coreconfigitem('chgserver', 'idletimeout',
84 default=3600,
84 default=3600,
85 )
85 )
86 coreconfigitem('chgserver', 'skiphash',
86 coreconfigitem('chgserver', 'skiphash',
87 default=False,
87 default=False,
88 )
88 )
89 coreconfigitem('cmdserver', 'log',
89 coreconfigitem('cmdserver', 'log',
90 default=None,
90 default=None,
91 )
91 )
92 coreconfigitem('color', 'mode',
92 coreconfigitem('color', 'mode',
93 default='auto',
93 default='auto',
94 )
94 )
95 coreconfigitem('color', 'pagermode',
95 coreconfigitem('color', 'pagermode',
96 default=dynamicdefault,
96 default=dynamicdefault,
97 )
97 )
98 coreconfigitem('commands', 'status.relative',
98 coreconfigitem('commands', 'status.relative',
99 default=False,
99 default=False,
100 )
100 )
101 coreconfigitem('commands', 'status.skipstates',
101 coreconfigitem('commands', 'status.skipstates',
102 default=[],
102 default=[],
103 )
103 )
104 coreconfigitem('commands', 'status.verbose',
104 coreconfigitem('commands', 'status.verbose',
105 default=False,
105 default=False,
106 )
106 )
107 coreconfigitem('commands', 'update.requiredest',
107 coreconfigitem('commands', 'update.requiredest',
108 default=False,
108 default=False,
109 )
109 )
110 coreconfigitem('debug', 'dirstate.delaywrite',
110 coreconfigitem('debug', 'dirstate.delaywrite',
111 default=0,
111 default=0,
112 )
112 )
113 coreconfigitem('devel', 'all-warnings',
113 coreconfigitem('devel', 'all-warnings',
114 default=False,
114 default=False,
115 )
115 )
116 coreconfigitem('devel', 'bundle2.debug',
116 coreconfigitem('devel', 'bundle2.debug',
117 default=False,
117 default=False,
118 )
118 )
119 coreconfigitem('devel', 'cache-vfs',
119 coreconfigitem('devel', 'cache-vfs',
120 default=None,
120 default=None,
121 )
121 )
122 coreconfigitem('devel', 'check-locks',
122 coreconfigitem('devel', 'check-locks',
123 default=False,
123 default=False,
124 )
124 )
125 coreconfigitem('devel', 'check-relroot',
125 coreconfigitem('devel', 'check-relroot',
126 default=False,
126 default=False,
127 )
127 )
128 coreconfigitem('devel', 'default-date',
128 coreconfigitem('devel', 'default-date',
129 default=None,
129 default=None,
130 )
130 )
131 coreconfigitem('devel', 'deprec-warn',
131 coreconfigitem('devel', 'deprec-warn',
132 default=False,
132 default=False,
133 )
133 )
134 coreconfigitem('devel', 'disableloaddefaultcerts',
134 coreconfigitem('devel', 'disableloaddefaultcerts',
135 default=False,
135 default=False,
136 )
136 )
137 coreconfigitem('devel', 'empty-changegroup',
137 coreconfigitem('devel', 'empty-changegroup',
138 default=False,
138 default=False,
139 )
139 )
140 coreconfigitem('devel', 'legacy.exchange',
140 coreconfigitem('devel', 'legacy.exchange',
141 default=list,
141 default=list,
142 )
142 )
143 coreconfigitem('devel', 'servercafile',
143 coreconfigitem('devel', 'servercafile',
144 default='',
144 default='',
145 )
145 )
146 coreconfigitem('devel', 'serverexactprotocol',
146 coreconfigitem('devel', 'serverexactprotocol',
147 default='',
147 default='',
148 )
148 )
149 coreconfigitem('devel', 'serverrequirecert',
149 coreconfigitem('devel', 'serverrequirecert',
150 default=False,
150 default=False,
151 )
151 )
152 coreconfigitem('devel', 'strip-obsmarkers',
152 coreconfigitem('devel', 'strip-obsmarkers',
153 default=True,
153 default=True,
154 )
154 )
155 coreconfigitem('devel', 'warn-config',
155 coreconfigitem('devel', 'warn-config',
156 default=None,
156 default=None,
157 )
157 )
158 coreconfigitem('devel', 'warn-config-default',
158 coreconfigitem('devel', 'warn-config-default',
159 default=None,
159 default=None,
160 )
160 )
161 coreconfigitem('devel', 'user.obsmarker',
161 coreconfigitem('devel', 'user.obsmarker',
162 default=None,
162 default=None,
163 )
163 )
164 coreconfigitem('diff', 'nodates',
164 coreconfigitem('diff', 'nodates',
165 default=None,
165 default=None,
166 )
166 )
167 coreconfigitem('diff', 'showfunc',
167 coreconfigitem('diff', 'showfunc',
168 default=None,
168 default=None,
169 )
169 )
170 coreconfigitem('diff', 'unified',
170 coreconfigitem('diff', 'unified',
171 default=None,
171 default=None,
172 )
172 )
173 coreconfigitem('diff', 'git',
173 coreconfigitem('diff', 'git',
174 default=None,
174 default=None,
175 )
175 )
176 coreconfigitem('diff', 'ignorews',
176 coreconfigitem('diff', 'ignorews',
177 default=None,
177 default=None,
178 )
178 )
179 coreconfigitem('diff', 'ignorewsamount',
179 coreconfigitem('diff', 'ignorewsamount',
180 default=None,
180 default=None,
181 )
181 )
182 coreconfigitem('diff', 'ignoreblanklines',
182 coreconfigitem('diff', 'ignoreblanklines',
183 default=None,
183 default=None,
184 )
184 )
185 coreconfigitem('diff', 'ignorewseol',
185 coreconfigitem('diff', 'ignorewseol',
186 default=None,
186 default=None,
187 )
187 )
188 coreconfigitem('diff', 'nobinary',
188 coreconfigitem('diff', 'nobinary',
189 default=None,
189 default=None,
190 )
190 )
191 coreconfigitem('diff', 'noprefix',
191 coreconfigitem('diff', 'noprefix',
192 default=None,
192 default=None,
193 )
193 )
194 coreconfigitem('email', 'charsets',
194 coreconfigitem('email', 'charsets',
195 default=list,
195 default=list,
196 )
196 )
197 coreconfigitem('email', 'from',
197 coreconfigitem('email', 'from',
198 default=None,
198 default=None,
199 )
199 )
200 coreconfigitem('email', 'method',
200 coreconfigitem('email', 'method',
201 default='smtp',
201 default='smtp',
202 )
202 )
203 coreconfigitem('experimental', 'allowdivergence',
203 coreconfigitem('experimental', 'allowdivergence',
204 default=False,
204 default=False,
205 )
205 )
206 coreconfigitem('experimental', 'bundle-phases',
206 coreconfigitem('experimental', 'bundle-phases',
207 default=False,
207 default=False,
208 )
208 )
209 coreconfigitem('experimental', 'bundle2-advertise',
209 coreconfigitem('experimental', 'bundle2-advertise',
210 default=True,
210 default=True,
211 )
211 )
212 coreconfigitem('experimental', 'bundle2-output-capture',
212 coreconfigitem('experimental', 'bundle2-output-capture',
213 default=False,
213 default=False,
214 )
214 )
215 coreconfigitem('experimental', 'bundle2.pushback',
215 coreconfigitem('experimental', 'bundle2.pushback',
216 default=False,
216 default=False,
217 )
217 )
218 coreconfigitem('experimental', 'bundle2lazylocking',
218 coreconfigitem('experimental', 'bundle2lazylocking',
219 default=False,
219 default=False,
220 )
220 )
221 coreconfigitem('experimental', 'bundlecomplevel',
221 coreconfigitem('experimental', 'bundlecomplevel',
222 default=None,
222 default=None,
223 )
223 )
224 coreconfigitem('experimental', 'changegroup3',
224 coreconfigitem('experimental', 'changegroup3',
225 default=False,
225 default=False,
226 )
226 )
227 coreconfigitem('experimental', 'clientcompressionengines',
227 coreconfigitem('experimental', 'clientcompressionengines',
228 default=list,
228 default=list,
229 )
229 )
230 coreconfigitem('experimental', 'copytrace',
230 coreconfigitem('experimental', 'copytrace',
231 default='on',
231 default='on',
232 )
232 )
233 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
233 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
234 default=100,
234 default=100,
235 )
235 )
236 coreconfigitem('experimental', 'crecordtest',
236 coreconfigitem('experimental', 'crecordtest',
237 default=None,
237 default=None,
238 )
238 )
239 coreconfigitem('experimental', 'editortmpinhg',
239 coreconfigitem('experimental', 'editortmpinhg',
240 default=False,
240 default=False,
241 )
241 )
242 coreconfigitem('experimental', 'maxdeltachainspan',
242 coreconfigitem('experimental', 'maxdeltachainspan',
243 default=-1,
243 default=-1,
244 )
244 )
245 coreconfigitem('experimental', 'mmapindexthreshold',
245 coreconfigitem('experimental', 'mmapindexthreshold',
246 default=None,
246 default=None,
247 )
247 )
248 coreconfigitem('experimental', 'nonnormalparanoidcheck',
248 coreconfigitem('experimental', 'nonnormalparanoidcheck',
249 default=False,
249 default=False,
250 )
250 )
251 coreconfigitem('experimental', 'stabilization',
251 coreconfigitem('experimental', 'stabilization',
252 default=list,
252 default=list,
253 alias=[('experimental', 'evolution')],
253 alias=[('experimental', 'evolution')],
254 )
254 )
255 coreconfigitem('experimental', 'stabilization.bundle-obsmarker',
255 coreconfigitem('experimental', 'stabilization.bundle-obsmarker',
256 default=False,
256 default=False,
257 alias=[('experimental', 'evolution.bundle-obsmarker')],
257 alias=[('experimental', 'evolution.bundle-obsmarker')],
258 )
258 )
259 coreconfigitem('experimental', 'stabilization.track-operation',
259 coreconfigitem('experimental', 'stabilization.track-operation',
260 default=True,
260 default=True,
261 alias=[('experimental', 'evolution.track-operation')]
261 alias=[('experimental', 'evolution.track-operation')]
262 )
262 )
263 coreconfigitem('experimental', 'exportableenviron',
263 coreconfigitem('experimental', 'exportableenviron',
264 default=list,
264 default=list,
265 )
265 )
266 coreconfigitem('experimental', 'extendedheader.index',
266 coreconfigitem('experimental', 'extendedheader.index',
267 default=None,
267 default=None,
268 )
268 )
269 coreconfigitem('experimental', 'extendedheader.similarity',
269 coreconfigitem('experimental', 'extendedheader.similarity',
270 default=False,
270 default=False,
271 )
271 )
272 coreconfigitem('experimental', 'format.compression',
272 coreconfigitem('experimental', 'format.compression',
273 default='zlib',
273 default='zlib',
274 )
274 )
275 coreconfigitem('experimental', 'graphshorten',
275 coreconfigitem('experimental', 'graphshorten',
276 default=False,
276 default=False,
277 )
277 )
278 coreconfigitem('experimental', 'graphstyle.parent',
278 coreconfigitem('experimental', 'graphstyle.parent',
279 default=dynamicdefault,
279 default=dynamicdefault,
280 )
280 )
281 coreconfigitem('experimental', 'graphstyle.missing',
281 coreconfigitem('experimental', 'graphstyle.missing',
282 default=dynamicdefault,
282 default=dynamicdefault,
283 )
283 )
284 coreconfigitem('experimental', 'graphstyle.grandparent',
284 coreconfigitem('experimental', 'graphstyle.grandparent',
285 default=dynamicdefault,
285 default=dynamicdefault,
286 )
286 )
287 coreconfigitem('experimental', 'hook-track-tags',
287 coreconfigitem('experimental', 'hook-track-tags',
288 default=False,
288 default=False,
289 )
289 )
290 coreconfigitem('experimental', 'httppostargs',
290 coreconfigitem('experimental', 'httppostargs',
291 default=False,
291 default=False,
292 )
292 )
293 coreconfigitem('experimental', 'manifestv2',
293 coreconfigitem('experimental', 'manifestv2',
294 default=False,
294 default=False,
295 )
295 )
296 coreconfigitem('experimental', 'mergedriver',
296 coreconfigitem('experimental', 'mergedriver',
297 default=None,
297 default=None,
298 )
298 )
299 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
299 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
300 default=False,
300 default=False,
301 )
301 )
302 coreconfigitem('experimental', 'rebase.multidest',
302 coreconfigitem('experimental', 'rebase.multidest',
303 default=False,
303 default=False,
304 )
304 )
305 coreconfigitem('experimental', 'revertalternateinteractivemode',
305 coreconfigitem('experimental', 'revertalternateinteractivemode',
306 default=True,
306 default=True,
307 )
307 )
308 coreconfigitem('experimental', 'revlogv2',
308 coreconfigitem('experimental', 'revlogv2',
309 default=None,
309 default=None,
310 )
310 )
311 coreconfigitem('experimental', 'spacemovesdown',
311 coreconfigitem('experimental', 'spacemovesdown',
312 default=False,
312 default=False,
313 )
313 )
314 coreconfigitem('experimental', 'treemanifest',
314 coreconfigitem('experimental', 'treemanifest',
315 default=False,
315 default=False,
316 )
316 )
317 coreconfigitem('experimental', 'updatecheck',
317 coreconfigitem('experimental', 'updatecheck',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem('format', 'aggressivemergedeltas',
320 coreconfigitem('format', 'aggressivemergedeltas',
321 default=False,
321 default=False,
322 )
322 )
323 coreconfigitem('format', 'chunkcachesize',
323 coreconfigitem('format', 'chunkcachesize',
324 default=None,
324 default=None,
325 )
325 )
326 coreconfigitem('format', 'dotencode',
326 coreconfigitem('format', 'dotencode',
327 default=True,
327 default=True,
328 )
328 )
329 coreconfigitem('format', 'generaldelta',
329 coreconfigitem('format', 'generaldelta',
330 default=False,
330 default=False,
331 )
331 )
332 coreconfigitem('format', 'manifestcachesize',
332 coreconfigitem('format', 'manifestcachesize',
333 default=None,
333 default=None,
334 )
334 )
335 coreconfigitem('format', 'maxchainlen',
335 coreconfigitem('format', 'maxchainlen',
336 default=None,
336 default=None,
337 )
337 )
338 coreconfigitem('format', 'obsstore-version',
338 coreconfigitem('format', 'obsstore-version',
339 default=None,
339 default=None,
340 )
340 )
341 coreconfigitem('format', 'usefncache',
341 coreconfigitem('format', 'usefncache',
342 default=True,
342 default=True,
343 )
343 )
344 coreconfigitem('format', 'usegeneraldelta',
344 coreconfigitem('format', 'usegeneraldelta',
345 default=True,
345 default=True,
346 )
346 )
347 coreconfigitem('format', 'usestore',
347 coreconfigitem('format', 'usestore',
348 default=True,
348 default=True,
349 )
349 )
350 coreconfigitem('hostsecurity', 'ciphers',
350 coreconfigitem('hostsecurity', 'ciphers',
351 default=None,
351 default=None,
352 )
352 )
353 coreconfigitem('hostsecurity', 'disabletls10warning',
353 coreconfigitem('hostsecurity', 'disabletls10warning',
354 default=False,
354 default=False,
355 )
355 )
356 coreconfigitem('http_proxy', 'always',
356 coreconfigitem('http_proxy', 'always',
357 default=False,
357 default=False,
358 )
358 )
359 coreconfigitem('http_proxy', 'host',
359 coreconfigitem('http_proxy', 'host',
360 default=None,
360 default=None,
361 )
361 )
362 coreconfigitem('http_proxy', 'no',
362 coreconfigitem('http_proxy', 'no',
363 default=list,
363 default=list,
364 )
364 )
365 coreconfigitem('http_proxy', 'passwd',
365 coreconfigitem('http_proxy', 'passwd',
366 default=None,
366 default=None,
367 )
367 )
368 coreconfigitem('http_proxy', 'user',
368 coreconfigitem('http_proxy', 'user',
369 default=None,
369 default=None,
370 )
370 )
371 coreconfigitem('merge', 'checkunknown',
371 coreconfigitem('merge', 'checkunknown',
372 default='abort',
372 default='abort',
373 )
373 )
374 coreconfigitem('merge', 'checkignored',
374 coreconfigitem('merge', 'checkignored',
375 default='abort',
375 default='abort',
376 )
376 )
377 coreconfigitem('merge', 'followcopies',
377 coreconfigitem('merge', 'followcopies',
378 default=True,
378 default=True,
379 )
379 )
380 coreconfigitem('merge', 'preferancestor',
380 coreconfigitem('merge', 'preferancestor',
381 default=lambda: ['*'],
381 default=lambda: ['*'],
382 )
382 )
383 coreconfigitem('pager', 'ignore',
383 coreconfigitem('pager', 'ignore',
384 default=list,
384 default=list,
385 )
385 )
386 coreconfigitem('patch', 'eol',
386 coreconfigitem('patch', 'eol',
387 default='strict',
387 default='strict',
388 )
388 )
389 coreconfigitem('patch', 'fuzz',
389 coreconfigitem('patch', 'fuzz',
390 default=2,
390 default=2,
391 )
391 )
392 coreconfigitem('paths', 'default',
392 coreconfigitem('paths', 'default',
393 default=None,
393 default=None,
394 )
394 )
395 coreconfigitem('paths', 'default-push',
395 coreconfigitem('paths', 'default-push',
396 default=None,
396 default=None,
397 )
397 )
398 coreconfigitem('phases', 'checksubrepos',
398 coreconfigitem('phases', 'checksubrepos',
399 default='follow',
399 default='follow',
400 )
400 )
401 coreconfigitem('phases', 'new-commit',
401 coreconfigitem('phases', 'new-commit',
402 default='draft',
402 default='draft',
403 )
403 )
404 coreconfigitem('phases', 'publish',
404 coreconfigitem('phases', 'publish',
405 default=True,
405 default=True,
406 )
406 )
407 coreconfigitem('profiling', 'enabled',
407 coreconfigitem('profiling', 'enabled',
408 default=False,
408 default=False,
409 )
409 )
410 coreconfigitem('profiling', 'format',
410 coreconfigitem('profiling', 'format',
411 default='text',
411 default='text',
412 )
412 )
413 coreconfigitem('profiling', 'freq',
413 coreconfigitem('profiling', 'freq',
414 default=1000,
414 default=1000,
415 )
415 )
416 coreconfigitem('profiling', 'limit',
416 coreconfigitem('profiling', 'limit',
417 default=30,
417 default=30,
418 )
418 )
419 coreconfigitem('profiling', 'nested',
419 coreconfigitem('profiling', 'nested',
420 default=0,
420 default=0,
421 )
421 )
422 coreconfigitem('profiling', 'output',
422 coreconfigitem('profiling', 'output',
423 default=None,
423 default=None,
424 )
424 )
425 coreconfigitem('profiling', 'showmax',
425 coreconfigitem('profiling', 'showmax',
426 default=0.999,
426 default=0.999,
427 )
427 )
428 coreconfigitem('profiling', 'showmin',
428 coreconfigitem('profiling', 'showmin',
429 default=dynamicdefault,
429 default=dynamicdefault,
430 )
430 )
431 coreconfigitem('profiling', 'sort',
431 coreconfigitem('profiling', 'sort',
432 default='inlinetime',
432 default='inlinetime',
433 )
433 )
434 coreconfigitem('profiling', 'statformat',
434 coreconfigitem('profiling', 'statformat',
435 default='hotpath',
435 default='hotpath',
436 )
436 )
437 coreconfigitem('profiling', 'type',
437 coreconfigitem('profiling', 'type',
438 default='stat',
438 default='stat',
439 )
439 )
440 coreconfigitem('progress', 'assume-tty',
440 coreconfigitem('progress', 'assume-tty',
441 default=False,
441 default=False,
442 )
442 )
443 coreconfigitem('progress', 'changedelay',
443 coreconfigitem('progress', 'changedelay',
444 default=1,
444 default=1,
445 )
445 )
446 coreconfigitem('progress', 'clear-complete',
446 coreconfigitem('progress', 'clear-complete',
447 default=True,
447 default=True,
448 )
448 )
449 coreconfigitem('progress', 'debug',
449 coreconfigitem('progress', 'debug',
450 default=False,
450 default=False,
451 )
451 )
452 coreconfigitem('progress', 'delay',
452 coreconfigitem('progress', 'delay',
453 default=3,
453 default=3,
454 )
454 )
455 coreconfigitem('progress', 'disable',
455 coreconfigitem('progress', 'disable',
456 default=False,
456 default=False,
457 )
457 )
458 coreconfigitem('progress', 'estimateinterval',
458 coreconfigitem('progress', 'estimateinterval',
459 default=60.0,
459 default=60.0,
460 )
460 )
461 coreconfigitem('progress', 'refresh',
461 coreconfigitem('progress', 'refresh',
462 default=0.1,
462 default=0.1,
463 )
463 )
464 coreconfigitem('progress', 'width',
464 coreconfigitem('progress', 'width',
465 default=dynamicdefault,
465 default=dynamicdefault,
466 )
466 )
467 coreconfigitem('push', 'pushvars.server',
467 coreconfigitem('push', 'pushvars.server',
468 default=False,
468 default=False,
469 )
469 )
470 coreconfigitem('server', 'bundle1',
470 coreconfigitem('server', 'bundle1',
471 default=True,
471 default=True,
472 )
472 )
473 coreconfigitem('server', 'bundle1gd',
473 coreconfigitem('server', 'bundle1gd',
474 default=None,
474 default=None,
475 )
475 )
476 coreconfigitem('server', 'compressionengines',
476 coreconfigitem('server', 'compressionengines',
477 default=list,
477 default=list,
478 )
478 )
479 coreconfigitem('server', 'concurrent-push-mode',
479 coreconfigitem('server', 'concurrent-push-mode',
480 default='strict',
480 default='strict',
481 )
481 )
482 coreconfigitem('server', 'disablefullbundle',
482 coreconfigitem('server', 'disablefullbundle',
483 default=False,
483 default=False,
484 )
484 )
485 coreconfigitem('server', 'maxhttpheaderlen',
485 coreconfigitem('server', 'maxhttpheaderlen',
486 default=1024,
486 default=1024,
487 )
487 )
488 coreconfigitem('server', 'preferuncompressed',
488 coreconfigitem('server', 'preferuncompressed',
489 default=False,
489 default=False,
490 )
490 )
491 coreconfigitem('server', 'uncompressed',
491 coreconfigitem('server', 'uncompressed',
492 default=True,
492 default=True,
493 )
493 )
494 coreconfigitem('server', 'uncompressedallowsecret',
494 coreconfigitem('server', 'uncompressedallowsecret',
495 default=False,
495 default=False,
496 )
496 )
497 coreconfigitem('server', 'validate',
497 coreconfigitem('server', 'validate',
498 default=False,
498 default=False,
499 )
499 )
500 coreconfigitem('server', 'zliblevel',
500 coreconfigitem('server', 'zliblevel',
501 default=-1,
501 default=-1,
502 )
502 )
503 coreconfigitem('smtp', 'host',
503 coreconfigitem('smtp', 'host',
504 default=None,
504 default=None,
505 )
505 )
506 coreconfigitem('smtp', 'local_hostname',
506 coreconfigitem('smtp', 'local_hostname',
507 default=None,
507 default=None,
508 )
508 )
509 coreconfigitem('smtp', 'password',
509 coreconfigitem('smtp', 'password',
510 default=None,
510 default=None,
511 )
511 )
512 coreconfigitem('smtp', 'port',
512 coreconfigitem('smtp', 'port',
513 default=dynamicdefault,
513 default=dynamicdefault,
514 )
514 )
515 coreconfigitem('smtp', 'tls',
515 coreconfigitem('smtp', 'tls',
516 default='none',
516 default='none',
517 )
517 )
518 coreconfigitem('smtp', 'username',
518 coreconfigitem('smtp', 'username',
519 default=None,
519 default=None,
520 )
520 )
521 coreconfigitem('sparse', 'missingwarning',
521 coreconfigitem('sparse', 'missingwarning',
522 default=True,
522 default=True,
523 )
523 )
524 coreconfigitem('trusted', 'groups',
524 coreconfigitem('trusted', 'groups',
525 default=list,
525 default=list,
526 )
526 )
527 coreconfigitem('trusted', 'users',
527 coreconfigitem('trusted', 'users',
528 default=list,
528 default=list,
529 )
529 )
530 coreconfigitem('ui', '_usedassubrepo',
530 coreconfigitem('ui', '_usedassubrepo',
531 default=False,
531 default=False,
532 )
532 )
533 coreconfigitem('ui', 'allowemptycommit',
533 coreconfigitem('ui', 'allowemptycommit',
534 default=False,
534 default=False,
535 )
535 )
536 coreconfigitem('ui', 'archivemeta',
536 coreconfigitem('ui', 'archivemeta',
537 default=True,
537 default=True,
538 )
538 )
539 coreconfigitem('ui', 'askusername',
539 coreconfigitem('ui', 'askusername',
540 default=False,
540 default=False,
541 )
541 )
542 coreconfigitem('ui', 'clonebundlefallback',
542 coreconfigitem('ui', 'clonebundlefallback',
543 default=False,
543 default=False,
544 )
544 )
545 coreconfigitem('ui', 'clonebundleprefers',
545 coreconfigitem('ui', 'clonebundleprefers',
546 default=list,
546 default=list,
547 )
547 )
548 coreconfigitem('ui', 'clonebundles',
548 coreconfigitem('ui', 'clonebundles',
549 default=True,
549 default=True,
550 )
550 )
551 coreconfigitem('ui', 'color',
551 coreconfigitem('ui', 'color',
552 default='auto',
552 default='auto',
553 )
553 )
554 coreconfigitem('ui', 'commitsubrepos',
554 coreconfigitem('ui', 'commitsubrepos',
555 default=False,
555 default=False,
556 )
556 )
557 coreconfigitem('ui', 'debug',
557 coreconfigitem('ui', 'debug',
558 default=False,
558 default=False,
559 )
559 )
560 coreconfigitem('ui', 'debugger',
560 coreconfigitem('ui', 'debugger',
561 default=None,
561 default=None,
562 )
562 )
563 coreconfigitem('ui', 'fallbackencoding',
563 coreconfigitem('ui', 'fallbackencoding',
564 default=None,
564 default=None,
565 )
565 )
566 coreconfigitem('ui', 'forcecwd',
566 coreconfigitem('ui', 'forcecwd',
567 default=None,
567 default=None,
568 )
568 )
569 coreconfigitem('ui', 'forcemerge',
569 coreconfigitem('ui', 'forcemerge',
570 default=None,
570 default=None,
571 )
571 )
572 coreconfigitem('ui', 'formatdebug',
572 coreconfigitem('ui', 'formatdebug',
573 default=False,
573 default=False,
574 )
574 )
575 coreconfigitem('ui', 'formatjson',
575 coreconfigitem('ui', 'formatjson',
576 default=False,
576 default=False,
577 )
577 )
578 coreconfigitem('ui', 'formatted',
578 coreconfigitem('ui', 'formatted',
579 default=None,
579 default=None,
580 )
580 )
581 coreconfigitem('ui', 'graphnodetemplate',
581 coreconfigitem('ui', 'graphnodetemplate',
582 default=None,
582 default=None,
583 )
583 )
584 coreconfigitem('ui', 'http2debuglevel',
584 coreconfigitem('ui', 'http2debuglevel',
585 default=None,
585 default=None,
586 )
586 )
587 coreconfigitem('ui', 'interactive',
587 coreconfigitem('ui', 'interactive',
588 default=None,
588 default=None,
589 )
589 )
590 coreconfigitem('ui', 'interface',
590 coreconfigitem('ui', 'interface',
591 default=None,
591 default=None,
592 )
592 )
593 coreconfigitem('ui', 'logblockedtimes',
593 coreconfigitem('ui', 'logblockedtimes',
594 default=False,
594 default=False,
595 )
595 )
596 coreconfigitem('ui', 'logtemplate',
596 coreconfigitem('ui', 'logtemplate',
597 default=None,
597 default=None,
598 )
598 )
599 coreconfigitem('ui', 'merge',
599 coreconfigitem('ui', 'merge',
600 default=None,
600 default=None,
601 )
601 )
602 coreconfigitem('ui', 'mergemarkers',
602 coreconfigitem('ui', 'mergemarkers',
603 default='basic',
603 default='basic',
604 )
604 )
605 coreconfigitem('ui', 'mergemarkertemplate',
605 coreconfigitem('ui', 'mergemarkertemplate',
606 default=('{node|short} '
606 default=('{node|short} '
607 '{ifeq(tags, "tip", "", '
607 '{ifeq(tags, "tip", "", '
608 'ifeq(tags, "", "", "{tags} "))}'
608 'ifeq(tags, "", "", "{tags} "))}'
609 '{if(bookmarks, "{bookmarks} ")}'
609 '{if(bookmarks, "{bookmarks} ")}'
610 '{ifeq(branch, "default", "", "{branch} ")}'
610 '{ifeq(branch, "default", "", "{branch} ")}'
611 '- {author|user}: {desc|firstline}')
611 '- {author|user}: {desc|firstline}')
612 )
612 )
613 coreconfigitem('ui', 'nontty',
613 coreconfigitem('ui', 'nontty',
614 default=False,
614 default=False,
615 )
615 )
616 coreconfigitem('ui', 'origbackuppath',
616 coreconfigitem('ui', 'origbackuppath',
617 default=None,
617 default=None,
618 )
618 )
619 coreconfigitem('ui', 'paginate',
619 coreconfigitem('ui', 'paginate',
620 default=True,
620 default=True,
621 )
621 )
622 coreconfigitem('ui', 'patch',
622 coreconfigitem('ui', 'patch',
623 default=None,
623 default=None,
624 )
624 )
625 coreconfigitem('ui', 'portablefilenames',
625 coreconfigitem('ui', 'portablefilenames',
626 default='warn',
626 default='warn',
627 )
627 )
628 coreconfigitem('ui', 'promptecho',
628 coreconfigitem('ui', 'promptecho',
629 default=False,
629 default=False,
630 )
630 )
631 coreconfigitem('ui', 'quiet',
631 coreconfigitem('ui', 'quiet',
632 default=False,
632 default=False,
633 )
633 )
634 coreconfigitem('ui', 'quietbookmarkmove',
634 coreconfigitem('ui', 'quietbookmarkmove',
635 default=False,
635 default=False,
636 )
636 )
637 coreconfigitem('ui', 'remotecmd',
637 coreconfigitem('ui', 'remotecmd',
638 default='hg',
638 default='hg',
639 )
639 )
640 coreconfigitem('ui', 'report_untrusted',
640 coreconfigitem('ui', 'report_untrusted',
641 default=True,
641 default=True,
642 )
642 )
643 coreconfigitem('ui', 'rollback',
643 coreconfigitem('ui', 'rollback',
644 default=True,
644 default=True,
645 )
645 )
646 coreconfigitem('ui', 'slash',
646 coreconfigitem('ui', 'slash',
647 default=False,
647 default=False,
648 )
648 )
649 coreconfigitem('ui', 'ssh',
649 coreconfigitem('ui', 'ssh',
650 default='ssh',
650 default='ssh',
651 )
651 )
652 coreconfigitem('ui', 'statuscopies',
652 coreconfigitem('ui', 'statuscopies',
653 default=False,
653 default=False,
654 )
654 )
655 coreconfigitem('ui', 'strict',
655 coreconfigitem('ui', 'strict',
656 default=False,
656 default=False,
657 )
657 )
658 coreconfigitem('ui', 'style',
658 coreconfigitem('ui', 'style',
659 default='',
659 default='',
660 )
660 )
661 coreconfigitem('ui', 'supportcontact',
661 coreconfigitem('ui', 'supportcontact',
662 default=None,
662 default=None,
663 )
663 )
664 coreconfigitem('ui', 'textwidth',
664 coreconfigitem('ui', 'textwidth',
665 default=78,
665 default=78,
666 )
666 )
667 coreconfigitem('ui', 'timeout',
667 coreconfigitem('ui', 'timeout',
668 default='600',
668 default='600',
669 )
669 )
670 coreconfigitem('ui', 'traceback',
670 coreconfigitem('ui', 'traceback',
671 default=False,
671 default=False,
672 )
672 )
673 coreconfigitem('ui', 'tweakdefaults',
673 coreconfigitem('ui', 'tweakdefaults',
674 default=False,
674 default=False,
675 )
675 )
676 coreconfigitem('ui', 'usehttp2',
676 coreconfigitem('ui', 'usehttp2',
677 default=False,
677 default=False,
678 )
678 )
679 coreconfigitem('ui', 'username',
679 coreconfigitem('ui', 'username',
680 alias=[('ui', 'user')]
680 alias=[('ui', 'user')]
681 )
681 )
682 coreconfigitem('ui', 'verbose',
682 coreconfigitem('ui', 'verbose',
683 default=False,
683 default=False,
684 )
684 )
685 coreconfigitem('verify', 'skipflags',
685 coreconfigitem('verify', 'skipflags',
686 default=None,
686 default=None,
687 )
687 )
688 coreconfigitem('web', 'accesslog',
688 coreconfigitem('web', 'accesslog',
689 default='-',
689 default='-',
690 )
690 )
691 coreconfigitem('web', 'address',
691 coreconfigitem('web', 'address',
692 default='',
692 default='',
693 )
693 )
694 coreconfigitem('web', 'allow_archive',
694 coreconfigitem('web', 'allow_archive',
695 default=list,
695 default=list,
696 )
696 )
697 coreconfigitem('web', 'allow_read',
697 coreconfigitem('web', 'allow_read',
698 default=list,
698 default=list,
699 )
699 )
700 coreconfigitem('web', 'baseurl',
700 coreconfigitem('web', 'baseurl',
701 default=None,
701 default=None,
702 )
702 )
703 coreconfigitem('web', 'cacerts',
703 coreconfigitem('web', 'cacerts',
704 default=None,
704 default=None,
705 )
705 )
706 coreconfigitem('web', 'certificate',
706 coreconfigitem('web', 'certificate',
707 default=None,
707 default=None,
708 )
708 )
709 coreconfigitem('web', 'collapse',
709 coreconfigitem('web', 'collapse',
710 default=False,
710 default=False,
711 )
711 )
712 coreconfigitem('web', 'csp',
712 coreconfigitem('web', 'csp',
713 default=None,
713 default=None,
714 )
714 )
715 coreconfigitem('web', 'deny_read',
715 coreconfigitem('web', 'deny_read',
716 default=list,
716 default=list,
717 )
717 )
718 coreconfigitem('web', 'descend',
718 coreconfigitem('web', 'descend',
719 default=True,
719 default=True,
720 )
720 )
721 coreconfigitem('web', 'description',
721 coreconfigitem('web', 'description',
722 default="",
722 default="",
723 )
723 )
724 coreconfigitem('web', 'encoding',
724 coreconfigitem('web', 'encoding',
725 default=lambda: encoding.encoding,
725 default=lambda: encoding.encoding,
726 )
726 )
727 coreconfigitem('web', 'errorlog',
727 coreconfigitem('web', 'errorlog',
728 default='-',
728 default='-',
729 )
729 )
730 coreconfigitem('web', 'ipv6',
730 coreconfigitem('web', 'ipv6',
731 default=False,
731 default=False,
732 )
732 )
733 coreconfigitem('web', 'port',
733 coreconfigitem('web', 'port',
734 default=8000,
734 default=8000,
735 )
735 )
736 coreconfigitem('web', 'prefix',
736 coreconfigitem('web', 'prefix',
737 default='',
737 default='',
738 )
738 )
739 coreconfigitem('web', 'push_ssl',
740 default=True,
741 )
739 coreconfigitem('web', 'refreshinterval',
742 coreconfigitem('web', 'refreshinterval',
740 default=20,
743 default=20,
741 )
744 )
742 coreconfigitem('web', 'stripes',
745 coreconfigitem('web', 'stripes',
743 default=1,
746 default=1,
744 )
747 )
745 coreconfigitem('web', 'style',
748 coreconfigitem('web', 'style',
746 default='paper',
749 default='paper',
747 )
750 )
748 coreconfigitem('web', 'templates',
751 coreconfigitem('web', 'templates',
749 default=None,
752 default=None,
750 )
753 )
751 coreconfigitem('web', 'view',
754 coreconfigitem('web', 'view',
752 default='served',
755 default='served',
753 )
756 )
754 coreconfigitem('worker', 'backgroundclose',
757 coreconfigitem('worker', 'backgroundclose',
755 default=dynamicdefault,
758 default=dynamicdefault,
756 )
759 )
757 # Windows defaults to a limit of 512 open files. A buffer of 128
760 # Windows defaults to a limit of 512 open files. A buffer of 128
758 # should give us enough headway.
761 # should give us enough headway.
759 coreconfigitem('worker', 'backgroundclosemaxqueue',
762 coreconfigitem('worker', 'backgroundclosemaxqueue',
760 default=384,
763 default=384,
761 )
764 )
762 coreconfigitem('worker', 'backgroundcloseminfilecount',
765 coreconfigitem('worker', 'backgroundcloseminfilecount',
763 default=2048,
766 default=2048,
764 )
767 )
765 coreconfigitem('worker', 'backgroundclosethreadcount',
768 coreconfigitem('worker', 'backgroundclosethreadcount',
766 default=4,
769 default=4,
767 )
770 )
768 coreconfigitem('worker', 'numcpus',
771 coreconfigitem('worker', 'numcpus',
769 default=None,
772 default=None,
770 )
773 )
@@ -1,233 +1,233 b''
1 # hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod
1 # hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod
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, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 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 base64
11 import base64
12 import errno
12 import errno
13 import mimetypes
13 import mimetypes
14 import os
14 import os
15 import uuid
15 import uuid
16
16
17 from .. import (
17 from .. import (
18 encoding,
18 encoding,
19 pycompat,
19 pycompat,
20 util,
20 util,
21 )
21 )
22
22
23 httpserver = util.httpserver
23 httpserver = util.httpserver
24
24
25 HTTP_OK = 200
25 HTTP_OK = 200
26 HTTP_NOT_MODIFIED = 304
26 HTTP_NOT_MODIFIED = 304
27 HTTP_BAD_REQUEST = 400
27 HTTP_BAD_REQUEST = 400
28 HTTP_UNAUTHORIZED = 401
28 HTTP_UNAUTHORIZED = 401
29 HTTP_FORBIDDEN = 403
29 HTTP_FORBIDDEN = 403
30 HTTP_NOT_FOUND = 404
30 HTTP_NOT_FOUND = 404
31 HTTP_METHOD_NOT_ALLOWED = 405
31 HTTP_METHOD_NOT_ALLOWED = 405
32 HTTP_SERVER_ERROR = 500
32 HTTP_SERVER_ERROR = 500
33
33
34
34
35 def ismember(ui, username, userlist):
35 def ismember(ui, username, userlist):
36 """Check if username is a member of userlist.
36 """Check if username is a member of userlist.
37
37
38 If userlist has a single '*' member, all users are considered members.
38 If userlist has a single '*' member, all users are considered members.
39 Can be overridden by extensions to provide more complex authorization
39 Can be overridden by extensions to provide more complex authorization
40 schemes.
40 schemes.
41 """
41 """
42 return userlist == ['*'] or username in userlist
42 return userlist == ['*'] or username in userlist
43
43
44 def checkauthz(hgweb, req, op):
44 def checkauthz(hgweb, req, op):
45 '''Check permission for operation based on request data (including
45 '''Check permission for operation based on request data (including
46 authentication info). Return if op allowed, else raise an ErrorResponse
46 authentication info). Return if op allowed, else raise an ErrorResponse
47 exception.'''
47 exception.'''
48
48
49 user = req.env.get('REMOTE_USER')
49 user = req.env.get('REMOTE_USER')
50
50
51 deny_read = hgweb.configlist('web', 'deny_read')
51 deny_read = hgweb.configlist('web', 'deny_read')
52 if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)):
52 if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)):
53 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
53 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
54
54
55 allow_read = hgweb.configlist('web', 'allow_read')
55 allow_read = hgweb.configlist('web', 'allow_read')
56 if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)):
56 if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)):
57 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
57 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
58
58
59 if op == 'pull' and not hgweb.allowpull:
59 if op == 'pull' and not hgweb.allowpull:
60 raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized')
60 raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized')
61 elif op == 'pull' or op is None: # op is None for interface requests
61 elif op == 'pull' or op is None: # op is None for interface requests
62 return
62 return
63
63
64 # enforce that you can only push using POST requests
64 # enforce that you can only push using POST requests
65 if req.env['REQUEST_METHOD'] != 'POST':
65 if req.env['REQUEST_METHOD'] != 'POST':
66 msg = 'push requires POST request'
66 msg = 'push requires POST request'
67 raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
67 raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
68
68
69 # require ssl by default for pushing, auth info cannot be sniffed
69 # require ssl by default for pushing, auth info cannot be sniffed
70 # and replayed
70 # and replayed
71 scheme = req.env.get('wsgi.url_scheme')
71 scheme = req.env.get('wsgi.url_scheme')
72 if hgweb.configbool('web', 'push_ssl', True) and scheme != 'https':
72 if hgweb.configbool('web', 'push_ssl') and scheme != 'https':
73 raise ErrorResponse(HTTP_FORBIDDEN, 'ssl required')
73 raise ErrorResponse(HTTP_FORBIDDEN, 'ssl required')
74
74
75 deny = hgweb.configlist('web', 'deny_push')
75 deny = hgweb.configlist('web', 'deny_push')
76 if deny and (not user or ismember(hgweb.repo.ui, user, deny)):
76 if deny and (not user or ismember(hgweb.repo.ui, user, deny)):
77 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
77 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
78
78
79 allow = hgweb.configlist('web', 'allow_push')
79 allow = hgweb.configlist('web', 'allow_push')
80 if not (allow and ismember(hgweb.repo.ui, user, allow)):
80 if not (allow and ismember(hgweb.repo.ui, user, allow)):
81 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
81 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
82
82
83 # Hooks for hgweb permission checks; extensions can add hooks here.
83 # Hooks for hgweb permission checks; extensions can add hooks here.
84 # Each hook is invoked like this: hook(hgweb, request, operation),
84 # Each hook is invoked like this: hook(hgweb, request, operation),
85 # where operation is either read, pull or push. Hooks should either
85 # where operation is either read, pull or push. Hooks should either
86 # raise an ErrorResponse exception, or just return.
86 # raise an ErrorResponse exception, or just return.
87 #
87 #
88 # It is possible to do both authentication and authorization through
88 # It is possible to do both authentication and authorization through
89 # this.
89 # this.
90 permhooks = [checkauthz]
90 permhooks = [checkauthz]
91
91
92
92
93 class ErrorResponse(Exception):
93 class ErrorResponse(Exception):
94 def __init__(self, code, message=None, headers=None):
94 def __init__(self, code, message=None, headers=None):
95 if message is None:
95 if message is None:
96 message = _statusmessage(code)
96 message = _statusmessage(code)
97 Exception.__init__(self, message)
97 Exception.__init__(self, message)
98 self.code = code
98 self.code = code
99 if headers is None:
99 if headers is None:
100 headers = []
100 headers = []
101 self.headers = headers
101 self.headers = headers
102
102
103 class continuereader(object):
103 class continuereader(object):
104 def __init__(self, f, write):
104 def __init__(self, f, write):
105 self.f = f
105 self.f = f
106 self._write = write
106 self._write = write
107 self.continued = False
107 self.continued = False
108
108
109 def read(self, amt=-1):
109 def read(self, amt=-1):
110 if not self.continued:
110 if not self.continued:
111 self.continued = True
111 self.continued = True
112 self._write('HTTP/1.1 100 Continue\r\n\r\n')
112 self._write('HTTP/1.1 100 Continue\r\n\r\n')
113 return self.f.read(amt)
113 return self.f.read(amt)
114
114
115 def __getattr__(self, attr):
115 def __getattr__(self, attr):
116 if attr in ('close', 'readline', 'readlines', '__iter__'):
116 if attr in ('close', 'readline', 'readlines', '__iter__'):
117 return getattr(self.f, attr)
117 return getattr(self.f, attr)
118 raise AttributeError
118 raise AttributeError
119
119
120 def _statusmessage(code):
120 def _statusmessage(code):
121 responses = httpserver.basehttprequesthandler.responses
121 responses = httpserver.basehttprequesthandler.responses
122 return responses.get(code, ('Error', 'Unknown error'))[0]
122 return responses.get(code, ('Error', 'Unknown error'))[0]
123
123
124 def statusmessage(code, message=None):
124 def statusmessage(code, message=None):
125 return '%d %s' % (code, message or _statusmessage(code))
125 return '%d %s' % (code, message or _statusmessage(code))
126
126
127 def get_stat(spath, fn):
127 def get_stat(spath, fn):
128 """stat fn if it exists, spath otherwise"""
128 """stat fn if it exists, spath otherwise"""
129 cl_path = os.path.join(spath, fn)
129 cl_path = os.path.join(spath, fn)
130 if os.path.exists(cl_path):
130 if os.path.exists(cl_path):
131 return os.stat(cl_path)
131 return os.stat(cl_path)
132 else:
132 else:
133 return os.stat(spath)
133 return os.stat(spath)
134
134
135 def get_mtime(spath):
135 def get_mtime(spath):
136 return get_stat(spath, "00changelog.i").st_mtime
136 return get_stat(spath, "00changelog.i").st_mtime
137
137
138 def ispathsafe(path):
138 def ispathsafe(path):
139 """Determine if a path is safe to use for filesystem access."""
139 """Determine if a path is safe to use for filesystem access."""
140 parts = path.split('/')
140 parts = path.split('/')
141 for part in parts:
141 for part in parts:
142 if (part in ('', os.curdir, os.pardir) or
142 if (part in ('', os.curdir, os.pardir) or
143 pycompat.ossep in part or
143 pycompat.ossep in part or
144 pycompat.osaltsep is not None and pycompat.osaltsep in part):
144 pycompat.osaltsep is not None and pycompat.osaltsep in part):
145 return False
145 return False
146
146
147 return True
147 return True
148
148
149 def staticfile(directory, fname, req):
149 def staticfile(directory, fname, req):
150 """return a file inside directory with guessed Content-Type header
150 """return a file inside directory with guessed Content-Type header
151
151
152 fname always uses '/' as directory separator and isn't allowed to
152 fname always uses '/' as directory separator and isn't allowed to
153 contain unusual path components.
153 contain unusual path components.
154 Content-Type is guessed using the mimetypes module.
154 Content-Type is guessed using the mimetypes module.
155 Return an empty string if fname is illegal or file not found.
155 Return an empty string if fname is illegal or file not found.
156
156
157 """
157 """
158 if not ispathsafe(fname):
158 if not ispathsafe(fname):
159 return
159 return
160
160
161 fpath = os.path.join(*fname.split('/'))
161 fpath = os.path.join(*fname.split('/'))
162 if isinstance(directory, str):
162 if isinstance(directory, str):
163 directory = [directory]
163 directory = [directory]
164 for d in directory:
164 for d in directory:
165 path = os.path.join(d, fpath)
165 path = os.path.join(d, fpath)
166 if os.path.exists(path):
166 if os.path.exists(path):
167 break
167 break
168 try:
168 try:
169 os.stat(path)
169 os.stat(path)
170 ct = mimetypes.guess_type(path)[0] or "text/plain"
170 ct = mimetypes.guess_type(path)[0] or "text/plain"
171 with open(path, 'rb') as fh:
171 with open(path, 'rb') as fh:
172 data = fh.read()
172 data = fh.read()
173
173
174 req.respond(HTTP_OK, ct, body=data)
174 req.respond(HTTP_OK, ct, body=data)
175 except TypeError:
175 except TypeError:
176 raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename')
176 raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename')
177 except OSError as err:
177 except OSError as err:
178 if err.errno == errno.ENOENT:
178 if err.errno == errno.ENOENT:
179 raise ErrorResponse(HTTP_NOT_FOUND)
179 raise ErrorResponse(HTTP_NOT_FOUND)
180 else:
180 else:
181 raise ErrorResponse(HTTP_SERVER_ERROR,
181 raise ErrorResponse(HTTP_SERVER_ERROR,
182 encoding.strtolocal(err.strerror))
182 encoding.strtolocal(err.strerror))
183
183
184 def paritygen(stripecount, offset=0):
184 def paritygen(stripecount, offset=0):
185 """count parity of horizontal stripes for easier reading"""
185 """count parity of horizontal stripes for easier reading"""
186 if stripecount and offset:
186 if stripecount and offset:
187 # account for offset, e.g. due to building the list in reverse
187 # account for offset, e.g. due to building the list in reverse
188 count = (stripecount + offset) % stripecount
188 count = (stripecount + offset) % stripecount
189 parity = (stripecount + offset) / stripecount & 1
189 parity = (stripecount + offset) / stripecount & 1
190 else:
190 else:
191 count = 0
191 count = 0
192 parity = 0
192 parity = 0
193 while True:
193 while True:
194 yield parity
194 yield parity
195 count += 1
195 count += 1
196 if stripecount and count >= stripecount:
196 if stripecount and count >= stripecount:
197 parity = 1 - parity
197 parity = 1 - parity
198 count = 0
198 count = 0
199
199
200 def get_contact(config):
200 def get_contact(config):
201 """Return repo contact information or empty string.
201 """Return repo contact information or empty string.
202
202
203 web.contact is the primary source, but if that is not set, try
203 web.contact is the primary source, but if that is not set, try
204 ui.username or $EMAIL as a fallback to display something useful.
204 ui.username or $EMAIL as a fallback to display something useful.
205 """
205 """
206 return (config("web", "contact") or
206 return (config("web", "contact") or
207 config("ui", "username") or
207 config("ui", "username") or
208 encoding.environ.get("EMAIL") or "")
208 encoding.environ.get("EMAIL") or "")
209
209
210 def caching(web, req):
210 def caching(web, req):
211 tag = r'W/"%d"' % web.mtime
211 tag = r'W/"%d"' % web.mtime
212 if req.env.get('HTTP_IF_NONE_MATCH') == tag:
212 if req.env.get('HTTP_IF_NONE_MATCH') == tag:
213 raise ErrorResponse(HTTP_NOT_MODIFIED)
213 raise ErrorResponse(HTTP_NOT_MODIFIED)
214 req.headers.append(('ETag', tag))
214 req.headers.append(('ETag', tag))
215
215
216 def cspvalues(ui):
216 def cspvalues(ui):
217 """Obtain the Content-Security-Policy header and nonce value.
217 """Obtain the Content-Security-Policy header and nonce value.
218
218
219 Returns a 2-tuple of the CSP header value and the nonce value.
219 Returns a 2-tuple of the CSP header value and the nonce value.
220
220
221 First value is ``None`` if CSP isn't enabled. Second value is ``None``
221 First value is ``None`` if CSP isn't enabled. Second value is ``None``
222 if CSP isn't enabled or if the CSP header doesn't need a nonce.
222 if CSP isn't enabled or if the CSP header doesn't need a nonce.
223 """
223 """
224 # Don't allow untrusted CSP setting since it be disable protections
224 # Don't allow untrusted CSP setting since it be disable protections
225 # from a trusted/global source.
225 # from a trusted/global source.
226 csp = ui.config('web', 'csp', untrusted=False)
226 csp = ui.config('web', 'csp', untrusted=False)
227 nonce = None
227 nonce = None
228
228
229 if csp and '%nonce%' in csp:
229 if csp and '%nonce%' in csp:
230 nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip('=')
230 nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip('=')
231 csp = csp.replace('%nonce%', nonce)
231 csp = csp.replace('%nonce%', nonce)
232
232
233 return csp, nonce
233 return csp, nonce
General Comments 0
You need to be logged in to leave comments. Login now