changeset 611:b70f7c82b9b8

svncommands: fix layering violation & tweak error messages. Importing `SubversionException' directly from `svn.core' is a layering violation: Anything within the Subversion bindings should only be accessed via svnwrap. The advantages to doing this are twofold: we only need to intercept missing bindings in one place, and we have the option of supporting alternate bindings. As an added bonus, the recently-added support for intercepting missing Subversion bindings actually works. Two error messages are tweaked to remove `It appears...' from one error message (just blaming Subversion instead) and make both errors include the URL in the suggested command line.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Fri, 14 May 2010 20:22:32 +0200
parents 300b917d23c5
children 2c15e4c50a54
files hgsubversion/svncommands.py hgsubversion/svnrepo.py hgsubversion/svnwrap/svn_swig_wrapper.py
diffstat 3 files changed, 27 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/svncommands.py
+++ b/hgsubversion/svncommands.py
@@ -8,8 +8,6 @@ from mercurial import node
 from mercurial import util as hgutil
 from mercurial import error
 
-from svn import core
-
 import maps
 import svnwrap
 import svnrepo
@@ -420,11 +418,8 @@ def svn(ui, repo, subcommand, *args, **o
     try:
         commandfunc = table[subcommand]
         return commandfunc(ui, args=args, repo=repo, **opts)
-    except core.SubversionException, e:
-        if e.apr_err == core.SVN_ERR_RA_SERF_SSL_CERT_UNTRUSTED:
-            raise hgutil.Abort('It appears svn does not trust the ssl cert for this site.\n'
-                     'Please try running svn ls on that url first.')
-        raise
+    except svnwrap.SubversionConnectionException, e:
+        raise hgutil.Abort(*e.args)
     except TypeError:
         tb = traceback.extract_tb(sys.exc_info()[2])
         if len(tb) == 1:
--- a/hgsubversion/svnrepo.py
+++ b/hgsubversion/svnrepo.py
@@ -93,7 +93,11 @@ class svnremoterepo(mercurial.repo.repos
 
     @propertycache
     def svn(self):
-        return svnwrap.SubversionRepo(*self.svnauth)
+        try:
+            return svnwrap.SubversionRepo(*self.svnauth)
+        except svnwrap.SubversionConnectionException, e:
+            self.ui.traceback()
+            raise hgutil.Abort(e)
 
     @property
     def svnuuid(self):
--- a/hgsubversion/svnwrap/svn_swig_wrapper.py
+++ b/hgsubversion/svnwrap/svn_swig_wrapper.py
@@ -44,6 +44,11 @@ class SubversionRepoCanNotDiff(Exception
     """Exception raised when the svn API diff3() command cannot be used
     """
 
+class SubversionConnectionException(Exception):
+    """Exception raised when a generic error occurs when connecting to a
+       repository.
+    """
+
 '''Default chunk size used in fetch_history_at_paths() and revisions().'''
 _chunk_size = 1000
 
@@ -252,9 +257,22 @@ class SubversionRepo(object):
             path=urllib.quote(path)
             url = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
             self.ra = ra.open2(url, callbacks,
-                               svn_config, self.pool)
+                              svn_config, self.pool)
         except core.SubversionException, e:
-            raise hgutil.Abort(e.args[0])
+            if e.apr_err == core.SVN_ERR_RA_SERF_SSL_CERT_UNTRUSTED:
+                msg = ('Subversion does not trust the SSL certificate for this '
+                       'site; please try running \'svn ls %s\' first.'
+                       % self.svn_url)
+            elif e.apr_err == core.SVN_ERR_RA_DAV_REQUEST_FAILED:
+                msg = ('Failed to open Subversion repository; please try '
+                       'running \'svn ls %s\' for details.' % self.svn_url)
+            else:
+                msg = e.args[0]
+                for k, v in vars(core).iteritems():
+                    if k.startswith('SVN_ERR_') and v == e.apr_err:
+                        msg = '%s (%s)' % (msg, k)
+                        break
+            raise SubversionConnectionException(msg)
 
     def HEAD(self):
         return ra.get_latest_revnum(self.ra, self.pool)