commit 26ee54a1eb647b20fe1356352e2f1b0afad6c0c2 from: Jelmer Vernooij date: Mon Nov 27 13:41:54 2023 UTC Support credentials in proxy URL Fixes #1227 commit - 26246d71f3ba583c13c99c25114cc2396da836b4 commit + 26ee54a1eb647b20fe1356352e2f1b0afad6c0c2 blob - a1823e516b89e8e81b5417bc7e22a6a079fd618f blob + 400f1ab9f6bdcb9ed3cba930d244d232a4349bad --- NEWS +++ NEWS @@ -8,6 +8,8 @@ * Add a dedicated exception class for unresolved deltas. (Jelmer Vernooij, #1221) + + * Support credentials in proxy URL. (Jelmer Vernooij, #1227) 0.21.6 2023-09-02 blob - ddbbb2608f5a854380539c12e6ba871564aa6cf8 blob + 151964c40e281ce222d086742632981003c2d6b6 --- dulwich/client.py +++ dulwich/client.py @@ -566,7 +566,7 @@ def _handle_upload_pack_tail( capabilities: Set[bytes], graph_walker, pack_data: Callable[[bytes], None], - progress=None, + progress: Optional[Callable[[bytes], None]] = None, rbufsize=_RBUFSIZE, ): """Handle the tail of a 'git-upload-pack' request. @@ -708,13 +708,13 @@ class GitClient: path, target_path, mkdir: bool = True, - bare=False, - origin="origin", + bare: bool = False, + origin: Optional[str] = "origin", checkout=None, branch=None, progress=None, depth=None, - ): + ) -> Repo: """Clone a repository.""" from .refs import _set_default_branch, _set_head, _set_origin_head @@ -739,22 +739,24 @@ class GitClient: encoded_path = self.get_url(path).encode("utf-8") assert target is not None - target_config = target.get_config() - target_config.set((b"remote", origin.encode("utf-8")), b"url", encoded_path) - target_config.set( - (b"remote", origin.encode("utf-8")), - b"fetch", - b"+refs/heads/*:refs/remotes/" + origin.encode("utf-8") + b"/*", - ) - target_config.write_to_path() + if origin is not None: + target_config = target.get_config() + target_config.set((b"remote", origin.encode("utf-8")), b"url", encoded_path) + target_config.set( + (b"remote", origin.encode("utf-8")), + b"fetch", + b"+refs/heads/*:refs/remotes/" + origin.encode("utf-8") + b"/*", + ) + target_config.write_to_path() ref_message = b"clone: from " + encoded_path result = self.fetch(path, target, progress=progress, depth=depth) - _import_remote_refs(target.refs, origin, result.refs, message=ref_message) + if origin is not None: + _import_remote_refs(target.refs, origin, result.refs, message=ref_message) origin_head = result.symrefs.get(b"HEAD") origin_sha = result.refs.get(b"HEAD") - if origin_sha and not origin_head: + if origin is None or (origin_sha and not origin_head): # set detached HEAD target.refs[b"HEAD"] = origin_sha head = origin_sha @@ -852,13 +854,13 @@ class GitClient: def fetch_pack( self, - path, + path: str, determine_wants, graph_walker, pack_data, *, - progress=None, - depth=None, + progress: Optional[Callable[[bytes], None]] = None, + depth: Optional[int] = None, ): """Retrieve a pack from a git smart server. @@ -1895,7 +1897,16 @@ def default_urllib3_manager( proxy_manager_cls = urllib3.ProxyManager if not isinstance(proxy_server, str): proxy_server = proxy_server.decode() - manager = proxy_manager_cls(proxy_server, headers=headers, **kwargs) + proxy_server_url = urlparse(proxy_server) + if proxy_server_url.username is not None: + proxy_headers = urllib3.make_headers( + proxy_basic_auth=f"{proxy_server_url.username}:{proxy_server_url.password or ''}" + ) + else: + proxy_headers = {} + manager = proxy_manager_cls( + proxy_server, proxy_headers=proxy_headers, headers=headers, **kwargs + ) else: if pool_manager_cls is None: pool_manager_cls = urllib3.PoolManager blob - 6b79de15fb60d32d08fc6e6cc321b7d6cf8c126d blob + 9af8b8822fa7f9babd765ae7e8fbca145f7c4641 --- dulwich/tests/test_client.py +++ dulwich/tests/test_client.py @@ -1429,6 +1429,17 @@ class DefaultUrllib3ManagerTest(TestCase): ) self.assertIsInstance(manager, CustomProxyManager) + def test_config_proxy_creds(self): + import urllib3 + + config = ConfigDict() + config.set(b"http", b"proxy", b"http://jelmer:example@localhost:3128/") + manager = default_urllib3_manager(config=config) + assert isinstance(manager, urllib3.ProxyManager) + self.assertEqual( + manager.proxy_headers, {"proxy-authorization": "Basic amVsbWVyOmV4YW1wbGU="} + ) + def test_config_no_verify_ssl(self): manager = default_urllib3_manager(config=None, cert_reqs="CERT_NONE") self.assertEqual(manager.connection_pool_kw["cert_reqs"], "CERT_NONE")