Index: tracdarcs/components.py
===================================================================
--- tracdarcs/components.py	(revision 185)
+++ tracdarcs/components.py	(revision 195)
@@ -20,5 +20,5 @@
 from trac.db import Column, DatabaseManager, Index, Table
 from trac.env import IEnvironmentSetupParticipant
-from trac.util.text import shorten_line
+from trac.util.text import shorten_line, to_unicode
 from trac.versioncontrol import IRepositoryConnector, NoSuchChangeset
 from trac.versioncontrol.web_ui import IPropertyRenderer, RenderedProperty
@@ -86,14 +86,42 @@
 
     def _format_link(self, formatter, ns, rev, label):
-
-        repos = self.env.get_repository()
-        try:
-            chgset = repos.get_changeset(rev)
-            return tag.a(chgset.rev, class_="changeset",
-                         title=shorten_line(chgset.message),
-                         href=formatter.href.changeset(chgset.rev))
-        except NoSuchChangeset, e:
-            return tag.a(label, class_="missing changeset",
-                         title="No changeset for %s" % rev, rel="nofollow")
+        reponame = None
+
+        # See if the context carries a repository...
+        context = formatter.context
+        while context:
+            if context.resource.realm in ('source', 'changeset'):
+                reponame = context.resource.parent.id
+                break
+            context = context.parent
+
+        # If it does not, take the first repository containing the
+        # specified revision, if any. We can do this assuming that
+        #   a) we are dealing with full darcs hashes and
+        #   b) darcs hashes are globally unique
+        if reponame is None:
+            db = self.env.get_db_cnx()
+            c = db.cursor()
+            c.execute('SELECT r.value '
+                      'FROM darcs_changesets c JOIN repository r ON c.repo_id = r.id '
+                      'WHERE c.hash = %s AND r.name = %s '
+                      'ORDER BY r.id '
+                      'LIMIT 1', (rev, 'name',))
+            row = c.fetchone()
+            reponame = row and row[0] or ''
+
+        repos = self.env.get_repository(reponame)
+        if repos:
+            try:
+                chgset = repos.get_changeset(rev)
+                return tag.a(chgset.rev, class_="changeset",
+                             title=shorten_line(chgset.message),
+                             href=formatter.href.changeset(chgset.rev, reponame))
+            except NoSuchChangeset, e:
+                errmsg = to_unicode(e)
+        else:
+            errmsg = 'Repository "%s" not found' % reponame
+
+        return tag.a(label, class_="missing changeset", title=errmsg, rel="nofollow")
 
 class DarcsSetup(Component):
Index: tracdarcs/changesparser.py
===================================================================
--- tracdarcs/changesparser.py	(revision 183)
+++ tracdarcs/changesparser.py	(revision 196)
@@ -120,19 +120,37 @@
                 self.patches.append(patch)
 
-    from string import maketrans
-    tt = maketrans(BADCHARS, "-"*len(BADCHARS))
-    changes = changes.translate(tt)
-
     handler = SAXHandler()
     try:
         parseString(changes, handler)
     except SAXParseException, e:
+        # Retry, after removing badchars from the input
+
         lines = changes.splitlines()
-        line = lines[e._linenum-1]
-        log.critical("Cannot complete the parse of the XML output due to a SAX Error, "
-                     "on the changeset %d: %s", len(handler.patches), e)
-        log.warning("%s", line)
         if e._colnum:
-            log.warning('-'*(e._colnum-1)+'^'*5)
+            line = lines[e._linenum-1][:e._colnum+35]
+            pointer = '\nhere: ' + '-'*(e._colnum-1) + '^'*5
+        else:
+            line = lines[e._linenum-1][:60]
+            pointer = ''
+        log.warning("SAX couldn't parse the XML changes stream "
+                    "due to an error at line %d on changeset "
+                    "%d: %s\ntext: %s%s\n"
+                    "Replacing bad characters with a hyphen "
+                    "and retrying...",
+                    e._linenum, len(handler.patches), e,
+                    repr(line)[1:-1], pointer)
+
+        from string import maketrans
+        tt = maketrans(BADCHARS, "-"*len(BADCHARS))
+        changes = changes.translate(tt)
+
+        handler = SAXHandler()
+        try:
+            parseString(changes, handler)
+        except SAXParseException, e:
+            log.critical("Sorry, the substitution didn't help, giving up!")
+        else:
+            log.warning("... the replacement did the trick, going on!")
+
     return handler.patches
 
