changeset 804:4c73a3cea9f5

Basic Trac 0.12 support, supporting just a `(default)` repository - essentially Trac 0.11 behaviour. Thanks to those that have contributed to #480 to get this working and tested.
author osimons
date Thu, 26 Aug 2010 22:48:37 +0000
parents a01248c3968c
children b62562828364
files bitten/admin.py bitten/master.py bitten/model.py bitten/notify.py bitten/queue.py bitten/tests/admin.py bitten/tests/queue.py bitten/web_ui.py
diffstat 8 files changed, 91 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/admin.py
+++ b/bitten/admin.py
@@ -273,19 +273,27 @@
             warnings.append('The field "name" may only contain letters, '
                             'digits, periods, or dashes.')
 
+        repos = self.env.get_repository(authname=req.authname)
+        if not repos:
+            warnings.append('No "(default)" Repository: Add a repository or '
+                            'alias named "(default)" to Trac.')
         path = req.args.get('path', '')
-        repos = self.env.get_repository(req.authname)
+        min_rev = req.args.get('min_rev') or None
         max_rev = req.args.get('max_rev') or None
-        try:
-            node = repos.get_node(path, max_rev)
-            assert node.isdir, '%s is not a directory' % node.path
-        except (AssertionError, TracError), e:
-            warnings.append('Invalid Repository Path "%s".' % path)
-        if req.args.get('min_rev'):
+
+        if repos:
+            path = repos.normalize_path(path)
             try:
-                repos.get_node(path, req.args.get('min_rev'))
-            except TracError, e:
-                warnings.append('Invalid Oldest Revision: %s.' % unicode(e))
+                node = repos.get_node(path, max_rev)
+                assert node.isdir, '%s is not a directory' % node.path
+            except (AssertionError, TracError), e:
+                warnings.append('Invalid Repository Path: "%s" does not exist '
+                                'within the "(default)" repository.' % path)
+            if min_rev:
+                try:
+                    repos.get_node(path, min_rev)
+                except TracError, e:
+                    warnings.append('Invalid Oldest Revision: %s.' % unicode(e))
 
         recipe_xml = req.args.get('recipe', '')
         if recipe_xml:
@@ -297,10 +305,10 @@
                 warnings.append('Invalid Recipe: %s.' % unicode(e))
 
         config.name = name
-        config.path = repos.normalize_path(path)
+        config.path = path
         config.recipe = recipe_xml
-        config.min_rev = req.args.get('min_rev')
-        config.max_rev = req.args.get('max_rev')
+        config.min_rev = min_rev
+        config.max_rev = max_rev
         config.label = req.args.get('label', config.name)
         config.description = req.args.get('description', '')
 
--- a/bitten/master.py
+++ b/bitten/master.py
@@ -156,7 +156,11 @@
         queue = BuildQueue(self.env, build_all=self.build_all,
                            stabilize_wait=self.stabilize_wait,
                            timeout=self.slave_timeout)
-        queue.populate()
+        try:
+            queue.populate()
+        except AssertionError, e:
+            self.log.error(e.message, exc_info=True)
+            self._send_error(req, HTTP_BAD_REQUEST, e.message)
 
         try:
             elem = xmlio.parse(req.read())
--- a/bitten/model.py
+++ b/bitten/model.py
@@ -193,6 +193,8 @@
         configuration. Returns utcmin if not specified.
         """
         repos = env.get_repository()
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
         
         min_time = utcmin
 	if self.min_rev:
@@ -208,6 +210,8 @@
         configuration. Returns utcmax if not specified.
         """
         repos = env.get_repository()
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         max_time = utcmax
 	if self.max_rev:
--- a/bitten/notify.py
+++ b/bitten/notify.py
@@ -148,7 +148,10 @@
         return messages
 
     def get_changeset(self):
-        return self.env.get_repository().get_changeset(self.build.rev)
+        repos = self.env.get_repository()
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
+        return repos.get_changeset(self.build.rev)
 
     def get_author(self):
         return self.get_changeset().author
--- a/bitten/queue.py
+++ b/bitten/queue.py
@@ -131,6 +131,8 @@
 
         db = self.env.get_db_cnx()
         repos = self.env.get_repository()
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         self.reset_orphaned_builds()
 
@@ -212,6 +214,8 @@
         configuration being in the build queue.
         """
         repos = self.env.get_repository()
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         db = self.env.get_db_cnx()
         builds = []
--- a/bitten/tests/admin.py
+++ b/bitten/tests/admin.py
@@ -553,7 +553,8 @@
         
         self.failUnless(req.chrome['warnings'], "No warnings?")
         self.assertEquals(req.chrome['warnings'],
-                            ['Invalid Repository Path "invalid/path".'])
+                    ['Invalid Repository Path: "invalid/path" does not exist '
+                     'within the "(default)" repository.'])
 
     def test_process_update_config_non_wellformed_recipe(self):
         BuildConfig(self.env, name='foo', label='Foo', path='branches/foo',
--- a/bitten/tests/queue.py
+++ b/bitten/tests/queue.py
@@ -192,6 +192,14 @@
         build = queue.get_build_for_slave('foobar', {})
         self.assertEqual(None, build)
 
+    def test_populate_no_repos(self):
+        """
+        Cannot work when there are no repositories defined.
+        """
+        self.env.get_repository = lambda: None
+        queue = BuildQueue(self.env)
+        self.assertRaises(AssertionError, queue.populate)
+
     def test_populate_not_build_all(self):
         self.env.get_repository = lambda authname=None: Mock(
             get_changeset=lambda rev: Mock(date=to_datetime(rev * 1000, utc)),
--- a/bitten/web_ui.py
+++ b/bitten/web_ui.py
@@ -76,6 +76,20 @@
     }
     return data
 
+def _has_permission(repos, path, perm, raise_error=False):
+    if hasattr(repos, 'authz'):
+        if not repos.authz.has_permission(path):
+            if not raise_error:
+                return False
+            repos.authz.assert_permission(path)
+    else:
+        node = repos.get_node(path)
+        if not node.can_view(perm):
+            if not raise_error:
+                return False
+            from trac.perm import PermissionError
+            raise PermissionError('BROWSER_VIEW', node.resource)
+    return True
 
 class BittenChrome(Component):
     """Provides the Bitten templates and static resources."""
@@ -93,7 +107,9 @@
         if 'BUILD_VIEW' in req.perm:
             status = ''
             if BuildMaster(self.env).quick_status:
-                repos = self.env.get_repository(req.authname)
+                repos = self.env.get_repository(authname=req.authname)
+                assert repos, 'No "(default)" Repository: Add a repository ' \
+                              'or alias named "(default)" to Trac.'
                 for config in BuildConfig.select(self.env,
                                                  include_inactive=False):
                     prev_rev = None
@@ -188,11 +204,13 @@
             show_all = True
         data['show_all'] = show_all
 
-        repos = self.env.get_repository(req.authname)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         configs = []
         for config in BuildConfig.select(self.env, include_inactive=show_all):
-            if not repos.authz.has_permission(config.path):
+            if not _has_permission(repos, config.path, req.perm):
                 continue
 
             description = config.description
@@ -275,11 +293,13 @@
 
         db = self.env.get_db_cnx()
 
-        repos = self.env.get_repository(req.authname)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         configs = []
         for config in BuildConfig.select(self.env, include_inactive=False):
-            if not repos.authz.has_permission(config.path):
+            if not _has_permission(repos, config.path, req.perm):
                 continue
 
             self.log.debug(config.name)
@@ -342,8 +362,10 @@
             raise HTTPNotFound("Build configuration '%s' does not exist." \
                                 % config_name)
 
-        repos = self.env.get_repository(req.authname)
-        repos.authz.assert_permission(config.path)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
+        _has_permission(repos, config.path, req.perm, True)
 
         data = {'title': 'Build Configuration "%s"' \
                           % config.label or config.name,
@@ -412,7 +434,9 @@
         more = False
         data['page_number'] = page
 
-        repos = self.env.get_repository(req.authname)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         builds_per_page = 12 * len(platforms)
         idx = 0
@@ -465,7 +489,6 @@
         """
 
         db = self.env.get_db_cnx()
-        repos = self.env.get_repository()
         cursor = db.cursor()
 
         cursor.execute("""SELECT DISTINCT report.category as category
@@ -563,8 +586,10 @@
         data['build']['can_delete'] = ('BUILD_DELETE' in req.perm \
                                    and build.status != build.PENDING)
 
-        repos = self.env.get_repository(req.authname)
-        repos.authz.assert_permission(config.path)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
+        _has_permission(repos, config.path, req.perm, True)
         chgset = repos.get_changeset(build.rev)
         data['build']['chgset_author'] = chgset.author
 
@@ -604,13 +629,15 @@
                        "AND b.status IN (%s, %s) ORDER BY b.stopped",
                        (start, stop, Build.SUCCESS, Build.FAILURE))
 
-        repos = self.env.get_repository(req.authname)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
 
         event_kinds = {Build.SUCCESS: 'successbuild',
                        Build.FAILURE: 'failedbuild'}
 
         for id_, config, label, path, rev, platform, stopped, status in cursor:
-            if not repos.authz.has_permission(path):
+            if not _has_permission(repos, path, req.perm):
                 continue
             errors = []
             if status == Build.FAILURE:
@@ -754,7 +781,9 @@
     def get_formatter(self, req, build):
         """Return the log message formatter function."""
         config = BuildConfig.fetch(self.env, name=build.config)
-        repos = self.env.get_repository(req.authname)
+        repos = self.env.get_repository(authname=req.authname)
+        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
+                      'named "(default)" to Trac.'
         href = req.href.browser
         cache = {}
 
Copyright (C) 2012-2017 Edgewall Software