Commit 71b3d6e0 by Evan Rittenhouse Committed by GitHub

Correctly parse Git submodule URLs (#7017)

parent 472a17cd
...@@ -7,6 +7,7 @@ import re ...@@ -7,6 +7,7 @@ import re
from pathlib import Path from pathlib import Path
from subprocess import CalledProcessError from subprocess import CalledProcessError
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from urllib.parse import urljoin
from dulwich import porcelain from dulwich import porcelain
from dulwich.client import HTTPUnauthorized from dulwich.client import HTTPUnauthorized
...@@ -331,16 +332,24 @@ class Git: ...@@ -331,16 +332,24 @@ class Git:
repo_root = Path(repo.path) repo_root = Path(repo.path)
modules_config = repo_root.joinpath(".gitmodules") modules_config = repo_root.joinpath(".gitmodules")
# A relative URL by definition starts with ../ or ./
relative_submodule_regex = re.compile(r"^\.{1,2}/")
if modules_config.exists(): if modules_config.exists():
config = ConfigFile.from_path(str(modules_config)) config = ConfigFile.from_path(str(modules_config))
url: bytes url: bytes
path: bytes path: bytes
submodules = parse_submodules(config) submodules = parse_submodules(config)
for path, url, name in submodules: for path, url, name in submodules:
path_relative = Path(path.decode("utf-8")) path_relative = Path(path.decode("utf-8"))
path_absolute = repo_root.joinpath(path_relative) path_absolute = repo_root.joinpath(path_relative)
url_string = url.decode("utf-8")
if relative_submodule_regex.search(url_string):
url_string = urljoin(f"{Git.get_remote_url(repo)}/", url_string)
source_root = path_absolute.parent source_root = path_absolute.parent
source_root.mkdir(parents=True, exist_ok=True) source_root.mkdir(parents=True, exist_ok=True)
...@@ -357,7 +366,7 @@ class Git: ...@@ -357,7 +366,7 @@ class Git:
continue continue
cls.clone( cls.clone(
url=url.decode("utf-8"), url=url_string,
source_root=source_root, source_root=source_root,
name=path_relative.name, name=path_relative.name,
revision=revision, revision=revision,
......
...@@ -240,6 +240,30 @@ def test_git_clone_clones_submodules(source_url: str) -> None: ...@@ -240,6 +240,30 @@ def test_git_clone_clones_submodules(source_url: str) -> None:
assert len(list(submodule_package_directory.glob("*"))) > 1 assert len(list(submodule_package_directory.glob("*"))) > 1
def test_git_clone_clones_submodules_with_relative_urls(source_url: str) -> None:
with Git.clone(url=source_url, branch="relative_submodule") as repo:
submodule_package_directory = (
Path(repo.path) / "submodules" / "relative-url-submodule"
)
assert submodule_package_directory.exists()
assert submodule_package_directory.joinpath("README.md").exists()
assert len(list(submodule_package_directory.glob("*"))) > 1
def test_git_clone_clones_submodules_with_relative_urls_and_explicit_base(
source_url: str,
) -> None:
with Git.clone(url=source_url, branch="relative_submodule") as repo:
submodule_package_directory = (
Path(repo.path) / "submodules" / "relative-url-submodule-with-base"
)
assert submodule_package_directory.exists()
assert submodule_package_directory.joinpath("README.md").exists()
assert len(list(submodule_package_directory.glob("*"))) > 1
def test_system_git_fallback_on_http_401( def test_system_git_fallback_on_http_401(
mocker: MockerFixture, mocker: MockerFixture,
source_url: str, source_url: str,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment