Split get_transport_and_path_from_url() out of get_transport_and_path().
authorJelmer Vernooij <jelmer@samba.org>
Tue, 26 Nov 2013 23:35:32 +0000 (23:35 +0000)
committerJelmer Vernooij <jelmer@samba.org>
Tue, 26 Nov 2013 23:35:32 +0000 (23:35 +0000)
NEWS
dulwich/client.py
dulwich/tests/test_client.py

diff --git a/NEWS b/NEWS
index c12b0a297ca110a662bc26bea6ad420d5af91244..eeb4aeed73469ccedfe410b071fd96d01dc94ce6 100644 (file)
--- a/NEWS
+++ b/NEWS
  * Various performance improvements for object access.
    (Jelmer Vernooij)
 
+ * New function `get_transport_and_path_from_url`,
+   similar to `get_transport_and_path` but only
+   supports URLs.
+   (Jelmer Vernooij)
+
+ * Add support for file:// URLs in `get_transport_and_path_from_url`.
+   (Jelmer Vernooij)
+
  CHANGES
 
   * Ref handling has been moved to dulwich.refs.
index 13b72cef7667f095c1155bfeb710e18930db46c2..70b7ab93adb603bc7a74b4d57f33e70654fa56d1 100644 (file)
@@ -962,8 +962,8 @@ class HttpGitClient(GitClient):
         return refs
 
 
-def get_transport_and_path(uri, **kwargs):
-    """Obtain a git client from a URI or path.
+def get_transport_and_path_from_url(url, **kwargs):
+    """Obtain a git client from a URL.
 
     :param uri: URI or path
     :param thin_packs: Whether or not thin packs should be retrieved
@@ -971,7 +971,7 @@ def get_transport_and_path(uri, **kwargs):
         activity.
     :return: Tuple with client instance and relative path.
     """
-    parsed = urlparse.urlparse(uri)
+    parsed = urlparse.urlparse(url)
     if parsed.scheme == 'git':
         return (TCPGitClient(parsed.hostname, port=parsed.port, **kwargs),
                 parsed.path)
@@ -983,17 +983,36 @@ def get_transport_and_path(uri, **kwargs):
                             username=parsed.username, **kwargs), path
     elif parsed.scheme in ('http', 'https'):
         return HttpGitClient(urlparse.urlunparse(parsed), **kwargs), parsed.path
+    elif parsed.scheme == 'file':
+        return SubprocessGitClient(**kwargs), parsed.path
 
-    if parsed.scheme and not parsed.netloc:
+    raise ValueError("unknown scheme '%s'" % parsed.scheme)
+
+
+def get_transport_and_path(location, **kwargs):
+    """Obtain a git client from a URL.
+
+    :param location: URL or path
+    :param thin_packs: Whether or not thin packs should be retrieved
+    :param report_activity: Optional callback for reporting transport
+        activity.
+    :return: Tuple with client instance and relative path.
+    """
+    # First, try to parse it as a URL
+    try:
+        return get_transport_and_path_from_url(location, **kwargs)
+    except ValueError:
+        pass
+
+    if ':' in location and not '@' in location:
         # SSH with no user@, zero or one leading slash.
-        return SSHGitClient(parsed.scheme, **kwargs), parsed.path
-    elif parsed.scheme:
-        raise ValueError('Unknown git protocol scheme: %s' % parsed.scheme)
-    elif '@' in parsed.path and ':' in parsed.path:
+        (hostname, path) = location.split(':')
+        return SSHGitClient(hostname, **kwargs), path
+    elif '@' in location and ':' in location:
         # SSH with user@host:foo.
-        user_host, path = parsed.path.split(':')
+        user_host, path = location.split(':')
         user, host = user_host.rsplit('@')
         return SSHGitClient(host, username=user, **kwargs), path
 
     # Otherwise, assume it's a local path.
-    return SubprocessGitClient(**kwargs), uri
+    return SubprocessGitClient(**kwargs), location
index ce61d973a396f455b66ce61d1f25c8f51eacc38e..191135b7b2d68dbd3c310344d6d1321a4d0c5469 100644 (file)
@@ -31,6 +31,7 @@ from dulwich.client import (
     SendPackError,
     UpdateRefsError,
     get_transport_and_path,
+    get_transport_and_path_from_url,
     )
 from dulwich.tests import (
     TestCase,
@@ -202,8 +203,8 @@ class GitClientTests(TestCase):
     def test_get_transport_and_path_error(self):
         # Need to use a known urlparse.uses_netloc URL scheme to get the
         # expected parsing of the URL on Python versions less than 2.6.5
-        self.assertRaises(ValueError, get_transport_and_path,
-        'prospero://bar/baz')
+        client, path = get_transport_and_path('prospero://bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
 
     def test_get_transport_and_path_http(self):
         url = 'https://github.com/jelmer/dulwich'
@@ -378,6 +379,84 @@ class GitClientTests(TestCase):
         self.assertEqual(self.rout.getvalue(), '0000')
 
 
+class TestGetTransportAndPathFromUrl(TestCase):
+
+    def test_tcp(self):
+        c, path = get_transport_and_path_from_url('git://foo.com/bar/baz')
+        self.assertTrue(isinstance(c, TCPGitClient))
+        self.assertEqual('foo.com', c._host)
+        self.assertEqual(TCP_GIT_PORT, c._port)
+        self.assertEqual('/bar/baz', path)
+
+    def test_tcp_port(self):
+        c, path = get_transport_and_path_from_url('git://foo.com:1234/bar/baz')
+        self.assertTrue(isinstance(c, TCPGitClient))
+        self.assertEqual('foo.com', c._host)
+        self.assertEqual(1234, c._port)
+        self.assertEqual('/bar/baz', path)
+
+    def test_ssh_explicit(self):
+        c, path = get_transport_and_path_from_url('git+ssh://foo.com/bar/baz')
+        self.assertTrue(isinstance(c, SSHGitClient))
+        self.assertEqual('foo.com', c.host)
+        self.assertEqual(None, c.port)
+        self.assertEqual(None, c.username)
+        self.assertEqual('bar/baz', path)
+
+    def test_ssh_port_explicit(self):
+        c, path = get_transport_and_path_from_url(
+            'git+ssh://foo.com:1234/bar/baz')
+        self.assertTrue(isinstance(c, SSHGitClient))
+        self.assertEqual('foo.com', c.host)
+        self.assertEqual(1234, c.port)
+        self.assertEqual('bar/baz', path)
+
+    def test_ssh_abspath_explicit(self):
+        c, path = get_transport_and_path_from_url('git+ssh://foo.com//bar/baz')
+        self.assertTrue(isinstance(c, SSHGitClient))
+        self.assertEqual('foo.com', c.host)
+        self.assertEqual(None, c.port)
+        self.assertEqual(None, c.username)
+        self.assertEqual('/bar/baz', path)
+
+    def test_ssh_port_abspath_explicit(self):
+        c, path = get_transport_and_path_from_url(
+            'git+ssh://foo.com:1234//bar/baz')
+        self.assertTrue(isinstance(c, SSHGitClient))
+        self.assertEqual('foo.com', c.host)
+        self.assertEqual(1234, c.port)
+        self.assertEqual('/bar/baz', path)
+
+    def test_ssh_host_relpath(self):
+        self.assertRaises(ValueError, get_transport_and_path_from_url,
+            'foo.com:bar/baz')
+
+    def test_ssh_user_host_relpath(self):
+        self.assertRaises(ValueError, get_transport_and_path_from_url,
+            'user@foo.com:bar/baz')
+
+    def test_local_path(self):
+        self.assertRaises(ValueError, get_transport_and_path_from_url,
+            'foo.bar/baz')
+
+    def test_error(self):
+        # Need to use a known urlparse.uses_netloc URL scheme to get the
+        # expected parsing of the URL on Python versions less than 2.6.5
+        self.assertRaises(ValueError, get_transport_and_path_from_url,
+            'prospero://bar/baz')
+
+    def test_http(self):
+        url = 'https://github.com/jelmer/dulwich'
+        c, path = get_transport_and_path_from_url(url)
+        self.assertTrue(isinstance(c, HttpGitClient))
+        self.assertEqual('/jelmer/dulwich', path)
+
+    def test_file(self):
+        c, path = get_transport_and_path_from_url('file:///home/jelmer/foo')
+        self.assertTrue(isinstance(c, SubprocessGitClient))
+        self.assertEqual('/home/jelmer/foo', path)
+
+
 class TestSSHVendor(object):
 
     def __init__(self):