bug 49377, make pushlog handle non-existing database on readonly repos, test and fix
authorAxel Hecht <l10n@mozilla.com>
Wed, 26 Nov 2008 13:57:37 +0100
changeset 55 6db4ef76c839
parent 54 e955a1f05004
child 56 cd5ef08c3002
push id29
push useraxel@mozilla.com
push dateWed, 26 Nov 2008 12:57:44 +0000
bugs49377
bug 49377, make pushlog handle non-existing database on readonly repos, test and fix
pushlog-feed.py
runtests.py
--- a/pushlog-feed.py
+++ b/pushlog-feed.py
@@ -63,16 +63,19 @@ class PushlogQuery:
         self.urlbase = urlbase
         self.tipsonly = tipsonly
         self.reponame = reponame
 
     def DoQuery(self):
         """Figure out what the query parameters are, and query the database
         using those parameters."""
         self.entries = []
+        if not self.conn:
+            # we didn't get a connection to the database, return empty
+            return
         if self.querystart == QueryType.COUNT and not self.userquery and not self.changesetquery:
             # Get entries from self.page, using self.querystart_value as
             # the number of pushes per page.
             try:
                 res = self.conn.execute("SELECT id, user, date FROM pushlog ORDER BY date DESC LIMIT ? OFFSET ?",
                                         (self.querystart_value,
                                          (self.page - 1) * self.querystart_value))
                 for (id,user,date) in res:
@@ -207,17 +210,20 @@ def pushlogSetup(repo, req):
     build a PushlogQuery object and populate it with data from the request.
     The returned query object will have its query already run, and
     its entries member can be read."""
     repopath = os.path.dirname(repo.path)
     reponame = os.path.basename(repopath)
     if reponame == '.hg':
         reponame = os.path.basename(os.path.dirname(repopath))
     pushdb = os.path.join(repo.path, "pushlog2.db")
-    conn = sqlite.connect(pushdb)
+    try:
+        conn = sqlite.connect(pushdb)
+    except sqlite.OperationalError:
+        conn = None
 
     if 'node' in req.form:
         page = int(req.form['node'][0])
     else:
         page = 1
 
     # figure out the urlbase
     proto = req.env.get('wsgi.url_scheme')
@@ -436,17 +442,20 @@ def pushes(web, req, tmpl):
     return tmpl('pushes', data=pushes_worker(query))
 
 def printpushlog(ui, repo, *args):
     """HG Command to print the pushlog data in JSON format."""
     from hgwebjson import HGJSONEncoder
     e = HGJSONEncoder()
     startID = len(args) and args[0] or 0
     endID = len(args) > 1 and args[1] or None
-    conn = sqlite.connect(os.path.join(repo.path, 'pushlog2.db'))
+    try:
+        conn = sqlite.connect(os.path.join(repo.path, 'pushlog2.db'))
+    except sqlite.OperationalError:
+        conn = None
     query = PushlogQuery(repo=repo, dbconn=conn)
     query.querystart = QueryType.PUSHID
     query.querystart_value = startID
     if endID is not None:
         query.queryend = QueryType.PUSHID
         query.queryend_value = endID
     query.DoQuery()
     print e.encode(pushes_worker(query))
--- a/runtests.py
+++ b/runtests.py
@@ -1,15 +1,16 @@
 #!/usr/bin/python
 # I'm sure this all only works on my mac, but that's ok for now.
 
 import unittest
 import os.path
 from subprocess import check_call, Popen, STDOUT, PIPE
 import os
+import stat
 from signal import SIGTERM
 from httplib import HTTPConnection
 from urllib import urlopen
 from time import sleep
 import simplejson
 import feedparser
 
 mydir = os.path.abspath(os.path.dirname(__file__))
@@ -60,31 +61,51 @@ class TestEmptyRepo(unittest.TestCase):
         os.mkdir(repodir)
         check_call(["hg","init",repodir])
         write_hgrc(repodir)
         ensure_templates()
         # now run hg serve on it
         self.hgwebprocess = Popen(["hg", "-R", repodir, "serve"], stdout=devnull, stderr=STDOUT)
         # give it a second to be ready
         sleep(1)
+        self.repodir = repodir
 
     def tearDown(self):
         # kill hgweb process
         if self.hgwebprocess is not None:
             os.kill(self.hgwebprocess.pid, SIGTERM)
             self.hgwebprocess = None
 
     def testemptyrepo(self):
         # just GET /pushlog and verify that it's 200 OK
         conn = HTTPConnection("localhost", 8000)
         conn.request("GET", "/pushlog")
         r = conn.getresponse()
         conn.close()
         self.assertEqual(r.status, 200, "empty pushlog should not error (got HTTP status %d, expected 200)" % r.status)
 
+    def testemptyreporeadonly(self):
+        # just GET /pushlog and verify that it's 200 OK
+        def rchmod(canWrite = False):
+            w = 0
+            if canWrite:
+                w = stat.S_IWRITE
+            for dir, subdirs, files in os.walk(self.repodir):
+                os.chmod(dir, stat.S_IREAD + stat.S_IEXEC + w)
+                for f in files:
+                    os.chmod(os.path.join(dir, f), stat.S_IREAD)
+            pass
+        rchmod()
+        conn = HTTPConnection("localhost", 8000)
+        conn.request("GET", "/pushlog")
+        r = conn.getresponse()
+        conn.close()
+        rchmod(True)
+        self.assertEqual(r.status, 200, "empty pushlog should not error (got HTTP status %d, expected 200)" % r.status)
+
 class TestPushlog(unittest.TestCase):
     hgwebprocess = None
     repodir = ''
 
     def setUp(self):
         "Untar the test repo and add the pushlog extension to it."
         # unpack the test repo
         repoarchive = os.path.join(mydir, "testdata/test-repo.tar.bz2")