commit - aa67e876cf7e27d67a6f9baf186bf2b2a70cad4e
commit + a3704312cc36f6bf5e9cbf89b37f62973f1d9c06
blob - 0afceda1a36907e148b0bb4841a8c8d6bc6b4fa8
blob + da39847fd9a87b55175e2b7890d58abed6abe2b3
--- dulwich/client.py
+++ dulwich/client.py
urlunsplit,
urlunparse,
)
+from urllib.request import url2pathname
+
import dulwich
from dulwich.config import get_xdg_config_home_path
from dulwich.errors import (
HttpGitClient = Urllib3HttpGitClient
+def _win32_url_to_path(parsed) -> str:
+ """
+ Convert a file: URL to a path.
+
+ https://datatracker.ietf.org/doc/html/rfc8089
+ """
+ assert sys.platform == "win32" or os.name == "nt"
+ assert parsed.scheme == "file"
+
+ _, netloc, path, _, _, _ = parsed
+
+ if netloc == "localhost" or not netloc:
+ netloc = ""
+ elif (
+ netloc
+ and len(netloc) >= 2
+ and netloc[0].isalpha()
+ and netloc[1:2] in (":", ":/")
+ ):
+ # file://C:/foo.bar/baz or file://C://foo.bar//baz
+ netloc = netloc[:2]
+ else:
+ raise NotImplementedError("Non-local file URLs are not supported")
+
+ return url2pathname(netloc + path)
+
+
def get_transport_and_path_from_url(url, config=None, **kwargs):
"""Obtain a git client from a URL.
parsed.path,
)
elif parsed.scheme == "file":
+ if sys.platform == "win32" or os.name == "nt":
+ return default_local_git_client_cls(**kwargs), _win32_url_to_path(parsed)
return (
default_local_git_client_cls.from_parsedurl(parsed, **kwargs),
parsed.path,
blob - 9937d034e4255379f79e52cb269ba287f22e5c30
blob + 12f62d15e3ef2f408dc60a906e06e474720ff45a
--- dulwich/tests/test_client.py
+++ dulwich/tests/test_client.py
quote as urlquote,
urlparse,
)
+
+from unittest.mock import patch
import dulwich
from dulwich import (
self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
+ @patch("os.name", "posix")
+ @patch("sys.platform", "linux")
def test_file(self):
c, path = get_transport_and_path_from_url("file:///home/jelmer/foo")
self.assertIsInstance(c, LocalGitClient)
self.assertEqual("/home/jelmer/foo", path)
+
+ @patch("os.name", "nt")
+ @patch("sys.platform", "win32")
+ def test_file_win(self):
+ # `_win32_url_to_path` uses urllib.request.url2pathname, which is set to
+ # `ntutl2path.url2pathname` when `os.name==nt`
+ from nturl2path import url2pathname
+
+ with patch("dulwich.client.url2pathname", url2pathname):
+ expected = "C:\\foo.bar\\baz"
+ for file_url in [
+ "file:C:/foo.bar/baz",
+ "file:/C:/foo.bar/baz",
+ "file://C:/foo.bar/baz",
+ "file://C://foo.bar//baz",
+ "file:///C:/foo.bar/baz",
+ ]:
+ c, path = get_transport_and_path(file_url)
+ self.assertIsInstance(c, LocalGitClient)
+ self.assertEqual(path, expected)
+ for remote_url in [
+ "file://host.example.com/C:/foo.bar/baz"
+ "file://host.example.com/C:/foo.bar/baz"
+ "file:////host.example/foo.bar/baz",
+ ]:
+ with self.assertRaises(NotImplementedError):
+ c, path = get_transport_and_path(remote_url)
+
class TestSSHVendor(object):
def __init__(self):
self.host = None