Index: trac/versioncontrol/api.py
===================================================================
--- trac/versioncontrol/api.py	(revision 4279)
+++ trac/versioncontrol/api.py	(working copy)
@@ -24,6 +24,7 @@
 from trac.config import Option
 from trac.core import *
 from trac.perm import PermissionError
+from trac.web.api import IRequestFilter
 
 
 class IRepositoryConnector(Interface):
@@ -50,6 +51,8 @@
     It provides easy access to the configured implementation.
     """
 
+    implements(IRequestFilter)
+
     connectors = ExtensionPoint(IRepositoryConnector)
 
     repository_type = Option('trac', 'repository_type', 'svn',
@@ -62,6 +65,20 @@
         self._lock = threading.Lock()
         self._connector = None
 
+    # IRequestFilter methods
+
+    def pre_process_request(self, req, handler):
+        from trac.web.chrome import Chrome        
+        if handler is not Chrome(self.env):
+            repos = self.get_repository(req.authname)
+            if hasattr(repos, 'sync'):
+                repos.sync()
+        return handler
+
+    def post_process_request(self, req, template, content_type):
+        return (template, content_type)
+
+
     # Public API methods
 
     def get_repository(self, authname):
@@ -120,6 +137,10 @@
         """Close the connection to the repository."""
         raise NotImplementedError
 
+    def clear(self):
+        """Clear any data that may have been cached in instance properties."""
+        pass
+
     def get_changeset(self, rev):
         """Retrieve a Changeset corresponding to the  given revision `rev`."""
         raise NotImplementedError
Index: trac/versioncontrol/svn_fs.py
===================================================================
--- trac/versioncontrol/svn_fs.py	(revision 4279)
+++ trac/versioncontrol/svn_fs.py	(working copy)
@@ -307,6 +307,9 @@
         
         self.log.debug("Opening subversion file-system at %s with scope %s" \
                        % (self.path, self.scope))
+        self.clear()
+
+    def clear(self):
         self.youngest = None
         self.oldest = None
 
Index: trac/versioncontrol/cache.py
===================================================================
--- trac/versioncontrol/cache.py	(revision 4279)
+++ trac/versioncontrol/cache.py	(working copy)
@@ -31,22 +31,16 @@
         Repository.__init__(self, repos.name, authz, log)
         self.db = db
         self.repos = repos
-        self.synced = 0
+        self.sync()
 
     def close(self):
         self.repos.close()
 
     def get_changeset(self, rev):
-        if not self.synced:
-            self.sync()
-            self.synced = 1
         return CachedChangeset(self.repos.normalize_rev(rev), self.db,
                                self.authz)
 
     def get_changesets(self, start, stop):
-        if not self.synced:
-            self.sync()
-            self.synced = 1
         cursor = self.db.cursor()
         cursor.execute("SELECT rev FROM revision "
                        "WHERE time >= %s AND time < %s "
@@ -71,6 +65,7 @@
             raise TracError, ("The 'repository_dir' has changed, "
                               "a 'trac-admin resync' operation is needed.")
 
+        self.repos.clear()
         youngest_stored = self.repos.get_youngest_rev_in_cache(self.db)
 
         if youngest_stored != str(self.repos.youngest_rev):
@@ -107,13 +102,7 @@
                                    (str(current_rev), path, kind, action,
                                    base_path, base_rev))
                 current_rev = self.repos.next_rev(current_rev)
-            try:
-                self.db.commit()
-            except:
-                # See <http://trac.edgewall.org/ticket/4120>: this breaks badly
-                # while rendering the timeline, because the commit happens
-                # while iterating over a recordset
-                pass
+            self.db.commit()
             self.repos.authz = authz # restore permission checking
 
     def get_node(self, path, rev=None):
@@ -126,7 +115,7 @@
         return self.repos.oldest_rev
 
     def get_youngest_rev(self):
-        return self.repos.youngest_rev
+        return self.repos.get_youngest_rev_in_cache(self.db)
 
     def previous_rev(self, rev):
         return self.repos.previous_rev(rev)

