Index: tracdarcs/__init__.py
===================================================================
--- tracdarcs/__init__.py	(revision 143)
+++ tracdarcs/__init__.py	(revision 144)
@@ -22,3 +22,4 @@
     __version__ = "0.7"
 
-from tracdarcs.components import DarcsConnector, DarcsSetup
+from tracdarcs.components import DarcsConnector, DarcsSetup, \
+     EquivalentChangesetsRenderer
Index: tracdarcs/components.py
===================================================================
--- tracdarcs/components.py	(revision 139)
+++ tracdarcs/components.py	(revision 144)
@@ -22,4 +22,6 @@
 from trac.util.text import shorten_line
 from trac.versioncontrol import IRepositoryConnector, NoSuchChangeset
+from trac.versioncontrol.web_ui import IPropertyRenderer, RenderedProperty
+
 from trac.wiki import IWikiSyntaxProvider
 
@@ -162,2 +164,19 @@
             for stmt in connector.to_sql(t):
                 c.execute(stmt)
+
+class EquivalentChangesetsRenderer(Component):
+    implements(IPropertyRenderer)
+
+    def match_property(self, name, mode):
+        return (mode == 'revprop' and name == 'EqChangesets') and 5 or 0
+
+    def render_property(self, name, mode, context, props):
+        eqcsets = props[name]
+        eqlinks = [tag.a(repos or '(default)', class_="changeset",
+                         title="Equivalent patch %s in repository %s" % (
+                             rev, repos or '(default)'),
+                         href=context.href.changeset(rev, repos))
+                   for repos, rev in eqcsets]
+        return RenderedProperty(name='Present in:',
+                                name_attributes=[("class", "property")],
+                                content=tag([eqlinks]))
Index: tracdarcs/repository.py
===================================================================
--- tracdarcs/repository.py	(revision 140)
+++ tracdarcs/repository.py	(revision 145)
@@ -180,7 +180,12 @@
 
         c = self.db.cursor()
-        c.execute('SELECT rev,path FROM darcs_node_changes '
-                  'WHERE repo_id = %s AND node_id = %s AND rev >= %s AND rev <= %s',
-                  (self.repo_id,node_id,old_rev,new_rev))
+        if node_id is not None:
+            c.execute('SELECT rev,path FROM darcs_node_changes '
+                      'WHERE repo_id = %s AND node_id = %s AND rev >= %s AND rev <= %s',
+                      (self.repo_id,node_id,old_rev,new_rev))
+        else:
+            c.execute('SELECT rev,path FROM darcs_node_changes '
+                      'WHERE repo_id = %s AND rev >= %s AND rev <= %s',
+                      (self.repo_id,old_rev,new_rev))
         node_set = dict()
         node_list = []
@@ -451,3 +456,16 @@
         # "Content-Encoding: gzip" that in turn may confuse the browser.
         # Darcs recognizes also extension-stripped hashnames.
-        return dict(Hashname=self.__hash[:-3])
+
+        props = dict(Hashname=self.__hash[:-3])
+
+        c = self.__db.cursor()
+        c.execute('SELECT dcs.repo_id, dcs.rev '
+                  'FROM darcs_changesets dcs, darcs_changesets dcs2 '
+                  'WHERE dcs2.repo_id = %s AND dcs2.rev = %s '
+                  '  AND dcs.hash = dcs2.hash '
+                  '  AND dcs.repo_id <> dcs2.repo_id', (self.repo_id, self.rev))
+        eqcsets = [(repo, rev) for repo,rev in c.fetchall()]
+        if eqcsets:
+            props['EqChangesets'] = eqcsets
+
+        return props
