Index: scripts/trac-admin
===================================================================
--- scripts/trac-admin	(revision 1333)
+++ scripts/trac-admin	(working copy)
@@ -583,10 +583,25 @@
         print 'Congratulations!'
         print
         
-    _help_resync = [('resync', 'Re-synchronize trac with the repository')]
+    _help_resync = [('resync [start-rev][:end-rev]', 'Re-synchronize trac with the repository')]
     
     ## Resync
     def do_resync(self, line):
+        arg = self.arg_tokenize(line)
+        if len(arg) > 0 and arg[0] != '':
+            sep = arg[0].find(':')
+            if sep == 0:                # only the 'end-rev' given
+                start = 0               # forces a resync from the start
+                end = int(arg[0][1:])
+            elif sep > 0:               # both 'start-rev' and 'end-rev' given
+                start = int(arg[0][:sep])
+                end = int(arg[0][sep+1:])
+            else:                       # only the 'start-rev' given
+                start = int(arg[0])
+                end = -1
+        else:                           # no revs given
+            start = 0
+            end = -1
         from svn import util, repos, core
         core.apr_initialize()
         pool = core.svn_pool_create(None)
@@ -603,9 +618,23 @@
         
         cnx = self.__env.get_db_cnx()
         print 'resyncing...'
-        self.db_execsql("DELETE FROM revision")
-        self.db_execsql("DELETE FROM node_change")
-        sync.sync(cnx, rep, fs_ptr, pool)
+        if start > 0 and end > 0:
+            print '  from revision %d to revision %d' % (start, end)
+            self.db_execsql("DELETE FROM revision where rev >= %d and rev <= %d" % (start, end))
+            self.db_execsql("DELETE FROM node_change where rev >= %d and rev <= %d" % (start, end))
+        elif start > 0:
+            print '  from revision %d to the youngest revision' % start
+            self.db_execsql("DELETE FROM revision where rev >= %d" % start)
+            self.db_execsql("DELETE FROM node_change where rev >= %d" % start)
+        elif end > 0:
+            print '  from the first revision to revision %d' % end
+            self.db_execsql("DELETE FROM revision where rev <= %d" % end)
+            self.db_execsql("DELETE FROM node_change where rev <= %d" % end)
+        else:
+            print '  all revisions'
+            self.db_execsql("DELETE FROM revision")
+            self.db_execsql("DELETE FROM node_change")
+        sync.sync(cnx, rep, fs_ptr, pool, start, end)
         print 'done.'
         
     ## Wiki
Index: trac/sync.py
===================================================================
--- trac/sync.py	(revision 1333)
+++ trac/sync.py	(working copy)
@@ -21,11 +21,15 @@
 
 from svn import fs, util, delta, repos, core
 
+import posixpath
 
-def sync(db, repos, fs_ptr, pool):
+
+def sync(db, repos, fs_ptr, pool, start=-1, end=-1):
     """
     Update the revision and node_change tables to be in sync with
     the repository.
+    start -- start from this changeset (-1 means the youngest stored)
+    end   -- end at this changeset (-1 means the youngest rev in the repository)
     """
 
     if util.SVN_VER_MAJOR < 1:
@@ -37,8 +41,15 @@
     cursor.execute("SELECT COALESCE(max(rev),0) FROM revision")
     youngest_stored =  int(cursor.fetchone()[0])
     max_rev = fs.youngest_rev(fs_ptr, pool)
-    num = max_rev - youngest_stored
-    offset = youngest_stored + 1
+    if end < 0 or end > max_rev:
+        end = max_rev
+    # Note: after that point, start is readjusted to be one changeset _before_ the real start
+    if start < 0 or start > youngest_stored:
+        start = youngest_stored
+    else:
+        start -= 1
+    num = end - start
+    offset = start + 1
     
     subpool = core.svn_pool_create(pool)
     for rev in range(num):
@@ -77,11 +88,12 @@
     ||     ||  'M'   || modified path                                 ||
     ||     ||  'C'   || original rev, original path // copied path    ||
     ||     ||  'R'   || original rev, original path // renamed path   ||
+    ||     ||  'm'   || original rev, original path // modified path  ||
     ||     ||  'd'   || original rev, original path // deleted path   ||
 
     The 'ADM' operations are direct operations.
-    The 'CR' operation can be direct operations.
-    The 'CRdm' may happen after a 'CR' operation on a parent path.
+    The 'CR' operations can be direct operations.
+    The 'CRdm' operations may happen after a 'CR' operation on a parent path.
     """
 
     class ChangeEditor(delta.Editor):

