Modified: bloodhound/vendor/trac/current/trac/versioncontrol/templates/repository_index.html URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/templates/repository_index.html?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/templates/repository_index.html (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/templates/repository_index.html Fri Nov 14 11:06:23 2014 @@ -1,4 +1,15 @@ -<!--! Template snippet for a table of repositories --> +<!--! Copyright (C) 2008-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + +Template snippet for a table of repositories +--> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude" py:strip=""> @@ -11,11 +22,11 @@ <tr class="${'odd' if idx % 2 else 'even'}"> <td class="name"> <em py:strip="not err"> - <b py:strip="repoinfo.alias != ''"> + <strong py:strip="repoinfo.alias != ''"> <a class="dir" title="View Root Directory" href="${href.browser(repos.reponame if repos else reponame, order=order if order != 'name' else None, desc=desc)}">$reponame</a> - </b> + </strong> </em> </td> <td class="size">
Modified: bloodhound/vendor/trac/current/trac/versioncontrol/templates/revisionlog.html URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/templates/revisionlog.html?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/templates/revisionlog.html (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/templates/revisionlog.html Fri Nov 14 11:06:23 2014 @@ -1,3 +1,13 @@ +<!--! Copyright (C) 2006-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. +--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Modified: bloodhound/vendor/trac/current/trac/versioncontrol/templates/sortable_th.html URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/templates/sortable_th.html?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/templates/sortable_th.html (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/templates/sortable_th.html Fri Nov 14 11:06:23 2014 @@ -1,4 +1,14 @@ -<!--! Snippet for a <th> corresponding to a sortable column. +<!--! Copyright (C) 2008-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + +Snippet for a <th> corresponding to a sortable column. Expects the following variables to be set specifically: Modified: bloodhound/vendor/trac/current/trac/versioncontrol/tests/api.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/tests/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/tests/api.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/tests/api.py Fri Nov 14 11:06:23 2014 @@ -111,6 +111,12 @@ class ResourceManagerTestCase(unittest.T self.assertEqual('/trac.cgi/browser/testrepo', get_resource_url(self.env, res, self.env.href)) + res = Resource('repository', '') # default repository + self.assertEqual('Default repository', + get_resource_description(self.env, res)) + self.assertEqual('/trac.cgi/browser', + get_resource_url(self.env, res, self.env.href)) + def suite(): suite = unittest.TestSuite() Modified: bloodhound/vendor/trac/current/trac/versioncontrol/tests/cache.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/tests/cache.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/tests/cache.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/tests/cache.py Fri Nov 14 11:06:23 2014 @@ -18,8 +18,8 @@ from __future__ import with_statement from datetime import datetime +import trac.tests.compat from trac.test import EnvironmentStub, Mock -from trac.tests import compat from trac.util.datefmt import to_utimestamp, utc from trac.versioncontrol import Repository, Changeset, Node, NoSuchChangeset from trac.versioncontrol.cache import CachedRepository @@ -283,6 +283,40 @@ class CacheTestCase(unittest.TestCase): rows[2]) self.assertEqual((to_utimestamp(t[3]), 'joe', 'Add COPYING'), rows[3]) + def test_sync_changeset_with_string_rev(self): # ticket:11660 + + class MockCachedRepository(CachedRepository): + def db_rev(self, rev): + return '%010d' % rev + + t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc) + t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc) + repos = self.get_repos(get_changeset=lambda x: changesets[int(x)], + youngest_rev=1) + changesets = [ + Mock(Changeset, repos, 0, 'empty', 'joe', t1, + get_changes=lambda: []), + Mock(Changeset, repos, 1, 'first', 'joe', t2, + get_changes=lambda: []), + ] + cache = MockCachedRepository(self.env, repos, self.log) + + cache.sync_changeset('0') # not cached yet + cache.sync_changeset(u'1') # not cached yet + rows = self.env.db_query( + "SELECT rev,author FROM revision ORDER BY rev") + self.assertEqual(2, len(rows)) + self.assertEquals(('0000000000', 'joe'), rows[0]) + self.assertEquals(('0000000001', 'joe'), rows[1]) + + cache.sync_changeset(u'0') # cached + cache.sync_changeset('1') # cached + rows = self.env.db_query( + "SELECT rev,author FROM revision ORDER BY rev") + self.assertEqual(2, len(rows)) + self.assertEquals(('0000000000', 'joe'), rows[0]) + self.assertEquals(('0000000001', 'joe'), rows[1]) + def test_get_changes(self): t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc) t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc) Modified: bloodhound/vendor/trac/current/trac/versioncontrol/tests/functional.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/tests/functional.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/tests/functional.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/tests/functional.py Fri Nov 14 11:06:23 2014 @@ -291,6 +291,51 @@ class RegressionTestTicket11438(Function tc.notfind('@%d' % (rev - 2)) +class RegressionTestTicket11584(FunctionalTwillTestCaseSetup): + def runTest(self): + """Test for regression of http://trac.edgewall.org/ticket/11584 + don't raise NoSuchChangeset for empty repository if no "rev" parameter + """ + repo_path = self._testenv.svnadmin_create('repo-t11584') + + self._tester.go_to_admin() + tc.follow("\\bRepositories\\b") + tc.url(self._tester.url + '/admin/versioncontrol/repository') + + tc.formvalue('trac-addrepos', 'name', 't11584') + tc.formvalue('trac-addrepos', 'dir', repo_path) + tc.submit() + tc.notfind(internal_error) + self._testenv._tracadmin('repository', 'sync', 't11584') + + browser_url = self._tester.url + '/browser/t11584' + tc.go(browser_url) + tc.url(browser_url) + tc.notfind('Error: No such changeset') + + +class RegressionTestTicket11618(FunctionalTwillTestCaseSetup): + def runTest(self): + """Test for regression of http://trac.edgewall.org/ticket/11618 + fix for malformed `readonly="True"` attribute in repository admin. + """ + env = self._testenv.get_trac_environment() + env.config.set('repositories', 't11618.dir', + self._testenv.repo_path_for_initenv()) + env.config.save() + try: + self._tester.go_to_admin() + tc.follow(r'\bRepositories\b') + tc.url(self._tester.url + '/admin/versioncontrol/repository') + tc.follow(r'\bt11618\b') + tc.url(self._tester.url + '/admin/versioncontrol/repository/t11618') + tc.notfind(' readonly="True"') + tc.find(' readonly="readonly"') + finally: + env.config.remove('repositories', 't11618.dir') + env.config.save() + + def functionalSuite(suite=None): if not suite: import trac.tests.functional @@ -308,6 +353,8 @@ def functionalSuite(suite=None): suite.addTest(RegressionTestTicket11194()) suite.addTest(RegressionTestTicket11346()) suite.addTest(RegressionTestTicket11438()) + suite.addTest(RegressionTestTicket11584()) + suite.addTest(RegressionTestTicket11618()) suite.addTest(RegressionTestRev5877()) else: print "SKIP: versioncontrol/tests/functional.py (no svn bindings)" Modified: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/browser.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/browser.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/browser.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/browser.py Fri Nov 14 11:06:23 2014 @@ -24,15 +24,14 @@ from genshi.builder import tag from trac.config import ListOption, BoolOption, Option from trac.core import * from trac.mimeview.api import IHTMLPreviewAnnotator, Mimeview, is_binary -from trac.perm import IPermissionRequestor +from trac.perm import IPermissionRequestor, PermissionError from trac.resource import Resource, ResourceNotFound from trac.util import as_bool, embedded_numbers -from trac.util.compat import cleandoc from trac.util.datefmt import http_date, to_datetime, utc from trac.util.html import escape, Markup from trac.util.text import exception_to_unicode, shorten_line from trac.util.translation import _, cleandoc_ -from trac.web.api import IRequestHandler, Request, RequestDone +from trac.web.api import IRequestHandler, RequestDone from trac.web.chrome import (INavigationContributor, add_ctxtnav, add_link, add_script, add_stylesheet, prevnext_nav, web_context) @@ -296,7 +295,8 @@ class BrowserModule(Component): def get_navigation_items(self, req): rm = RepositoryManager(self.env) - if 'BROWSER_VIEW' in req.perm and rm.get_real_repositories(): + if any(repos.is_viewable(req.perm) for repos + in rm.get_real_repositories()): yield ('mainnav', 'browser', tag.a(_('Browse Source'), href=req.href.browser())) @@ -327,8 +327,6 @@ class BrowserModule(Component): return True def process_request(self, req): - req.perm.require('BROWSER_VIEW') - presel = req.args.get('preselected') if presel and (presel + '/').startswith(req.href.browser() + '/'): req.redirect(presel) @@ -366,6 +364,7 @@ class BrowserModule(Component): # Find node for the requested path/rev context = web_context(req) node = None + changeset = None display_rev = lambda rev: rev if repos: try: @@ -378,6 +377,12 @@ class BrowserModule(Component): except NoSuchChangeset, e: raise ResourceNotFound(e.message, _('Invalid changeset number')) + if node: + try: + # use changeset instance to retrieve branches and tags + changeset = repos.get_changeset(node.rev) + except NoSuchChangeset: + pass context = context.child(repos.resource.child('source', path, version=rev_or_latest)) @@ -392,6 +397,9 @@ class BrowserModule(Component): repo_data = self._render_repository_index( context, all_repositories, order, desc) if node: + if not node.is_viewable(req.perm): + raise PermissionError('BROWSER_VIEW' if node.isdir else + 'FILE_VIEW', node.resource, self.env) if node.isdir: if format in ('zip',): # extension point here... self._render_zip(req, context, repos, node, rev) @@ -401,7 +409,13 @@ class BrowserModule(Component): file_data = self._render_file(req, context, repos, node, rev) if not repos and not (repo_data and repo_data['repositories']): - raise ResourceNotFound(_("No node %(path)s", path=path)) + # If no viewable repositories, check permission instead of + # repos.is_viewable() + req.perm.require('BROWSER_VIEW') + if show_index: + raise ResourceNotFound(_("No viewable repositories")) + else: + raise ResourceNotFound(_("No node %(path)s", path=path)) quickjump_data = properties_data = None if node and not xhr: @@ -413,7 +427,7 @@ class BrowserModule(Component): 'context': context, 'reponame': reponame, 'repos': repos, 'repoinfo': all_repositories.get(reponame or ''), 'path': path, 'rev': node and node.rev, 'stickyrev': rev, - 'display_rev': display_rev, + 'display_rev': display_rev, 'changeset': changeset, 'created_path': node and node.created_path, 'created_rev': node and node.created_rev, 'properties': properties_data, @@ -504,6 +518,10 @@ class BrowserModule(Component): continue try: repos = rm.get_repository(reponame) + except TracError, err: + entry = (reponame, repoinfo, None, None, + exception_to_unicode(err), None) + else: if repos: if not repos.is_viewable(context.perm): continue @@ -522,10 +540,7 @@ class BrowserModule(Component): raw_href) else: entry = (reponame, repoinfo, None, None, u"\u2013", None) - except TracError, err: - entry = (reponame, repoinfo, None, None, - exception_to_unicode(err), None) - if entry[-1] is not None: # Check permission in case of error + if entry[4] is not None: # Check permission in case of error root = Resource('repository', reponame).child('source', '/') if 'BROWSER_VIEW' not in context.perm(root): continue Modified: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/changeset.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/changeset.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/changeset.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/changeset.py Fri Nov 14 11:06:23 2014 @@ -40,7 +40,7 @@ from trac.util import as_bool, content_d from trac.util.datefmt import from_utimestamp, pretty_timedelta from trac.util.text import exception_to_unicode, to_unicode, \ unicode_urlencode, shorten_line, CRLF -from trac.util.translation import _, ngettext +from trac.util.translation import _, ngettext, tag_ from trac.versioncontrol.api import RepositoryManager, Changeset, Node, \ NoSuchChangeset from trac.versioncontrol.diff import get_diff_options, diff_blocks, \ @@ -102,7 +102,7 @@ class DefaultPropertyDiffRenderer(Compon unidiff = '--- \n+++ \n' + \ '\n'.join(unified_diff(old.splitlines(), new.splitlines(), options.get('contextlines', 3))) - return tag.li('Property ', tag.strong(name), + return tag.li(tag_("Property %(name)s", name=tag.strong(name)), Mimeview(self.env).render(old_context, 'text/x-diff', unidiff)) @@ -215,9 +215,9 @@ class ChangesetModule(Component): req.perm.require('CHANGESET_VIEW') # -- retrieve arguments - full_new_path = new_path = req.args.get('new_path') + new_path = req.args.get('new_path') new = req.args.get('new') - full_old_path = old_path = req.args.get('old_path') + old_path = req.args.get('old_path') old = req.args.get('old') reponame = req.args.get('reponame') @@ -254,14 +254,14 @@ class ChangesetModule(Component): # -- normalize and check for special case try: - new_path = repos.normalize_path(new_path) new = repos.normalize_rev(new) - full_new_path = '/' + pathjoin(repos.reponame, new_path) - old_path = repos.normalize_path(old_path or new_path) old = repos.normalize_rev(old or new) - full_old_path = '/' + pathjoin(repos.reponame, old_path) except NoSuchChangeset, e: - raise ResourceNotFound(e.message, _('Invalid Changeset Number')) + raise ResourceNotFound(e.message, _("Invalid Changeset Number")) + new_path = repos.normalize_path(new_path) + old_path = repos.normalize_path(old_path or new_path) + full_new_path = '/' + pathjoin(repos.reponame, new_path) + full_old_path = '/' + pathjoin(repos.reponame, old_path) if old_path == new_path and old == new: # revert to Changeset old_path = old = None @@ -1175,7 +1175,7 @@ class AnyDiffModule(Component): if repos.is_viewable(req.perm)) elem = tag.ul( - [tag.li(tag.b(path) if isdir else path) + [tag.li(tag.strong(path) if isdir else path) for (isdir, name, path) in sorted(entries, key=kind_order) if name.lower().startswith(prefix)]) Modified: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/log.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/log.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/log.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/log.py Fri Nov 14 11:06:23 2014 @@ -28,8 +28,7 @@ from trac.resource import ResourceNotFou from trac.util import Ranges from trac.util.text import to_unicode, wrap from trac.util.translation import _ -from trac.versioncontrol.api import (RepositoryManager, Changeset, - NoSuchChangeset) +from trac.versioncontrol.api import Changeset, RepositoryManager from trac.versioncontrol.web_ui.changeset import ChangesetModule from trac.versioncontrol.web_ui.util import * from trac.web import IRequestHandler @@ -90,8 +89,12 @@ class LogModule(Component): reponame, repos, path = rm.get_repository_by_path(path) if not repos: - raise ResourceNotFound(_("Repository '%(repo)s' not found", - repo=reponame)) + if path == '/': + raise TracError(_("No repository specified and no default" + " repository configured.")) + else: + raise ResourceNotFound(_("Repository '%(repo)s' not found", + repo=reponame or path.strip('/'))) if reponame != repos.reponame: # Redirect alias qs = req.query_string @@ -110,7 +113,7 @@ class LogModule(Component): rev = revranges.b except ValueError: pass - rev = unicode(repos.normalize_rev(rev)) + rev = repos.normalize_rev(rev) display_rev = repos.display_rev # The `history()` method depends on the mode: @@ -139,12 +142,12 @@ class LogModule(Component): node_history = list(node.get_history(2)) p, rev, chg = node_history[0] if repos.rev_older_than(rev, a): - break # simply skip, no separator + break # simply skip, no separator if 'CHANGESET_VIEW' in req.perm(cset_resource(id=rev)): if expected_next_item: # check whether we're continuing previous range np, nrev, nchg = expected_next_item - if rev != nrev: # no, we need a separator + if rev != nrev: # no, we need a separator yield (np, nrev, None) yield node_history[0] if len(node_history) > 1: @@ -159,6 +162,7 @@ class LogModule(Component): else: show_graph = path == '/' and not verbose \ and not repos.has_linear_changesets + def history(): node = get_existing_node(req, repos, path, rev) for h in node.get_history(): @@ -193,7 +197,7 @@ class LogModule(Component): break elif mode == 'path_history': depth -= 1 - if old_chg is None: # separator entry + if old_chg is None: # separator entry stop_limit = limit else: count += 1 @@ -201,13 +205,15 @@ class LogModule(Component): if count >= stop_limit: break previous_path = old_path - if info == []: + if not info: node = get_existing_node(req, repos, path, rev) if repos.rev_older_than(stop_rev, node.created_rev): # FIXME: we should send a 404 error here raise TracError(_("The file or directory '%(path)s' doesn't " - "exist at revision %(rev)s or at any previous revision.", - path=path, rev=display_rev(rev)), _('Nonexistent path')) + "exist at revision %(rev)s or at any " + "previous revision.", path=path, + rev=display_rev(rev)), + _('Nonexistent path')) # Generate graph data graph = {} @@ -232,7 +238,7 @@ class LogModule(Component): return req.href.log(repos.reponame or None, path, **params) if format in ('rss', 'changelog'): - info = [i for i in info if i['change']] # drop separators + info = [i for i in info if i['change']] # drop separators if info and count > limit: del info[-1] elif info and count >= limit: @@ -246,8 +252,9 @@ class LogModule(Component): older_revisions_href = make_log_href(next_path, rev=next_rev, revs=next_revranges) add_link(req, 'next', older_revisions_href, - _('Revision Log (restarting at %(path)s, rev. %(rev)s)', - path=next_path, rev=display_rev(next_rev))) + _('Revision Log (restarting at %(path)s, rev. ' + '%(rev)s)', path=next_path, + rev=display_rev(next_rev))) # only show fully 'limit' results, use `change == None` as a marker info[-1]['change'] = None @@ -276,11 +283,11 @@ class LogModule(Component): 'reponame': repos.reponame or None, 'repos': repos, 'path': path, 'rev': rev, 'stop_rev': stop_rev, 'display_rev': display_rev, 'revranges': revranges, - 'mode': mode, 'verbose': verbose, 'limit' : limit, + 'mode': mode, 'verbose': verbose, 'limit': limit, 'items': info, 'changes': changes, 'extra_changes': extra_changes, 'graph': graph, - 'wiki_format_messages': - self.config['changeset'].getbool('wiki_format_messages') + 'wiki_format_messages': self.config['changeset'] + .getbool('wiki_format_messages') } if format == 'changelog': @@ -295,8 +302,8 @@ class LogModule(Component): item_ranges = [] range = [] for item in info: - if item['change'] is None: # separator - if range: # start new range + if item['change'] is None: # separator + if range: # start new range range.append(item) item_ranges.append(range) range = [] @@ -321,7 +328,8 @@ class LogModule(Component): 'application/rss+xml', 'rss') changelog_href = make_log_href(path, format='changelog', revs=revs, stop_rev=stop_rev) - add_link(req, 'alternate', changelog_href, _('ChangeLog'), 'text/plain') + add_link(req, 'alternate', changelog_href, _('ChangeLog'), + 'text/plain') add_ctxtnav(req, _('View Latest Revision'), href=req.href.browser(repos.reponame or None, path)) Modified: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/__init__.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/__init__.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/__init__.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/__init__.py Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006-2013 Edgewall Software +# Copyright (C) 2006-2014 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -13,10 +13,15 @@ import unittest -from trac.versioncontrol.web_ui.tests import wikisyntax +from trac.versioncontrol.web_ui.tests import browser, changeset, log, \ + wikisyntax + def suite(): suite = unittest.TestSuite() + suite.addTest(browser.suite()) + suite.addTest(changeset.suite()) + suite.addTest(log.suite()) suite.addTest(wikisyntax.suite()) return suite Added: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/browser.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/browser.py?rev=1639602&view=auto ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/browser.py (added) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/browser.py Fri Nov 14 11:06:23 2014 @@ -0,0 +1,379 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.com/license.html. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/. + +import unittest +from datetime import datetime +from cStringIO import StringIO + +import trac.tests.compat +from trac.core import Component, TracError, implements +from trac.perm import PermissionError +from trac.resource import ResourceNotFound +from trac.test import EnvironmentStub, Mock, MockPerm +from trac.util.datefmt import utc +from trac.versioncontrol.api import ( + Changeset, DbRepositoryProvider, IRepositoryConnector, Node, NoSuchNode, + Repository, RepositoryManager) +from trac.versioncontrol.web_ui.browser import BrowserModule +from trac.web.tests.api import RequestHandlerPermissionsTestCaseBase +from tracopt.perm.authz_policy import ConfigObj + + +class MockRepositoryConnector(Component): + + implements(IRepositoryConnector) + + def get_supported_types(self): + yield 'mock', 8 + + def get_repository(self, repos_type, repos_dir, params): + def get_changeset(rev): + return Mock(Changeset, repos, rev, 'message', 'author', + datetime(2001, 1, 1, tzinfo=utc)) + + def get_node(path, rev): + if 'missing' in path: + raise NoSuchNode(path, rev) + kind = Node.FILE if 'file' in path else Node.DIRECTORY + node = Mock(Node, repos, path, rev, kind, + created_path=path, created_rev=rev, + get_entries=lambda: iter([]), + get_properties=lambda: {}, + get_content=lambda: StringIO('content'), + get_content_length=lambda: 7, + get_content_type=lambda: 'application/octet-stream') + return node + + if params['name'] == 'raise': + raise TracError("") + else: + repos = Mock(Repository, params['name'], params, self.log, + get_youngest_rev=lambda: 1, + get_changeset=get_changeset, + get_node=get_node, + previous_rev=lambda rev, path='': None, + next_rev=lambda rev, path='': None) + return repos + + +class BrowserModulePermissionsTestCase(RequestHandlerPermissionsTestCaseBase): + + authz_policy = """\ +[repository:*allow*@*/source:*deny*] +anonymous = !BROWSER_VIEW, !FILE_VIEW + +[repository:*deny*@*/source:*allow*] +anonymous = BROWSER_VIEW, FILE_VIEW + +[repository:*allow*@*] +anonymous = BROWSER_VIEW, FILE_VIEW + +[repository:*deny*@*] +anonymous = !BROWSER_VIEW, !FILE_VIEW + +""" + + def setUp(self): + super(BrowserModulePermissionsTestCase, self).setUp(BrowserModule) + provider = DbRepositoryProvider(self.env) + provider.add_repository('(default)', '/', 'mock') + provider.add_repository('allow', '/', 'mock') + provider.add_repository('deny', '/', 'mock') + provider.add_repository('raise', '/', 'mock') + + def tearDown(self): + RepositoryManager(self.env).reload_repositories() + super(BrowserModulePermissionsTestCase, self).tearDown() + + def test_get_navigation_items_with_browser_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW') + provider = DbRepositoryProvider(self.env) + req = self.create_request(path_info='/') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('allow') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('deny') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('(default)') + self.assertEqual([], list(self.get_navigation_items(req))) + + def test_get_navigation_items_without_browser_view(self): + provider = DbRepositoryProvider(self.env) + req = self.create_request(path_info='/') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('(default)') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('deny') + self.assertEqual('browser', self.get_navigation_items(req).next()[1]) + + provider.remove_repository('allow') + self.assertEqual([], list(self.get_navigation_items(req))) + + def test_repository_with_browser_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW') + + req = self.create_request(path_info='/browser/') + rv = self.process_request(req) + self.assertEqual('', rv[1]['repos'].name) + + req = self.create_request(path_info='/browser/allow') + rv = self.process_request(req) + self.assertEqual('allow', rv[1]['repos'].name) + + req = self.create_request(path_info='/browser/deny') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual('/', e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('deny', e.resource.parent.id) + + DbRepositoryProvider(self.env).remove_repository('(default)') + req = self.create_request(path_info='/browser/') + rv = self.process_request(req) + self.assertEqual(None, rv[1]['repos']) + + req = self.create_request(path_info='/browser/blah-blah-file') + try: + self.process_request(req) + self.fail('ResourceNotFound not raised') + except ResourceNotFound, e: + self.assertEqual('No node blah-blah-file', unicode(e)) + + def test_repository_without_browser_view(self): + req = self.create_request(path_info='/browser/') + rv = self.process_request(req) + # cannot view default repository but don't raise PermissionError + self.assertEqual(None, rv[1]['repos']) + + req = self.create_request(path_info='/browser/allow') + rv = self.process_request(req) + self.assertEqual('allow', rv[1]['repos'].name) + + req = self.create_request(path_info='/browser/deny') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual('/', e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('deny', e.resource.parent.id) + + DbRepositoryProvider(self.env).remove_repository('(default)') + req = self.create_request(path_info='/browser/') + rv = self.process_request(req) + self.assertEqual(None, rv[1]['repos']) + + req = self.create_request(path_info='/browser/blah-blah-file') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual(None, e.resource) + + def test_node_with_file_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW', 'FILE_VIEW') + + req = self.create_request(path_info='/browser/file') + rv = self.process_request(req) + self.assertEqual('', rv[1]['repos'].name) + self.assertEqual('file', rv[1]['path']) + + req = self.create_request(path_info='/browser/allow-file') + rv = self.process_request(req) + self.assertEqual('', rv[1]['repos'].name) + self.assertEqual('allow-file', rv[1]['path']) + + req = self.create_request(path_info='/browser/deny-file') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('FILE_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual('deny-file', e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('', e.resource.parent.id) + + def test_node_in_allowed_repos_with_file_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW', 'FILE_VIEW') + + req = self.create_request(path_info='/browser/allow/file') + rv = self.process_request(req) + self.assertEqual('allow', rv[1]['repos'].name) + self.assertEqual('file', rv[1]['path']) + + req = self.create_request(path_info='/browser/allow/allow-file') + rv = self.process_request(req) + self.assertEqual('allow', rv[1]['repos'].name) + self.assertEqual('allow-file', rv[1]['path']) + + req = self.create_request(path_info='/browser/allow/deny-file') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('FILE_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual('deny-file', e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('allow', e.resource.parent.id) + + def test_node_in_denied_repos_with_file_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW', 'FILE_VIEW') + + req = self.create_request(path_info='/browser/deny/allow-file') + rv = self.process_request(req) + self.assertEqual('deny', rv[1]['repos'].name) + self.assertEqual('allow-file', rv[1]['path']) + + for path in ('file', 'deny-file'): + req = self.create_request(path_info='/browser/deny/' + path) + try: + self.process_request(req) + self.fail('PermissionError not raised (path: %r)' % path) + except PermissionError, e: + self.assertEqual('FILE_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual(path, e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('deny', e.resource.parent.id) + + def test_missing_node_with_browser_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW') + req = self.create_request(path_info='/browser/allow/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + req = self.create_request(path_info='/browser/deny/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + req = self.create_request(path_info='/browser/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + + def test_missing_node_without_browser_view(self): + req = self.create_request(path_info='/browser/allow/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + req = self.create_request(path_info='/browser/deny/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + req = self.create_request(path_info='/browser/missing') + self.assertRaises(ResourceNotFound, self.process_request, req) + + def test_repository_index_with_hidden_default_repos(self): + self.grant_perm('anonymous', 'BROWSER_VIEW', 'FILE_VIEW') + provider = DbRepositoryProvider(self.env) + provider.modify_repository('(default)', {'hidden': 'enabled'}) + req = self.create_request(path_info='/browser/') + template, data, content_type = self.process_request(req) + self.assertEqual(None, data['repos']) + repo_data = data['repo'] # for repository index + self.assertEqual('allow', repo_data['repositories'][0][0]) + self.assertEqual('raise', repo_data['repositories'][1][0]) + self.assertEqual(2, len(repo_data['repositories'])) + + def test_node_in_hidden_default_repos(self): + self.grant_perm('anonymous', 'BROWSER_VIEW', 'FILE_VIEW') + provider = DbRepositoryProvider(self.env) + provider.modify_repository('(default)', {'hidden': 'enabled'}) + req = self.create_request(path_info='/browser/blah-blah-file') + template, data, content_type = self.process_request(req) + self.assertEqual('', data['reponame']) + self.assertEqual('blah-blah-file', data['path']) + + def test_no_viewable_repositories_with_browser_view(self): + self.grant_perm('anonymous', 'BROWSER_VIEW') + provider = DbRepositoryProvider(self.env) + + provider.remove_repository('allow') + provider.remove_repository('(default)') + provider.remove_repository('raise') + + req = self.create_request(path_info='/browser/') + try: + self.process_request(req) + self.fail('ResourceNotFound not raised') + except ResourceNotFound, e: + self.assertEqual('No viewable repositories', unicode(e)) + req = self.create_request(path_info='/browser/allow/') + try: + self.process_request(req) + self.fail('ResourceNotFound not raised') + except ResourceNotFound, e: + self.assertEqual('No node allow', unicode(e)) + req = self.create_request(path_info='/browser/deny/') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual('source', e.resource.realm) + self.assertEqual('/', e.resource.id) + self.assertEqual('repository', e.resource.parent.realm) + self.assertEqual('deny', e.resource.parent.id) + + provider.remove_repository('deny') + req = self.create_request(path_info='/browser/') + try: + self.process_request(req) + self.fail('ResourceNotFound not raised') + except ResourceNotFound, e: + self.assertEqual('No viewable repositories', unicode(e)) + req = self.create_request(path_info='/browser/deny/') + try: + self.process_request(req) + self.fail('ResourceNotFound not raised') + except ResourceNotFound, e: + self.assertEqual('No node deny', unicode(e)) + + def test_no_viewable_repositories_without_browser_view(self): + provider = DbRepositoryProvider(self.env) + provider.remove_repository('allow') + req = self.create_request(path_info='/browser/') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual(None, e.resource) + provider.remove_repository('deny') + provider.remove_repository('(default)') + req = self.create_request(path_info='/browser/') + try: + self.process_request(req) + self.fail('PermissionError not raised') + except PermissionError, e: + self.assertEqual('BROWSER_VIEW', e.action) + self.assertEqual(None, e.resource) + + +def suite(): + suite = unittest.TestSuite() + if ConfigObj: + suite.addTest(unittest.makeSuite(BrowserModulePermissionsTestCase)) + else: + print("SKIP: %s.%s (no configobj installed)" % + (BrowserModulePermissionsTestCase.__module__, + BrowserModulePermissionsTestCase.__name__)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') Added: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/changeset.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/changeset.py?rev=1639602&view=auto ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/changeset.py (added) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/changeset.py Fri Nov 14 11:06:23 2014 @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.com/license.html. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/. + +import unittest + +from trac.core import TracError +from trac.test import EnvironmentStub, Mock, MockPerm +from trac.versioncontrol.web_ui.changeset import ChangesetModule + + +class ChangesetModuleTestCase(unittest.TestCase): + + def setUp(self): + self.env = EnvironmentStub() + self.cm = ChangesetModule(self.env) + + def test_default_repository_not_configured(self): + """Test for regression of http://trac.edgewall.org/ticket/11599.""" + req = Mock(perm=MockPerm(), args={'new_path': '/'}, + get_header=lambda self: None) + self.assertRaises(TracError, self.cm.process_request, req) + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ChangesetModuleTestCase)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') Added: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/log.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/log.py?rev=1639602&view=auto ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/log.py (added) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/log.py Fri Nov 14 11:06:23 2014 @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.com/license.html. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/. + +import unittest + +from trac.core import TracError +from trac.test import EnvironmentStub, Mock, MockPerm +from trac.versioncontrol.web_ui.log import LogModule + + +class LogModuleTestCase(unittest.TestCase): + + def setUp(self): + self.env = EnvironmentStub() + self.lm = LogModule(self.env) + + def test_default_repository_not_configured(self): + """Test for regression of http://trac.edgewall.org/ticket/11599.""" + req = Mock(perm=MockPerm(), args={'new_path': '/'}) + self.assertRaises(TracError, self.lm.process_request, req) + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(LogModuleTestCase)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') Modified: bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/wikisyntax.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/wikisyntax.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/wikisyntax.py (original) +++ bloodhound/vendor/trac/current/trac/versioncontrol/web_ui/tests/wikisyntax.py Fri Nov 14 11:06:23 2014 @@ -14,7 +14,6 @@ import unittest from trac.test import Mock -from trac.versioncontrol import NoSuchChangeset, NoSuchNode from trac.versioncontrol.api import * from trac.versioncontrol.web_ui import * from trac.wiki.tests import formatter Modified: bloodhound/vendor/trac/current/trac/web/api.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/api.py (original) +++ bloodhound/vendor/trac/current/trac/web/api.py Fri Nov 14 11:06:23 2014 @@ -29,10 +29,12 @@ from StringIO import StringIO import sys import urlparse +from genshi.builder import Fragment from trac.core import Interface, TracError +from trac.perm import PermissionError from trac.util import get_last_traceback, unquote from trac.util.datefmt import http_date, localtz -from trac.util.text import empty, to_unicode +from trac.util.text import empty, exception_to_unicode, to_unicode from trac.util.translation import _ from trac.web.href import Href from trac.web.wsgi import _FileWrapper @@ -131,7 +133,7 @@ HTTP_STATUS = dict([(code, reason.title( class HTTPException(Exception): def __init__(self, detail, *args): - if isinstance(detail, TracError): + if isinstance(detail, (TracError, PermissionError)): self.detail = detail.message self.reason = detail.title else: @@ -141,6 +143,35 @@ class HTTPException(Exception): Exception.__init__(self, '%s %s (%s)' % (self.code, self.reason, self.detail)) + @property + def message(self): + # The message is based on the e.detail, which can be an Exception + # object, but not a TracError one: when creating HTTPException, + # a TracError.message is directly assigned to e.detail + if isinstance(self.detail, Exception): # not a TracError or PermissionError + message = exception_to_unicode(self.detail) + elif isinstance(self.detail, Fragment): # TracError or PermissionError markup + message = self.detail + else: + message = to_unicode(self.detail) + return message + + @property + def title(self): + try: + # We first try to get localized error messages here, but we + # should ignore secondary errors if the main error was also + # due to i18n issues + title = _("Error") + if self.reason: + if title.lower() in self.reason.lower(): + title = self.reason + else: + title = _("Error: %(message)s", message=self.reason) + except Exception: + title = "Error" + return title + @classmethod def subclass(cls, name, code): """Create a new Exception class representing a HTTP status code.""" Modified: bloodhound/vendor/trac/current/trac/web/chrome.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/chrome.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/chrome.py (original) +++ bloodhound/vendor/trac/current/trac/web/chrome.py Fri Nov 14 11:06:23 2014 @@ -178,7 +178,7 @@ def add_script_data(req, data={}, **kwar script_data.update(kwargs) def add_javascript(req, filename): - """:deprecated: use `add_script` instead.""" + """:deprecated: since 0.10, use `add_script` instead.""" add_script(req, filename, mimetype='text/javascript') def add_warning(req, msg, *args): @@ -274,6 +274,8 @@ def web_context(req, resource=None, id=F name) :return: a new rendering context :rtype: `RenderingContext` + + :since: version 1.0 """ if req: href = req.abs_href if absurls else req.href @@ -313,9 +315,7 @@ def _chrome_resource_path(req, filename) elif filename.startswith('common/') and 'htdocs_location' in req.chrome: return Href(req.chrome['htdocs_location'])(filename[7:]) else: - href = req.href - if not filename.startswith('/'): - href = href.chrome + href = req.href if filename.startswith('/') else req.href.chrome return href(filename) @@ -503,6 +503,9 @@ class Chrome(Component): templates = None + # DocType for 'text/html' output + html_doctype = DocType.XHTML_STRICT + # A dictionary of default context data for templates _default_context_data = { '_': translation.gettext, @@ -970,9 +973,10 @@ class Chrome(Component): """Render the `filename` using the `data` for the context. The `content_type` argument is used to choose the kind of template - used (`NewTextTemplate` if `'text/plain'`, `MarkupTemplate` otherwise), - and tweak the rendering process (use of XHTML Strict doctype if - `'text/html'` is given). + used (`NewTextTemplate` if `'text/plain'`, `MarkupTemplate` + otherwise), and tweak the rendering process. Doctype for `'text/html'` + can be specified by setting the `html_doctype` attribute (default + is `XHTML_STRICT`) When `fragment` is specified, the (filtered) Genshi stream is returned. @@ -1012,8 +1016,9 @@ class Chrome(Component): stream.render('text', out=buffer, encoding='utf-8') return buffer.getvalue() - doctype = {'text/html': DocType.XHTML_STRICT}.get(content_type) - if doctype: + doctype = None + if content_type == 'text/html': + doctype = self.html_doctype if req.form_token: stream |= self._add_form_token(req.form_token) if not int(req.session.get('accesskeys', 0)): Modified: bloodhound/vendor/trac/current/trac/web/main.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/main.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/main.py (original) +++ bloodhound/vendor/trac/current/trac/web/main.py Fri Nov 14 11:06:23 2014 @@ -28,7 +28,7 @@ from pprint import pformat, pprint import re import sys -from genshi.builder import Fragment, tag +from genshi.builder import tag from genshi.output import DocType from genshi.template import TemplateLoader @@ -41,14 +41,14 @@ from trac.loader import get_plugin_info, from trac.perm import PermissionCache, PermissionError from trac.resource import ResourceNotFound from trac.util import arity, get_frame_info, get_last_traceback, hex_entropy, \ - read_file, safe_repr, translation + read_file, safe_repr, translation, warn_setuptools_issue from trac.util.concurrency import threading from trac.util.datefmt import format_datetime, localtz, timezone, user_time from trac.util.text import exception_to_unicode, shorten_line, to_unicode from trac.util.translation import _, get_negotiated_locale, has_babel, \ safefmt, tag_ from trac.web.api import * -from trac.web.chrome import Chrome, add_warning +from trac.web.chrome import Chrome, add_notice, add_warning from trac.web.href import Href from trac.web.session import Session @@ -256,7 +256,7 @@ class RequestDispatcher(Component): exception_to_unicode(e, traceback=True)) raise err[0], err[1], err[2] except PermissionError, e: - raise HTTPForbidden(to_unicode(e)) + raise HTTPForbidden(e) except ResourceNotFound, e: raise HTTPNotFound(e) except TracError, e: @@ -349,6 +349,7 @@ class RequestDispatcher(Component): return resp +_warn_setuptools = False _slashes_re = re.compile(r'/+') def dispatch_request(environ, start_response): @@ -358,6 +359,11 @@ def dispatch_request(environ, start_resp :param start_response: the WSGI callback for starting the response """ + global _warn_setuptools + if _warn_setuptools is False: + _warn_setuptools = True + warn_setuptools_issue(out=environ.get('wsgi.errors')) + # SCRIPT_URL is an Apache var containing the URL before URL rewriting # has been applied, so we can use it to reconstruct logical SCRIPT_NAME script_url = environ.get('SCRIPT_URL') @@ -518,35 +524,13 @@ def _send_user_error(req, env, e): # See trac/web/api.py for the definition of HTTPException subclasses. if env: env.log.warn('[%s] %s' % (req.remote_addr, exception_to_unicode(e))) - try: - # We first try to get localized error messages here, but we - # should ignore secondary errors if the main error was also - # due to i18n issues - title = _('Error') - if e.reason: - if title.lower() in e.reason.lower(): - title = e.reason - else: - title = _('Error: %(message)s', message=e.reason) - except Exception: - title = 'Error' - # The message is based on the e.detail, which can be an Exception - # object, but not a TracError one: when creating HTTPException, - # a TracError.message is directly assigned to e.detail - if isinstance(e.detail, Exception): # not a TracError - message = exception_to_unicode(e.detail) - elif isinstance(e.detail, Fragment): # markup coming from a TracError - message = e.detail - else: - message = to_unicode(e.detail) - data = {'title': title, 'type': 'TracError', 'message': message, + data = {'title': e.title, 'type': 'TracError', 'message': e.message, 'frames': [], 'traceback': None} if e.code == 403 and req.authname == 'anonymous': # TRANSLATOR: ... not logged in, you may want to 'do so' now (link) do_so = tag.a(_("do so"), href=req.href.login()) - req.chrome['notices'].append( - tag_("You are currently not logged in. You may want to " - "%(do_so)s now.", do_so=do_so)) + add_notice(req, tag_("You are currently not logged in. You may want " + "to %(do_so)s now.", do_so=do_so)) try: req.send_error(sys.exc_info(), status=e.code, env=env, data=data) except RequestDone: @@ -598,7 +582,9 @@ def send_internal_error(env, req, exc_in sys_info = "".join("|| '''`%s`''' || `%s` ||\n" % (k, v.replace('\n', '` [[br]] `')) for k, v in env.get_systeminfo()) - sys_info += "|| '''`jQuery`''' || `#JQUERY#` ||\n" + sys_info += "|| '''`jQuery`''' || `#JQUERY#` ||\n" \ + "|| '''`jQuery UI`''' || `#JQUERYUI#` ||\n" \ + "|| '''`jQuery Timepicker`''' || `#JQUERYTP#` ||\n" enabled_plugins = "".join("|| '''`%s`''' || `%s` ||\n" % (p['name'], p['version'] or _('N/A')) for p in plugins) @@ -645,6 +631,7 @@ User agent: `#USER_AGENT#` 'tracker': tracker, 'tracker_args': tracker_args, 'description': description, 'description_en': description_en} + Chrome(env).add_jquery_ui(req) try: req.send_error(exc_info, status=500, env=env, data=data) except RequestDone: Modified: bloodhound/vendor/trac/current/trac/web/session.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/session.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/session.py (original) +++ bloodhound/vendor/trac/current/trac/web/session.py Fri Nov 14 11:06:23 2014 @@ -358,8 +358,7 @@ class SessionAdmin(Component): self._complete_delete, self._do_delete) yield ('session purge', '<age>', - """Purge all anonymous sessions older than the given age or - date + """Purge anonymous sessions older than the given age or date Age may be specified as a relative time like "90 days ago", or as a date in the "%(datetime)s" or "%(iso8601)s" (ISO 8601) Modified: bloodhound/vendor/trac/current/trac/web/standalone.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/standalone.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/standalone.py (original) +++ bloodhound/vendor/trac/current/trac/web/standalone.py Fri Nov 14 11:06:23 2014 @@ -28,7 +28,6 @@ from SocketServer import ThreadingMixIn from trac import __version__ as VERSION from trac.util import autoreload, daemon -from trac.web.api import Request from trac.web.auth import BasicAuthentication, DigestAuthentication from trac.web.main import dispatch_request from trac.web.wsgi import WSGIServer, WSGIRequestHandler Modified: bloodhound/vendor/trac/current/trac/web/tests/api.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/tests/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/tests/api.py (original) +++ bloodhound/vendor/trac/current/trac/web/tests/api.py Fri Nov 14 11:06:23 2014 @@ -11,23 +11,100 @@ # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. -from trac.test import Mock +import os.path +import shutil +import sys +import tempfile +import unittest +from StringIO import StringIO + +import trac.tests.compat +from trac import perm +from trac.core import TracError +from trac.test import EnvironmentStub, Mock, MockPerm, locale_en +from trac.util import create_file +from trac.util.datefmt import utc +from trac.util.text import shorten_line from trac.web.api import Request, RequestDone, parse_arg_list +from tracopt.perm.authz_policy import AuthzPolicy -from StringIO import StringIO -import unittest + +class RequestHandlerPermissionsTestCaseBase(unittest.TestCase): + + authz_policy = None + + def setUp(self, module_class): + self.path = tempfile.mkdtemp(prefix='trac-') + if self.authz_policy is not None: + self.authz_file = os.path.join(self.path, 'authz_policy.conf') + create_file(self.authz_file, self.authz_policy) + self.env = EnvironmentStub(enable=['trac.*', AuthzPolicy], + path=self.path) + self.env.config.set('authz_policy', 'authz_file', self.authz_file) + self.env.config.set('trac', 'permission_policies', + 'AuthzPolicy, DefaultPermissionPolicy') + else: + self.env = EnvironmentStub(path=self.path) + self.req_handler = module_class(self.env) + + def tearDown(self): + self.env.reset_db() + shutil.rmtree(self.path) + + def create_request(self, authname='anonymous', **kwargs): + kw = {'perm': perm.PermissionCache(self.env, authname), 'args': {}, + 'href': self.env.href, 'abs_href': self.env.abs_href, + 'tz': utc, 'locale': None, 'lc_time': locale_en, + 'chrome': {'notices': [], 'warnings': []}, + 'method': None, 'get_header': lambda v: None} + kw.update(kwargs) + return Mock(**kw) + + def get_navigation_items(self, req): + return self.req_handler.get_navigation_items(req) + + def grant_perm(self, username, *actions): + permsys = perm.PermissionSystem(self.env) + for action in actions: + permsys.grant_permission(username, action) + + def process_request(self, req): + self.assertTrue(self.req_handler.match_request(req)) + return self.req_handler.process_request(req) + + +def _make_environ(scheme='http', server_name='example.org', + server_port=80, method='GET', script_name='/trac', + **kwargs): + environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''), + 'REQUEST_METHOD': method, 'SERVER_NAME': server_name, + 'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name} + environ.update(kwargs) + return environ + + +def _make_req(environ, start_response, args={}, arg_list=(), authname='admin', + form_token='A' * 40, chrome={'links': {}, 'scripts': []}, + perm=MockPerm(), session={}, tz=utc, locale=None, **kwargs): + req = Request(environ, start_response) + req.args = args + req.arg_list = arg_list + req.authname = authname + req.form_token = form_token + req.chrome = chrome + req.perm = perm + req.session = session + req.tz = tz + req.locale = locale + for name, value in kwargs.iteritems(): + setattr(req, name, value) + return req class RequestTestCase(unittest.TestCase): - def _make_environ(self, scheme='http', server_name='example.org', - server_port=80, method='GET', script_name='/trac', - **kwargs): - environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''), - 'REQUEST_METHOD': method, 'SERVER_NAME': server_name, - 'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name} - environ.update(kwargs) - return environ + def _make_environ(self, *args, **kwargs): + return _make_environ(*args, **kwargs) def test_base_url(self): environ = self._make_environ() @@ -153,6 +230,118 @@ class RequestTestCase(unittest.TestCase) self.assertEqual('bar', req.args['action']) +class SendErrorTestCase(unittest.TestCase): + + def setUp(self): + self.env = EnvironmentStub() + + def tearDown(self): + self.env.reset_db() + + def test_trac_error(self): + content = self._send_error(error_klass=TracError) + self.assertIn('<p class="message">Oops!</p>', content) + self.assertNotIn('<strong>Trac detected an internal error:</strong>', + content) + self.assertNotIn('There was an internal error in Trac.', content) + + def test_internal_error_for_non_admin(self): + content = self._send_error(perm={}) + self.assertIn('There was an internal error in Trac.', content) + self.assertIn('<p>To that end, you could', content) + self.assertNotIn('This is probably a local installation issue.', + content) + self.assertNotIn('<h2>Found a bug in Trac?</h2>', content) + + def test_internal_error_with_admin_trac_for_non_admin(self): + content = self._send_error(perm={}, + admin_trac_url='http://example.org/admin') + self.assertIn('There was an internal error in Trac.', content) + self.assertIn('<p>To that end, you could', content) + self.assertIn(' action="http://example.org/admin/newticket#"', content) + self.assertNotIn('This is probably a local installation issue.', + content) + self.assertNotIn('<h2>Found a bug in Trac?</h2>', content) + + def test_internal_error_without_admin_trac_for_non_admin(self): + content = self._send_error(perm={}, admin_trac_url='') + self.assertIn('There was an internal error in Trac.', content) + self.assertNotIn('<p>To that end, you could', content) + self.assertNotIn('This is probably a local installation issue.', + content) + self.assertNotIn('<h2>Found a bug in Trac?</h2>', content) + + def test_internal_error_for_admin(self): + content = self._send_error() + self.assertNotIn('There was an internal error in Trac.', content) + self.assertIn('This is probably a local installation issue.', content) + self.assertNotIn('a ticket at the admin Trac to report', content) + self.assertIn('<h2>Found a bug in Trac?</h2>', content) + self.assertIn('<p>Otherwise, please', content) + self.assertIn(' action="http://example.org/tracker/newticket"', + content) + + def test_internal_error_with_admin_trac_for_admin(self): + content = self._send_error(admin_trac_url='http://example.org/admin') + self.assertNotIn('There was an internal error in Trac.', content) + self.assertIn('This is probably a local installation issue.', content) + self.assertIn('a ticket at the admin Trac to report', content) + self.assertIn(' action="http://example.org/admin/newticket#"', content) + self.assertIn('<h2>Found a bug in Trac?</h2>', content) + self.assertIn('<p>Otherwise, please', content) + self.assertIn(' action="http://example.org/tracker/newticket"', + content) + + def test_internal_error_without_admin_trac_for_admin(self): + content = self._send_error(admin_trac_url='') + self.assertNotIn('There was an internal error in Trac.', content) + self.assertIn('This is probably a local installation issue.', content) + self.assertNotIn('a ticket at the admin Trac to report', content) + self.assertIn('<h2>Found a bug in Trac?</h2>', content) + self.assertIn('<p>Otherwise, please', content) + self.assertIn(' action="http://example.org/tracker/newticket"', + content) + + def _send_error(self, admin_trac_url='.', perm=None, + error_klass=ValueError): + self.env.config.set('project', 'admin_trac_url', admin_trac_url) + self.assertEquals(admin_trac_url, self.env.project_admin_trac_url) + + content = StringIO() + result = {'status': None, 'headers': []} + def write(data): + content.write(data) + def start_response(status, headers, exc_info=None): + result['status'] = status + result['headers'].extend(headers) + return write + environ = _make_environ() + req = _make_req(environ, start_response) + try: + raise error_klass('Oops!') + except: + exc_info = sys.exc_info() + data = {'title': 'Internal Error', + 'type': ('internal', 'TracError')[error_klass is TracError], + 'message': 'Oops!', 'traceback': None, 'frames': [], + 'shorten_line': shorten_line, + 'plugins': [], 'faulty_plugins': [], + 'tracker': 'http://example.org/tracker', 'tracker_args': {}, + 'description': '', 'description_en': '', + 'get_systeminfo': lambda: ()} + if perm is not None: + data['perm'] = perm + + self.assertRaises(RequestDone, req.send_error, exc_info, env=self.env, + data=data) + content = content.getvalue().decode('utf-8') + self.assertIn('<!DOCTYPE ', content) + self.assertEquals('500', result['status'].split()[0]) + self.assertIn(('Content-Type', 'text/html;charset=utf-8'), + result['headers']) + return content + + class ParseArgListTestCase(unittest.TestCase): def test_qs_str(self): @@ -177,6 +366,7 @@ class ParseArgListTestCase(unittest.Test def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(RequestTestCase)) + suite.addTest(unittest.makeSuite(SendErrorTestCase)) suite.addTest(unittest.makeSuite(ParseArgListTestCase)) return suite Modified: bloodhound/vendor/trac/current/trac/web/tests/auth.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/tests/auth.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/tests/auth.py (original) +++ bloodhound/vendor/trac/current/trac/web/tests/auth.py Fri Nov 14 11:06:23 2014 @@ -13,9 +13,9 @@ import os +import trac.tests.compat from trac.core import TracError from trac.test import EnvironmentStub, Mock -from trac.tests import compat from trac.web.auth import BasicAuthentication, LoginModule from trac.web.href import Href Modified: bloodhound/vendor/trac/current/trac/web/tests/chrome.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/tests/chrome.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/tests/chrome.py (original) +++ bloodhound/vendor/trac/current/trac/web/tests/chrome.py Fri Nov 14 11:06:23 2014 @@ -16,9 +16,9 @@ import shutil import tempfile import unittest +import trac.tests.compat from trac.core import Component, TracError, implements from trac.test import EnvironmentStub, locale_en -from trac.tests import compat from trac.tests.contentgen import random_sentence from trac.util import create_file from trac.web.chrome import ( @@ -85,8 +85,10 @@ class ChromeTestCase(unittest.TestCase): add_script(req, 'common/js/trac.js') add_script(req, 'http://example.com/trac.js') add_script(req, '//example.com/trac.js') + add_script(req, '/dynamic.js') + add_script(req, 'plugin/js/plugin.js') scripts = req.chrome['scripts'] - self.assertEqual(3, len(scripts)) + self.assertEqual(5, len(scripts)) self.assertEqual('text/javascript', scripts[0]['type']) self.assertEqual('/trac.cgi/chrome/common/js/trac.js', scripts[0]['href']) @@ -96,6 +98,10 @@ class ChromeTestCase(unittest.TestCase): self.assertEqual('text/javascript', scripts[2]['type']) self.assertEqual('//example.com/trac.js', scripts[2]['href']) + self.assertEqual('/trac.cgi/dynamic.js', + scripts[3]['href']) + self.assertEqual('/trac.cgi/chrome/plugin/js/plugin.js', + scripts[4]['href']) def test_add_script_data(self): req = Request(href=Href('/trac.cgi')) @@ -110,8 +116,10 @@ class ChromeTestCase(unittest.TestCase): add_stylesheet(req, 'common/css/trac.css') add_stylesheet(req, 'https://example.com/trac.css') add_stylesheet(req, '//example.com/trac.css') + add_stylesheet(req, '/dynamic.css') + add_stylesheet(req, 'plugin/css/plugin.css') links = req.chrome['links']['stylesheet'] - self.assertEqual(3, len(links)) + self.assertEqual(5, len(links)) self.assertEqual('text/css', links[0]['type']) self.assertEqual('/trac.cgi/chrome/common/css/trac.css', links[0]['href']) @@ -121,6 +129,10 @@ class ChromeTestCase(unittest.TestCase): self.assertEqual('text/css', links[2]['type']) self.assertEqual('//example.com/trac.css', links[2]['href']) + self.assertEqual('/trac.cgi/dynamic.css', + links[3]['href']) + self.assertEqual('/trac.cgi/chrome/plugin/css/plugin.css', + links[4]['href']) def test_add_stylesheet_media(self): req = Request(base_path='/trac.cgi', href=Href('/trac.cgi')) Modified: bloodhound/vendor/trac/current/trac/web/tests/href.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/tests/href.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/tests/href.py (original) +++ bloodhound/vendor/trac/current/trac/web/tests/href.py Fri Nov 14 11:06:23 2014 @@ -15,8 +15,8 @@ import doctest import unittest +import trac.tests.compat import trac.web.href -from trac.tests import compat class HrefTestCase(unittest.TestCase): Modified: bloodhound/vendor/trac/current/trac/web/tests/session.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/tests/session.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/tests/session.py (original) +++ bloodhound/vendor/trac/current/trac/web/tests/session.py Fri Nov 14 11:06:23 2014 @@ -18,8 +18,8 @@ import time from datetime import datetime import unittest +import trac.tests.compat from trac.test import EnvironmentStub, Mock -from trac.tests import compat from trac.web.session import DetachedSession, Session, PURGE_AGE, \ UPDATE_INTERVAL, SessionAdmin from trac.core import TracError Modified: bloodhound/vendor/trac/current/trac/web/wsgi.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/web/wsgi.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/web/wsgi.py (original) +++ bloodhound/vendor/trac/current/trac/web/wsgi.py Fri Nov 14 11:06:23 2014 @@ -194,9 +194,15 @@ class WSGIRequestHandler(BaseHTTPRequest def finish(self): """We need to help the garbage collector a little.""" - BaseHTTPRequestHandler.finish(self) - self.wfile = None - self.rfile = None + try: + BaseHTTPRequestHandler.finish(self) + except (IOError, socket.error), e: + # ignore an exception if client disconnects + if e.args[0] not in (errno.EPIPE, errno.ECONNRESET, 10053, 10054): + raise + finally: + self.wfile = None + self.rfile = None class WSGIServerGateway(WSGIGateway): Modified: bloodhound/vendor/trac/current/trac/wiki/default-pages/InterMapTxt URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/wiki/default-pages/InterMapTxt?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/wiki/default-pages/InterMapTxt (original) +++ bloodhound/vendor/trac/current/trac/wiki/default-pages/InterMapTxt Fri Nov 14 11:06:23 2014 @@ -38,22 +38,53 @@ Also note that !InterWiki prefixes are c == Prefix Definitions == {{{ -PEP http://www.python.org/peps/pep-$1.html # Python Enhancement Proposal +PEP http://www.python.org/dev/peps/pep-$1/ # Python Enhancement Proposal PythonBug http://bugs.python.org/issue$1 # Python Issue #$1 Python-issue http://bugs.python.org/issue$1 # Python Issue #$1 Trac-ML http://thread.gmane.org/gmane.comp.version-control.subversion.trac.general/ # Message $1 in Trac Mailing List trac-dev http://thread.gmane.org/gmane.comp.version-control.subversion.trac.devel/ # Message $1 in Trac Development Mailing List +apidoc http://www.edgewall.org/docs/trac-trunk/html/$1.html # $1 in the API documentation for Trac +apiref http://www.edgewall.org/docs/trac-trunk/epydoc/$1.html # $1 in the Epydoc API reference for Trac + +bitten http://bitten.edgewall.org/intertrac/ # Bitten's Trac + Mercurial http://www.selenic.com/mercurial/wiki/index.cgi/ # the wiki for the Mercurial distributed SCM +hg http://www.selenic.com/hg/rev/$1?rev=$2 # Changeset $1 $2 in Mercurial repository +hg-issue http://mercurial.selenic.com/bts/issue # Issue $1 in Mercurial BTS RFC http://tools.ietf.org/html/rfc$1 # IETF's RFC $1 ISO http://en.wikipedia.org/wiki/ISO_ # ISO Standard $1 in Wikipedia kb http://support.microsoft.com/kb/$1/en-us/ # Article $1 in Microsoft's Knowledge Base +pypi http://pypi.python.org/pypi/ # $1 package in the Python Package Index +CheeseShop http://pypi.python.org/pypi/ # $1 package in the Python Package Index +peak http://peak.telecommunity.com/DevCenter/ # $1 in Python Enterprise Application Kit's Wiki +setuptools-issue http://bugs.python.org/setuptools/issue # issue$1 in legacy Setuptools tracker +pypa-setuptools-issue https://bitbucket.org/pypa/setuptools/issue/ # issue #$1 in BitBucket Setuptools tracker + +SQLite http://www.sqlite.org/cvstrac/wiki?p=$1 # $1 page in the CvsTrac for SQLite +SQLiteTkt http://www.sqlite.org/cvstrac/tktview?tn=$1 # Ticket $1 in the CvsTrac for SQLite + +mysql-bugs http://bugs.mysql.com/bug.php?id= # Bug #$1 in MySQL's bug database +mysql-issue http://bugs.mysql.com/bug.php?id= # Bug #$1 in MySQL's bug database + +MODPYTHON http://issues.apache.org/jira/browse/MODPYTHON- # Issue $1 in mod_python's JIRA instance +mod-python-issue http://issues.apache.org/jira/browse/MODPYTHON- # Issue $1 in mod_python's JIRA instance + +SvnWiki http://www.orcaware.com/svn/wiki/ # Subversion Wiki +svnissue http://subversion.tigris.org/issues/show_bug.cgi?id= # Subversion issue #$1 +svn-issue http://subversion.tigris.org/issues/show_bug.cgi?id= # Subversion issue #$1 +svncset http://svn.collab.net/viewvc/svn?view=revision&revision= # Subversion [$1] + +mod-wsgi http://code.google.com/p/modwsgi/wiki/ # mod_wsgi Wiki on Google Code +mod-wsgi-issue http://code.google.com/p/modwsgi/issues/detail?id= # mod_wsgi Issue Tracker on Google Code + chromium-issue http://code.google.com/p/chromium/issues/detail?id= Django http://code.djangoproject.com/intertrac/ # Django's Trac +AgileTrac http://www.agile-trac.org/intertrac/ # Plugin adding Iterations to Trac CreoleWiki http://wikicreole.org/wiki/ Creole1Wiki http://wikicreole.org/wiki/ Modified: bloodhound/vendor/trac/current/trac/wiki/default-pages/InterTrac URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/wiki/default-pages/InterTrac?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/wiki/default-pages/InterTrac (original) +++ bloodhound/vendor/trac/current/trac/wiki/default-pages/InterTrac Fri Nov 14 11:06:23 2014 @@ -42,8 +42,7 @@ It is necessary to setup a configuration This configuration has to be done in the TracIni file, `[intertrac]` section. Example configuration: -{{{ -... +{{{#!ini [intertrac] # -- Example of setting up an alias: t = trac @@ -66,7 +65,7 @@ a ''compatibility'' mode: ([trac:r3526 r3526] to be precise), then it doesn't know how to dispatch an InterTrac link, and it's up to the local Trac to prepare the correct link. Not all links will work that way, but the most common do. - This is called the compatibility mode, and is `true` by default. + This is called the compatibility mode, and is `false` by default. * If you know that the remote Trac knows how to dispatch InterTrac links, you can explicitly disable this compatibility mode and then ''any'' TracLinks can become an InterTrac link. Modified: bloodhound/vendor/trac/current/trac/wiki/default-pages/PageTemplates URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/wiki/default-pages/PageTemplates?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/wiki/default-pages/PageTemplates (original) +++ bloodhound/vendor/trac/current/trac/wiki/default-pages/PageTemplates Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ = Wiki Page Templates = - ''(since [http://trac.edgewall.org/milestone/0.11 0.11])'' + ''(since [trac:milestone:0.11 0.11])'' The default content for a new wiki page can be chosen from a list of page templates. Modified: bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAccessibility URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAccessibility?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAccessibility (original) +++ bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAccessibility Fri Nov 14 11:06:23 2014 @@ -4,9 +4,9 @@ Not every user has a graphic environment The keyboard shortcuts must be enabled for a session through the [/prefs/keybindings Keyboard Shortcuts] preferences panel. -Trac supports accessibility keys for the most common operations. +Trac supports accessibility keys for the most common operations. The access keys differ by browser and the following work for several browsers, but see [http://en.wikipedia.org/wiki/Access_key#Access_in_different_browsers access in different browsers] for more details. - on Linux platforms, press any of the keys listed below in combination with the `<Alt>` key - - on a Mac, use the `<ctrl>` key instead + - on a Mac, use the `<Ctrl>` + `<Opt>` key instead - on Windows, you need to hit `<Shift> + <Alt> + <Key>`. This works for most browsers (Firefox, Chrome, Safari and Internet Explorer) == Global Access Keys == Modified: bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAdmin URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAdmin?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAdmin (original) +++ bloodhound/vendor/trac/current/trac/wiki/default-pages/TracAdmin Fri Nov 14 11:06:23 2014 @@ -32,7 +32,7 @@ This subcommand is very important as it' [[TracAdminHelp(initenv)]] -It supports an extra `--inherit` option, which can be used to specify a global configuration file which can be used share settings between several environments. You can also inherit from a shared configuration afterwards, by setting the `[inherit] file` option in the `conf/trac.ini` file in your newly created environment, but the advantage of specifying the inherited configuration file at environment creation time is that only the options ''not'' already specified in the global configuration file will be written in the created environment's `conf/trac.ini` file. +It supports an extra `--inherit` option, which can be used to specify a global configuration file which can be used to share settings between several environments. You can also inherit from a shared configuration afterwards, by setting the `[inherit] file` option in the `conf/trac.ini` file in your newly created environment, but the advantage of specifying the inherited configuration file at environment creation time is that only the options ''not'' already specified in the global configuration file will be written in the created environment's `conf/trac.ini` file. See TracIni#GlobalConfiguration. Note that in version 0.11 of Trac, `initenv` lost an extra last argument `<templatepath>`, which was used in previous versions to point to the `templates` folder. If you are using the one-liner '`trac-admin /path/to/trac/ initenv <projectname> <db> <repostype> <repospath>`' in the above and getting an error that reads ''''`Wrong number of arguments to initenv: 4`'''', then this is because you're using a `trac-admin` script from an '''older''' version of Trac.