Index: htdocs/css/diff.css
===================================================================
--- htdocs/css/diff.css	(revision 1090)
+++ htdocs/css/diff.css	(working copy)
@@ -21,6 +21,8 @@
 #overview .mod, .diff #legend .mod { background: #fd8 }
 #overview .rem, .diff #legend .rem { background: #f88 }
 #overview .add, .diff #legend .add { background: #dfd }
+#overview .cp, .diff #legend .cp { background: #88f }
+#overview .mv, .diff #legend .mv { background: #ddd }
 
 /* Legend for diff colors */
 .diff #legend {
Index: trac/sync.py
===================================================================
--- trac/sync.py	(revision 1090)
+++ trac/sync.py	(working copy)
@@ -59,42 +59,61 @@
     core.svn_pool_destroy(subpool)
     db.commit()
 
-def insert_change (pool, fs_ptr, rev, cursor):
-    
+def insert_change(pool, fs_ptr, rev, cursor):
+
     class ChangeEditor(delta.Editor):
-        def __init__(self, rev, old_root, new_root, cursor):
+        def __init__(self, rev, new_root, cursor):
             self.rev = rev
             self.cursor = cursor
-            self.old_root = old_root
             self.new_root = new_root
+            self.deletions = {} 
         
         def delete_entry(self, path, revision, parent_baton, pool):
-            self.cursor.execute('INSERT INTO node_change (rev, name, change) '
-                                'VALUES (%s, %s, \'D\')', self.rev, path)
+            if path[0] != '/':
+                path = '/'+path
+            self.deletions[path] = 1
         
-        def add_directory(self, path, parent_baton,
-                          copyfrom_path, copyfrom_revision, dir_pool):
+        def add_file(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool):
+            self._add_entry( core.svn_node_file, path, parent_baton, copyfrom_path, copyfrom_revision )
+        def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool):
+            self._add_entry( core.svn_node_dir, path, parent_baton, copyfrom_path, copyfrom_revision )
+            
+        def _add_entry(self, node, path, parent_baton, copyfrom_path, copyfrom_revision):
+            if path[0] != '/':
+                path = '/'+path
+            if copyfrom_path and copyfrom_revision:
+                if self.deletions.has_key(copyfrom_path):
+                    self.deletions.pop(copyfrom_path)
+                    action = 'R'
+                else:
+                    action = 'C'
+                # encoding rev, copyfrom and path in a readable _and_ parseable string                    
+                name = "%d %d:%s %s" % ( 
+                    copyfrom_revision, len(copyfrom_path), copyfrom_path, path )
+            else:
+                action = 'A'
+                name = path
             self.cursor.execute('INSERT INTO node_change (rev, name, change) '
-                                'VALUES (%s, %s, \'A\')', self.rev, path)
-
-        def add_file(self, path, parent_baton,
-                     copyfrom_path, copyfrom_revision, file_pool):
-            self.cursor.execute('INSERT INTO node_change (rev, name, change) '
-                                'VALUES (%s, %s, \'A\')',self.rev, path)
+                                'VALUES (%s, %s, %s)', self.rev, name, action)
             
         def open_file(self, path, parent_baton, base_revision, file_pool):
+            if path[0] != '/':
+                path = '/'+path
             self.cursor.execute('INSERT INTO node_change (rev, name, change) '
                                 'VALUES (%s, %s, \'M\')',self.rev, path)
 
+        def finalize(self):
+            for path in self.deletions.iterkeys():
+                self.cursor.execute('INSERT INTO node_change (rev, name, change) '
+                                    'VALUES (%s, %s, \'D\')', self.rev, path)
 
-    old_root = fs.revision_root(fs_ptr, rev - 1, pool)
+
     new_root = fs.revision_root(fs_ptr, rev, pool)
     
-    editor = ChangeEditor(rev, old_root, new_root, cursor)
+    editor = ChangeEditor(rev, new_root, cursor)
     e_ptr, e_baton = delta.make_editor(editor, pool)
 
-    def authz_cb(root, path, pool): return 1
-    repos.svn_repos_dir_delta(old_root, '', '',
-                              new_root, '', e_ptr, e_baton, authz_cb,
-                              0, 1, 0, 1, pool)
+    repos.svn_repos_replay(new_root, e_ptr, e_baton, pool)
+    editor.finalize()
+        
     
Index: templates/changeset.cs
===================================================================
--- templates/changeset.cs	(revision 1090)
+++ templates/changeset.cs	(working copy)
@@ -1,6 +1,7 @@
 <?cs set:html.stylesheet = 'css/changeset.css' ?>
 <?cs include "header.cs"?>
 <?cs include "macros.cs"?>
+<?cs include "diff_macros.cs"?>
 
 <div id="ctxtnav" class="nav">
  <h2>Changeset Navigation</h2>
@@ -78,6 +79,18 @@
      <div class="add"></div>
      <a href="<?cs var:item.browser_href ?>" title="Show file in browser"><?cs
        var:item.name ?></a> <span class="comment">(added)</span>
+    <?cs elif:item.change == "R" ?>
+     <div class="mv"></div>
+     <a href="<?cs var:item.browser_href ?>" title="Show file in browser"><?cs
+       var:item.name ?></a> <span class="comment">(renamed)</span>
+       (from <a href="<?cs var:item.browser_copyfrom_href ?>" title="Show original in browser">
+        <?cs var:item.copyfrom_path ?></a>)
+    <?cs elif:item.change == "C" ?>
+     <div class="cp"></div>
+     <a href="<?cs var:item.browser_href ?>" title="Show file in browser"><?cs
+       var:item.name ?></a> <span class="comment">(copied)</span>
+       (from <a href="<?cs var:item.browser_copyfrom_href ?>" title="Show original in browser">
+        <?cs var:item.copyfrom_path ?></a>)
     <?cs elif:item.change == "M" ?>
      <div class="mod"></div>
      <a href="<?cs var:item.browser_href ?>" title="Show file in browser"><?cs
@@ -100,6 +113,8 @@
   <dl>
    <dt class="unmod"></dt><dd>Unmodified</dd>
    <dt class="add"></dt><dd>Added</dd>
+   <dt class="cp"></dt><dd>Copied</dd>
+   <dt class="mv"></dt><dd>Renamed</dd>
    <dt class="rem"></dt><dd>Removed</dd>
    <dt class="mod"></dt><dd>Modified</dd>
   </dl>

