changeset 317:01221c791547

Only connect to the Mercurial command server when needed. Remove (probably?) unnecessary locking.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 09 Oct 2014 13:05:28 -0700
parents 61902f36c789
children 4d22159b1836
files wikked/scm/mercurial.py
diffstat 1 files changed, 50 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/wikked/scm/mercurial.py	Wed Oct 08 23:27:00 2014 -0700
+++ b/wikked/scm/mercurial.py	Thu Oct 09 13:05:28 2014 -0700
@@ -190,56 +190,58 @@
 cl_lock = threading.Lock()
 
 
+def create_hg_client(root):
+    logger.debug("Spawning Mercurial command server at: %s" % root)
+    import hglib
+    global hg_client
+    hg_client = hglib.open(root)
+
+    def shutdown_commandserver(num, frame):
+        global hg_client
+        if hg_client is not None:
+            with cl_lock:
+                if hg_client is not None:
+                    logger.debug("Shutting down Mercurial command server.")
+                    hg_client.close()
+                    hg_client = None
+    import atexit
+    atexit.register(shutdown_commandserver, None, None)
+    try:
+        import signal
+        signal.signal(signal.SIGTERM, shutdown_commandserver)
+    except:
+        # `mod_wsgi` prevents adding stuff to `SIGTERM`
+        # so let's not make a big deal if this doesn't
+        # go through.
+        pass
+
+
 class MercurialCommandServerSourceControl(MercurialBaseSourceControl):
     def __init__(self, root, client=None):
         MercurialBaseSourceControl.__init__(self, root)
-        self.client = client
+        self._client = client
 
     def _initRepo(self, root):
         exe = ['hg', 'init', root]
         logger.debug("Running Mercurial: " + str(exe))
         return subprocess.check_output(exe)
 
-    def _doStart(self):
-        if self.client is None:
+    @property
+    def client(self):
+        if self._client is None:
             if hg_client is None:
                 with cl_lock:
                     if hg_client is None:
-                        self._createServer()
-                self.client = hg_client
+                        create_hg_client(self.root)
+                self._client = hg_client
             else:
                 logger.debug("Re-using existing Mercurial command server.")
-                self.client = hg_client
-
-    def _createServer(self):
-        logger.debug("Spawning Mercurial command server.")
-        import hglib
-        global hg_client
-        hg_client = hglib.open(self.root)
-
-        def shutdown_commandserver(num, frame):
-            global hg_client
-            if hg_client is not None:
-                with cl_lock:
-                    if hg_client is not None:
-                        logger.debug("Shutting down Mercurial command server.")
-                        hg_client.close()
-                        hg_client = None
-        import atexit
-        atexit.register(shutdown_commandserver, None, None)
-        try:
-            import signal
-            signal.signal(signal.SIGTERM, shutdown_commandserver)
-        except:
-            # `mod_wsgi` prevents adding stuff to `SIGTERM`
-            # so let's not make a big deal if this doesn't
-            # go through.
-            pass
+                self._client = hg_client
+        return self._client
 
     def getHistory(self, path=None, limit=10, after_rev=None):
         if path is not None:
-            with cl_lock:
-                status = self.client.status(include=[path])
+            status = self.client.status(include=[path])
             if len(status) > 0 and status[0] == '?':
                 return []
 
@@ -251,14 +253,12 @@
 
         needs_files = False
         if path is not None:
-            with cl_lock:
-                repo_revs = self.client.log(files=[path], follow=True,
-                                            limit=limit, revrange=rev)
+            repo_revs = self.client.log(files=[path], follow=True,
+                                        limit=limit, revrange=rev)
         else:
             needs_files = True
-            with cl_lock:
-                repo_revs = self.client.log(follow=True, limit=limit,
-                                            revrange=rev)
+            repo_revs = self.client.log(follow=True, limit=limit,
+                                        revrange=rev)
         revisions = []
         for rev in repo_revs:
             r = Revision(rev.node)
@@ -267,8 +267,7 @@
             r.timestamp = time.mktime(rev.date.timetuple())
             r.description = unicode(rev.desc)
             if needs_files:
-                with cl_lock:
-                    rev_statuses = self.client.status(change=rev.node)
+                rev_statuses = self.client.status(change=rev.node)
                 for rev_status in rev_statuses:
                     r.files.append({
                         'path': rev_status[1].decode('utf-8', 'replace'),
@@ -278,8 +277,7 @@
         return revisions
 
     def getState(self, path):
-        with cl_lock:
-            statuses = self.client.status(include=[path])
+        statuses = self.client.status(include=[path])
         if len(statuses) == 0:
             return STATE_COMMITTED
         status = statuses[0]
@@ -290,14 +288,12 @@
         raise Exception("Unsupported status: %s" % status)
 
     def getRevision(self, path, rev):
-        with cl_lock:
-            return self.client.cat([path], rev=rev)
+        return self.client.cat([path], rev=rev)
 
     def diff(self, path, rev1, rev2):
-        with cl_lock:
-            if rev2 is None:
-                return self.client.diff(files=[path], change=rev1, git=True)
-            return self.client.diff(files=[path], revs=[rev1, rev2], git=True)
+        if rev2 is None:
+            return self.client.diff(files=[path], change=rev1, git=True)
+        return self.client.diff(files=[path], revs=[rev1, rev2], git=True)
 
     def commit(self, paths, op_meta):
         if 'message' not in op_meta or not op_meta['message']:
@@ -313,15 +309,13 @@
             args = cmdbuilder('commit', *paths,
                     debug=True, m=op_meta['message'], A=True,
                     **kwargs)
-            with cl_lock:
-                self.client.rawcommand(args)
+            self.client.rawcommand(args)
         except CommandError as e:
             raise SourceControlError('commit', e.out, e.args, e.out)
 
     def revert(self, paths=None):
-        with cl_lock:
-            if paths is not None:
-                self.client.revert(files=paths, nobackup=True)
-            else:
-                self.client.revert(all=True, nobackup=True)
+        if paths is not None:
+            self.client.revert(files=paths, nobackup=True)
+        else:
+            self.client.revert(all=True, nobackup=True)