diff --git a/trac/versioncontrol/api.py b/trac/versioncontrol/api.py
--- a/trac/versioncontrol/api.py
+++ b/trac/versioncontrol/api.py
@@ -27,12 +27,28 @@
 from trac.config import ListOption, Option
 from trac.core import *
 from trac.perm import PermissionError
-from trac.resource import IResourceManager, ResourceSystem, ResourceNotFound
+from trac.resource import IResourceManager, Resource, ResourceSystem, \
+                          ResourceNotFound
 from trac.util.text import printout, to_unicode
 from trac.util.translation import _
 from trac.web.api import IRequestFilter
 
 
+def make_repo_resource(reponame):
+    """Create a repository resource for the given reponame, or return None
+    for the default repository.
+    """
+    if reponame:
+        return Resource('repository', reponame)
+
+
+def split_vc_resource(resource):
+    """Split a versioncontrol resource into reponame and path."""
+    if resource.parent and resource.parent.realm == 'repository':
+        return (resource.parent.id, resource.id)
+    return ('', resource.id)
+
+
 class IRepositoryConnector(Interface):
     """Provide support for a specific version control system."""
 
@@ -343,21 +359,20 @@
 
     # IResourceManager methods
 
-    # Note: with multiple repository support, the repository name becomes
-    #       part of the 'id', which becomes a `(reponame, rev or path)` pair.
-
     def get_resource_realms(self):
         yield 'changeset'
         yield 'source'
+        yield 'repository'
 
     def get_resource_description(self, resource, format=None, **kwargs):
-        reponame, id = resource.id
         if resource.realm == 'changeset':
+            (reponame, id) = split_vc_resource(resource)
             if reponame:
                 return _("Changeset %(rev)s in %(repo)s", rev=id, repo=reponame)
             else:
                 return _("Changeset %(rev)s", rev=id)
         elif resource.realm == 'source':
+            (reponame, id) = split_vc_resource(resource)
             version = in_repo = ''
             if format == 'summary':
                 repos = resource.env.get_repository(reponame)
@@ -375,14 +390,18 @@
             if reponame:
                 in_repo = _(" in %(repo)s", repo=reponame)
             return ''.join([kind, ' ', id, version, in_repo])
+        elif resource.realm == 'repository':
+            return _("Repository %(repo)s", repo=resource.id)
 
     def get_resource_url(self, resource, href, **kwargs):
-        if resource and resource.realm in ('source', 'changeset'):
-            repos, id = resource.id
-            if resource.realm == 'source':
-                return href.source(repos, id)
-            else:
-                return href.changeset(id, repos)
+        if resource.realm == 'changeset':
+            (reponame, id) = split_vc_resource(resource)
+            return href.changeset(id, reponame)
+        elif resource.realm == 'source':
+            (reponame, id) = split_vc_resource(resource)
+            return href.source(reponame, id)
+        elif resource.realm == 'repository':
+            return href.source(resource.id)
 
     # IRepositoryProvider methods
 
@@ -524,7 +543,7 @@
         """
         while context:
             if context.resource.realm in ('source', 'changeset'):
-                return context.resource.id[0]
+                return split_vc_resource(context.resource)[0]
             context = context.parent
 
     def get_all_repositories(self):
diff --git a/trac/versioncontrol/svn_prop.py b/trac/versioncontrol/svn_prop.py
--- a/trac/versioncontrol/svn_prop.py
+++ b/trac/versioncontrol/svn_prop.py
@@ -21,7 +21,7 @@
 from genshi.builder import tag
 
 from trac.core import *
-from trac.versioncontrol import NoSuchNode
+from trac.versioncontrol import NoSuchNode, split_vc_resource
 from trac.versioncontrol.svn_fs import _path_within_scope
 from trac.versioncontrol.web_ui.browser import IPropertyRenderer
 from trac.versioncontrol.web_ui.changeset import IPropertyDiffRenderer
@@ -147,7 +147,7 @@
         has_eligible = name in ('svnmerge-integrated', 'svn:mergeinfo')
         revs_label = (_('merged'), _('blocked'))[name.endswith('blocked')]
         revs_cols = has_eligible and 2 or None
-        (reponame, target_path) = context.resource.id
+        (reponame, target_path) = split_vc_resource(context.resource)
         repos = self.env.get_repository(reponame)
         target_rev = context.resource.version
         if has_eligible:
@@ -228,7 +228,7 @@
 
 def _get_source_link(spath, context):
     """Return a link to a merge source."""
-    reponame = context.resource.id[0]
+    reponame = split_vc_resource(context.resource)[0]
     return tag.a('/' + spath, title=_('View merge source'),
                  href=context.href.browser(reponame, spath,
                                            rev=context.resource.version))
@@ -238,7 +238,7 @@
     given, to the revision itself for a single revision, or a `<span>`
     with "no revision" for none.
     """
-    reponame = context.resource.id[0]
+    reponame = split_vc_resource(context.resource)[0]
     if not revs:
         return tag.span(label, title=_('No revisions'))
     elif ',' in revs or '-' in revs:
@@ -262,7 +262,8 @@
         # Build 3 columns table showing modifications on merge sources
         # || source || added revs || removed revs ||
         # || source || removed                    ||
-        repos = self.env.get_repository(old_context.resource.id[0])
+        reponame = split_vc_resource(old_context.resource)[0]
+        repos = self.env.get_repository(reponame)
         def parse_sources(props):
             sources = {}
             for line in props[name].splitlines():
diff --git a/trac/versioncontrol/web_ui/browser.py b/trac/versioncontrol/web_ui/browser.py
--- a/trac/versioncontrol/web_ui/browser.py
+++ b/trac/versioncontrol/web_ui/browser.py
@@ -28,7 +28,7 @@
 from trac.mimeview.api import Mimeview, is_binary, get_mimetype, \
                               IHTMLPreviewAnnotator, Context
 from trac.perm import IPermissionRequestor
-from trac.resource import ResourceNotFound, Resource
+from trac.resource import Resource, ResourceNotFound
 from trac.util import embedded_numbers
 from trac.util.compat import all
 from trac.util.datefmt import http_date, utc
@@ -41,7 +41,8 @@
 from trac.wiki.api import IWikiSyntaxProvider, IWikiMacroProvider, parse_args
 from trac.wiki.formatter import format_to_html, format_to_oneliner
 from trac.versioncontrol.api import RepositoryManager, NoSuchChangeset, \
-                                    NoSuchNode
+                                    NoSuchNode, make_repo_resource, \
+                                    split_vc_resource
 from trac.versioncontrol.web_ui.util import *
 
 
@@ -363,7 +364,9 @@
             except NoSuchChangeset, e:
                 raise ResourceNotFound(e.message, _('Invalid Changeset Number'))
 
-            context = context('source', (reponame, path), node.created_rev)
+            context = context(Resource('source', path,
+                                       version=node.created_rev,
+                                       parent=make_repo_resource(reponame)))
 
         # Prepare template data
         path_links = get_path_links(req.href, reponame, path, rev, order, desc)
@@ -789,11 +792,9 @@
     def __init__(self, env, context):
         self.env = env
         self.context = context
-        # `context`'s resource is ('source', (reponame, path), version=rev)
-        r = context.resource
-        self.reponame, self.path = r.id
+        (self.reponame, self.path) = split_vc_resource(context.resource)
         self.repos = env.get_repository(self.reponame)
-        self.rev = r.version
+        self.rev = context.resource.version
         # maintain state
         self.prev_chgset = None
         self.chgset_data = {}
diff --git a/trac/versioncontrol/web_ui/changeset.py b/trac/versioncontrol/web_ui/changeset.py
--- a/trac/versioncontrol/web_ui/changeset.py
+++ b/trac/versioncontrol/web_ui/changeset.py
@@ -42,7 +42,8 @@
                            unicode_urlencode, shorten_line, CRLF
 from trac.util.translation import _, ngettext
 from trac.versioncontrol.api import RepositoryManager, Changeset, Node, \
-                                    NoSuchChangeset
+                                    NoSuchChangeset, make_repo_resource, \
+                                    split_vc_resource
 from trac.versioncontrol.diff import get_diff_options, diff_blocks, \
                                      unified_diff
 from trac.versioncontrol.web_ui.browser import BrowserModule
@@ -485,12 +486,15 @@
         #           with _that_ node specific history...
 
         options = data['diff']['options']
+        repo_resource = make_repo_resource(reponame)
 
         def _prop_changes(old_node, new_node):
-            old_source = Resource('source', (reponame, old_node.created_path),
-                                  version=old_node.created_rev)
-            new_source = Resource('source', (reponame, new_node.created_path),
-                                  version=new_node.created_rev)
+            old_source = Resource('source', old_node.created_path,
+                                  version=old_node.created_rev,
+                                  parent=repo_resource)
+            new_source = Resource('source', new_node.created_path,
+                                  version=new_node.created_rev,
+                                  parent=repo_resource)
             old_props = new_props = []
             if 'FILE_VIEW' in req.perm(old_source):
                 old_props = old_node.get_properties()
@@ -854,12 +858,13 @@
                 
             uids_seen = {}
             def generate_changesets(reponame, repos):
+                repo_resource = make_repo_resource(reponame)
                 for _, changesets in groupby(repos.get_changesets(start, stop),
                                              key=collapse_changesets):
                     viewable_changesets = []
                     for cset in changesets:
-                        cset_resource = Resource('changeset', 
-                                                 (reponame, cset.rev))
+                        cset_resource = Resource('changeset', cset.rev,
+                                                 parent=repo_resource)
                         if 'CHANGESET_VIEW' in req.perm(cset_resource):
                             repos_for_uid = [reponame]
                             uid = repos.get_changeset_uid(cset.rev)
@@ -885,7 +890,7 @@
         changesets, show_location, show_files = event[3]
         cset, cset_resource, repos_for_uid = changesets[0]
         message = cset.message or ''
-        reponame = cset_resource.id[0] # first repo
+        reponame = split_vc_resource(cset_resource)[0]
         rev_b, rev_a = cset.rev, cset.rev
 
         if field == 'url':
@@ -1069,7 +1074,8 @@
             #cset = Resource('repository', reponame).child('changeset' , rev)
             #cset = repos.resource.child('changeset' , rev)
             #cset = repos.changeset_resource(rev)
-            cset = Resource('changeset', (reponame, rev))
+            cset = Resource('changeset', rev,
+                            parent=make_repo_resource(reponame))
             if 'CHANGESET_VIEW' in req.perm(cset):
                 yield (req.href.changeset(rev, reponame),
                        '[%s]: %s' % (rev, shorten_line(log)),
