[PATCH 4 of 5 hgweb-thread-isolation] hgweb: move some config options to requestcontext

Gregory Szorc gregory.szorc at gmail.com
Tue Sep 1 14:11:10 CDT 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1440280961 25200
#      Sat Aug 22 15:02:41 2015 -0700
# Node ID 2d87a8d17a3d35346f595cfcb32db233f5742ee0
# Parent  a3b9bcb5eaa7d0fae4d751c223cfd5b321f4bb8f
hgweb: move some config options to requestcontext

Various config options from the repository were stored on the
hgweb instance. While unlikely, there could be race conditions between
a new request updating these values and an in-flight request seeing both
old and new values, leading to weird results.

We move some of options/attributes from hgweb to requestcontext.

As part of this, we establish config* helpers on requestcontext. As
part of the move, we changed int() casts to configint() calls. The
int() usage likely predates the existence of configint().

We also removed config option updating from once every refresh to every
request. I don't believe obtaining config options is expensive enough to
warrant only doing when the repository has changed.

The excessive use of object.__setattr__ is unfortunate. But it will
eventually disappear once the proxy is no longer necessary.

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -71,16 +71,45 @@ class requestcontext(object):
     def __init__(self, app):
         object.__setattr__(self, 'app', app)
         object.__setattr__(self, 'repo', app.repo)
 
+        object.__setattr__(self, 'maxchanges',
+                           self.configint('web', 'maxchanges', 10))
+        object.__setattr__(self, 'stripecount',
+                           self.configint('web', 'stripes', 1))
+        object.__setattr__(self, 'maxshortchanges',
+                           self.configint('web', 'maxshortchanges', 60))
+        object.__setattr__(self, 'maxfiles',
+                           self.configint('web', 'maxfiles', 10))
+        object.__setattr__(self, 'allowpull',
+                           self.configbool('web', 'allowpull', True))
+
     # Proxy unknown reads and writes to the application instance
     # until everything is moved to us.
     def __getattr__(self, name):
         return getattr(self.app, name)
 
     def __setattr__(self, name, value):
         return setattr(self.app, name, value)
 
+    # Servers are often run by a user different from the repo owner.
+    # Trust the settings from the .hg/hgrc files by default.
+    def config(self, section, name, default=None, untrusted=True):
+        return self.repo.ui.config(section, name, default,
+                                   untrusted=untrusted)
+
+    def configbool(self, section, name, default=False, untrusted=True):
+        return self.repo.ui.configbool(section, name, default,
+                                       untrusted=untrusted)
+
+    def configint(self, section, name, default=None, untrusted=True):
+        return self.repo.ui.configint(section, name, default,
+                                      untrusted=untrusted)
+
+    def configlist(self, section, name, default=None, untrusted=True):
+        return self.repo.ui.configlist(section, name, default,
+                                       untrusted=untrusted)
+
 class hgweb(object):
     """HTTP server for individual repositories.
 
     Instances of this class serve HTTP responses for a particular
@@ -116,9 +145,8 @@ class hgweb(object):
         self.repostate = ((-1, -1), (-1, -1))
         self.mtime = -1
         self.reponame = name
         self.archives = 'zip', 'gz', 'bz2'
-        self.stripecount = 1
         # a repo owner may set web.templates in .hg/hgrc to get any file
         # readable by the user running the CGI script
         self.templatepath = self.config('web', 'templates')
         self.websubtable = self.loadwebsub()
@@ -169,14 +197,8 @@ class hgweb(object):
         # changes made less than a second ago
         if repostate != self.repostate:
             r = hg.repository(self.repo.baseui, self.repo.url())
             self.repo = self._getview(r)
-            self.maxchanges = int(self.config("web", "maxchanges", 10))
-            self.stripecount = int(self.config("web", "stripes", 1))
-            self.maxshortchanges = int(self.config("web", "maxshortchanges",
-                                                   60))
-            self.maxfiles = int(self.config("web", "maxfiles", 10))
-            self.allowpull = self.configbool("web", "allowpull", True)
             encoding.encoding = self.config("web", "encoding",
                                             encoding.encoding)
             # update these last to avoid threads seeing empty settings
             self.repostate = repostate


More information about the Mercurial-devel mailing list