# HG changeset patch # User osimons # Date 1282862917 0 # Node ID 4c73a3cea9f5c4ba01174e29e230da86ead84ce1 # Parent a01248c3968cd87000a0965dd1b5bf54b019b115 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. diff --git a/bitten/admin.py b/bitten/admin.py --- 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', '') diff --git a/bitten/master.py b/bitten/master.py --- 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()) diff --git a/bitten/model.py b/bitten/model.py --- 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: diff --git a/bitten/notify.py b/bitten/notify.py --- 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 diff --git a/bitten/queue.py b/bitten/queue.py --- 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 = [] diff --git a/bitten/tests/admin.py b/bitten/tests/admin.py --- 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', diff --git a/bitten/tests/queue.py b/bitten/tests/queue.py --- 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)), diff --git a/bitten/web_ui.py b/bitten/web_ui.py --- 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 = {}