comparison mercurial/hgweb/hgweb_mod.py @ 26217:0d0a0837895d

hgweb: remove proxy to hgweb instance We were temporarily routing attributes until all request-specific attributes from hgweb were moved to requestcontext. We have finally reached that juncture and we can remove the proxy. At this point, only the repo instance is prone to race conditions between threads. This will be dealt with shortly.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 22 Aug 2015 17:50:28 -0700
parents ea489d94e1dc
children 7d45ec47c0af
comparison
equal deleted inserted replaced
26216:e86d12404d69 26217:0d0a0837895d
65 Servers can be multi-threaded. Holding state on the WSGI application 65 Servers can be multi-threaded. Holding state on the WSGI application
66 is prone to race conditions. Instances of this class exist to hold 66 is prone to race conditions. Instances of this class exist to hold
67 mutable and race-free state for requests. 67 mutable and race-free state for requests.
68 """ 68 """
69 def __init__(self, app): 69 def __init__(self, app):
70 object.__setattr__(self, 'app', app) 70 self.repo = app.repo
71 object.__setattr__(self, 'repo', app.repo) 71 self.reponame = app.reponame
72 object.__setattr__(self, 'reponame', app.reponame) 72
73 73 self.archives = ('zip', 'gz', 'bz2')
74 object.__setattr__(self, 'archives', ('zip', 'gz', 'bz2')) 74
75 75 self.maxchanges = self.configint('web', 'maxchanges', 10)
76 object.__setattr__(self, 'maxchanges', 76 self.stripecount = self.configint('web', 'stripes', 1)
77 self.configint('web', 'maxchanges', 10)) 77 self.maxshortchanges = self.configint('web', 'maxshortchanges', 60)
78 object.__setattr__(self, 'stripecount', 78 self.maxfiles = self.configint('web', 'maxfiles', 10)
79 self.configint('web', 'stripes', 1)) 79 self.allowpull = self.configbool('web', 'allowpull', True)
80 object.__setattr__(self, 'maxshortchanges',
81 self.configint('web', 'maxshortchanges', 60))
82 object.__setattr__(self, 'maxfiles',
83 self.configint('web', 'maxfiles', 10))
84 object.__setattr__(self, 'allowpull',
85 self.configbool('web', 'allowpull', True))
86 80
87 # we use untrusted=False to prevent a repo owner from using 81 # we use untrusted=False to prevent a repo owner from using
88 # web.templates in .hg/hgrc to get access to any file readable 82 # web.templates in .hg/hgrc to get access to any file readable
89 # by the user running the CGI script 83 # by the user running the CGI script
90 object.__setattr__(self, 'templatepath', 84 self.templatepath = self.config('web', 'templates', untrusted=False)
91 self.config('web', 'templates', untrusted=False))
92 85
93 # This object is more expensive to build than simple config values. 86 # This object is more expensive to build than simple config values.
94 # It is shared across requests. The app will replace the object 87 # It is shared across requests. The app will replace the object
95 # if it is updated. Since this is a reference and nothing should 88 # if it is updated. Since this is a reference and nothing should
96 # modify the underlying object, it should be constant for the lifetime 89 # modify the underlying object, it should be constant for the lifetime
97 # of the request. 90 # of the request.
98 object.__setattr__(self, 'websubtable', app.websubtable) 91 self.websubtable = app.websubtable
99 92
100 # Proxy unknown reads and writes to the application instance
101 # until everything is moved to us.
102 def __getattr__(self, name):
103 return getattr(self.app, name)
104
105 def __setattr__(self, name, value):
106 return setattr(self.app, name, value)
107
108 # Servers are often run by a user different from the repo owner.
109 # Trust the settings from the .hg/hgrc files by default. 93 # Trust the settings from the .hg/hgrc files by default.
110 def config(self, section, name, default=None, untrusted=True): 94 def config(self, section, name, default=None, untrusted=True):
111 return self.repo.ui.config(section, name, default, 95 return self.repo.ui.config(section, name, default,
112 untrusted=untrusted) 96 untrusted=untrusted)
113 97
175 159
176 start = req.url[-1] == '?' and '&' or '?' 160 start = req.url[-1] == '?' and '&' or '?'
177 sessionvars = webutil.sessionvars(vars, start) 161 sessionvars = webutil.sessionvars(vars, start)
178 162
179 if not self.reponame: 163 if not self.reponame:
180 object.__setattr__(self, 'reponame', 164 self.reponame = (self.config('web', 'name')
181 (self.config('web', 'name') 165 or req.env.get('REPO_NAME')
182 or req.env.get('REPO_NAME') 166 or req.url.strip('/') or self.repo.root)
183 or req.url.strip('/') or self.repo.root))
184 167
185 def websubfilter(text): 168 def websubfilter(text):
186 return websub(text, self.websubtable) 169 return websub(text, self.websubtable)
187 170
188 # create the templater 171 # create the templater
396 caching(self, req) # sets ETag header or raises NOT_MODIFIED 379 caching(self, req) # sets ETag header or raises NOT_MODIFIED
397 if cmd not in webcommands.__all__: 380 if cmd not in webcommands.__all__:
398 msg = 'no such method: %s' % cmd 381 msg = 'no such method: %s' % cmd
399 raise ErrorResponse(HTTP_BAD_REQUEST, msg) 382 raise ErrorResponse(HTTP_BAD_REQUEST, msg)
400 elif cmd == 'file' and 'raw' in req.form.get('style', []): 383 elif cmd == 'file' and 'raw' in req.form.get('style', []):
401 # TODO convert to regular assignment once app proxy is removed. 384 rctx.ctype = ctype
402 object.__setattr__(rctx, 'ctype', ctype)
403 content = webcommands.rawfile(rctx, req, tmpl) 385 content = webcommands.rawfile(rctx, req, tmpl)
404 else: 386 else:
405 content = getattr(webcommands, cmd)(rctx, req, tmpl) 387 content = getattr(webcommands, cmd)(rctx, req, tmpl)
406 req.respond(HTTP_OK, ctype) 388 req.respond(HTTP_OK, ctype)
407 389