Index: trac/versioncontrol/cache.py
===================================================================
--- trac/versioncontrol/cache.py	(revision 3116)
+++ trac/versioncontrol/cache.py	(working copy)
@@ -40,8 +40,8 @@
         if not self.synced:
             self.sync()
             self.synced = 1
-        return CachedChangeset(self.repos.normalize_rev(rev), self.db,
-                               self.authz)
+        return CachedChangeset(self.repos, self.repos.normalize_rev(rev),
+                               self.db, self.authz)
 
     def sync(self):
         self.log.debug("Checking whether sync with repository is needed")
@@ -134,7 +134,8 @@
 
 class CachedChangeset(Changeset):
 
-    def __init__(self, rev, db, authz):
+    def __init__(self, repos, rev, db, authz):
+        self.repos = repos
         self.db = db
         self.authz = authz
         cursor = self.db.cursor()
@@ -161,4 +162,5 @@
             yield path, kind, change, base_path, base_rev
 
     def get_properties(self):
-        return []
+        for prop in self.repos.get_changeset(self.rev).get_properties():
+            yield prop
Index: trac/versioncontrol/svn_fs.py
===================================================================
--- trac/versioncontrol/svn_fs.py	(revision 3116)
+++ trac/versioncontrol/svn_fs.py	(working copy)
@@ -616,6 +616,14 @@
         date = core.svn_time_from_cstring(date, self.pool()) / 1000000
         Changeset.__init__(self, rev, message, author, date)
 
+    def get_properties(self):
+        props = fs.revision_proplist(self.fs_ptr, self.rev, self.pool())
+        for k,v in props.iteritems():
+            if k not in (core.SVN_PROP_REVISION_LOG,
+                         core.SVN_PROP_REVISION_AUTHOR,
+                         core.SVN_PROP_REVISION_DATE):
+                yield (k, to_unicode(v), False, '')
+
     def get_changes(self):
         pool = Pool(self.pool)
         tmp = Pool(pool)

