Fix typo: URI -> URL.
[jelmer/dulwich.git] / dulwich / client.py
index 0ee6145422d4dffd2d430cdc463860afc9916ecf..8e572e1d5345d0a3c8f3deb58237163dfa4ebdce 100644 (file)
@@ -1,5 +1,5 @@
 # client.py -- Implementation of the server side git protocols
-# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2008-2013 Jelmer Vernooij <jelmer@samba.org>
 # Copyright (C) 2008 John Carr
 #
 # This program is free software; you can redistribute it and/or
@@ -62,6 +62,9 @@ from dulwich.protocol import (
 from dulwich.pack import (
     write_pack_objects,
     )
+from dulwich.refs import (
+    read_info_refs,
+    )
 
 
 # Python 2.6.6 included these in urlparse.uses_netloc upstream. Do
@@ -154,14 +157,6 @@ def read_pkt_refs(proto):
     return refs, set(server_capabilities)
 
 
-def read_info_refs(f):
-    ret = {}
-    for l in f.readlines():
-        (sha, name) = l.rstrip("\r\n").split("\t", 1)
-        ret[name] = sha
-    return ret
-
-
 # TODO(durin42): this doesn't correctly degrade if the server doesn't
 # support some capabilities. This should work properly with servers
 # that don't support multi_ack.
@@ -650,6 +645,9 @@ class SubprocessGitClient(TraditionalGitClient):
                         report_activity=self._report_activity), p.can_read
 
 
+# What Git client to use for local access
+default_local_git_client_cls = SubprocessGitClient
+
 class SSHVendor(object):
     """A client side SSH implementation."""
 
@@ -967,16 +965,16 @@ 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 url: URL to open
     :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.
     """
-    parsed = urlparse.urlparse(uri)
+    parsed = urlparse.urlparse(url)
     if parsed.scheme == 'git':
         return (TCPGitClient(parsed.hostname, port=parsed.port, **kwargs),
                 parsed.path)
@@ -988,17 +986,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 default_local_git_client_cls(**kwargs), parsed.path
+
+    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 parsed.scheme and not parsed.netloc:
+    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 default_local_git_client_cls(**kwargs), location