changeset 197:d72c0587fae9

* Don't schedule/display builds for revisions where the repository directory is empty. Fixes #46. * Only display charts on build config page when reports are available. * BDB XML database is created lazily, i.e. only on write requests.
author cmlenz
date Tue, 13 Sep 2005 10:32:25 +0000
parents b5f7d8a4035e
children 6bb8e7a18072
files bitten/master.py bitten/store.py bitten/trac_ext/templates/bitten_config.cs bitten/trac_ext/tests/web_ui.py bitten/trac_ext/web_ui.py
diffstat 5 files changed, 75 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/master.py
+++ b/bitten/master.py
@@ -67,6 +67,21 @@
                           config.path)
                 node = repos.get_node(config.path)
                 for path, rev, chg in node.get_history():
+
+                    # Don't follow moves/copies
+                    if path != repos.normalize_path(config.path):
+                        break
+
+                    # Make sure the repository directory isn't empty at this
+                    # revision
+                    old_node = repos.get_node(path, rev)
+                    is_empty = True
+                    for entry in old_node.get_entries():
+                        is_empty = False
+                        break
+                    if is_empty:
+                        continue
+
                     enqueued = False
                     for platform in TargetPlatform.select(self.env,
                                                           config.name, db=db):
@@ -99,6 +114,9 @@
             return
         log.debug('Checking for pending builds...')
         for build in Build.select(self.env, status=Build.PENDING):
+            config = BuildConfig.fetch(self.env, name=build.config)
+            if not config.active:
+                continue
             for slave in self.slaves.get(build.platform, []):
                 active_builds = Build.select(self.env, slave=slave.name,
                                              status=Build.IN_PROGRESS)
--- a/bitten/store.py
+++ b/bitten/store.py
@@ -102,32 +102,31 @@
     def __init__(self, path):
         self.path = path
         self.mgr = dbxml.XmlManager()
-        if not os.path.exists(path):
-            self.container = self.mgr.createContainer(self.path)
-            ctxt = self.mgr.createUpdateContext()
-            for name, index in self.indices:
-                self.container.addIndex('', name, index, ctxt)
-        else:
-            self.container = self.mgr.openContainer(self.path)
 
     def delete(self, config=None, build=None, step=None, type=None):
+        container = self._open_container()
+        if not container:
+            return
         ctxt = self.mgr.createUpdateContext()
         for elem in self.query('return $reports', config=config, build=build,
                                step=step, type=type):
-            self.container.deleteDocument(elem._value.asDocument(), ctxt)
+            container.deleteDocument(elem._value.asDocument(), ctxt)
 
     def store(self, build, step, xml):
         assert xml.name == 'report' and 'type' in xml.attr
+        container = self._open_container(create=True)
         ctxt = self.mgr.createUpdateContext()
         doc = self.mgr.createDocument()
         doc.setContent(str(xml))
         doc.setMetaData('', 'config', dbxml.XmlValue(build.config))
         doc.setMetaData('', 'build', dbxml.XmlValue(build.id))
         doc.setMetaData('', 'step', dbxml.XmlValue(step.name))
-        self.container.putDocument(doc, ctxt, dbxml.DBXML_GEN_NAME)
+        container.putDocument(doc, ctxt, dbxml.DBXML_GEN_NAME)
 
-    def query(self, xquery, config=None, build=None, step=None,
-                     type=None):
+    def query(self, xquery, config=None, build=None, step=None, type=None):
+        container = self._open_container()
+        if not container:
+            return
         ctxt = self.mgr.createQueryContext()
 
         constraints = []
@@ -143,14 +142,26 @@
         query = "let $reports := collection('%s')/report" % self.path
         if constraints:
             query += '[%s]' % ' and '.join(constraints)
-        query += '\n' + xquery
+        query += '\n' + (xquery or 'return $reports')
 
         results = self.mgr.query(query, ctxt)
         for value in results:
             yield BDBXMLReportStore.XmlValueAdapter(value)
 
     def retrieve(self, build, step=None, type=None):
-        return self.query('return $reports', build=build, step=step, type=type)
+        return self.query('', build=build, step=step, type=type)
+
+    def _open_container(self, create=False):
+        if not os.path.exists(self.path):
+            if not create:
+                return None
+            container = self.mgr.createContainer(self.path)
+            ctxt = self.mgr.createUpdateContext()
+            for name, index in self.indices:
+                container.addIndex('', name, index, ctxt)
+        else:
+            container = self.mgr.openContainer(self.path)
+        return container
 
 
 def get_store(env):
--- a/bitten/trac_ext/templates/bitten_config.cs
+++ b/bitten/trac_ext/templates/bitten_config.cs
@@ -133,7 +133,7 @@
      <input type="submit" value="Delete configuration" />
     </div></form><?cs /if ?><?cs
    /if ?><?cs
-   if:len(config.platforms) ?>
+   if:len(config.platforms) && len(config.builds) ?>
     <table class="listing" id="builds"><thead><tr>
      <th class="chgset" abbrev="Changeset">Chgset</th><?cs
      each:platform = config.platforms ?><th><?cs var:platform.name ?><?cs
--- a/bitten/trac_ext/tests/web_ui.py
+++ b/bitten/trac_ext/tests/web_ui.py
@@ -7,6 +7,8 @@
 # you should have received as part of this distribution. The terms
 # are also available at http://bitten.cmlenz.net/wiki/License.
 
+import shutil
+import tempfile
 import unittest
 
 from trac.perm import PermissionCache, PermissionSystem
@@ -23,6 +25,7 @@
 
     def setUp(self):
         self.env = EnvironmentStub()
+        self.env.path = tempfile.mkdtemp()
 
         # Create tables
         db = self.env.get_db_cnx()
@@ -39,6 +42,9 @@
         repos = Mock(get_node=lambda path: Mock(get_history=lambda: []))
         self.env.get_repository = lambda x: repos
 
+    def tearDown(self):
+        shutil.rmtree(self.env.path)
+
     def test_overview(self):
         PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
         req = Mock(Request, cgi_location='', path_info='/build', args={},
--- a/bitten/trac_ext/web_ui.py
+++ b/bitten/trac_ext/web_ui.py
@@ -315,18 +315,37 @@
             {'name': platform.name, 'id': platform.id} for platform in platforms
         ]
 
-        req.hdf['config.charts'] = [
-            {'href': self.env.href.build(config.name, 'chart/unittest')},
-            {'href': self.env.href.build(config.name, 'chart/trace')}
-        ]
-        charts_license = self.config.get('bitten', 'charts_license')
-        if charts_license:
-            req.hdf['config.charts_license'] = escape(charts_license)
+        store = get_store(self.env)
+        has_reports = False
+        for report in  store.query('', config=config):
+            has_reports = True
+            break
+
+        if has_reports:
+            req.hdf['config.charts'] = [
+                {'href': self.env.href.build(config.name, 'chart/unittest')},
+                {'href': self.env.href.build(config.name, 'chart/trace')}
+            ]
+            charts_license = self.config.get('bitten', 'charts_license')
+            if charts_license:
+                req.hdf['config.charts_license'] = escape(charts_license)
 
         repos = self.env.get_repository(req.authname)
         try:
             root = repos.get_node(config.path)
             for idx, (path, rev, chg) in enumerate(root.get_history()):
+                # Don't follow moves/copies
+                if path != config.path:
+                    break
+                # If the directory was empty at that revision, it isn't built
+                old_node = repos.get_node(path, rev)
+                is_empty = True
+                for entry in old_node.get_entries():
+                    is_empty = False
+                    break
+                if is_empty:
+                    continue
+
                 prefix = 'config.builds.%d' % rev
                 req.hdf[prefix + '.href'] = self.env.href.changeset(rev)
                 for build in Build.select(self.env, config=config.name, rev=rev):
Copyright (C) 2012-2017 Edgewall Software