Merge branch 'feature/21' into develop
This commit is contained in:
commit
afdb9b2906
3 changed files with 78 additions and 32 deletions
2
TODO
2
TODO
|
|
@ -284,7 +284,7 @@ Content-Type: application/issue
|
|||
ID: 21
|
||||
Type: feature
|
||||
Title: relax host restriction in vcs.git parse_base_url and parse_repo_name
|
||||
Status: in-progress
|
||||
Status: done
|
||||
Priority: high
|
||||
Created: 2026-06-06
|
||||
Relationships:
|
||||
|
|
|
|||
|
|
@ -26,54 +26,40 @@ class GitError(Exception):
|
|||
|
||||
|
||||
def parse_base_url(base_url: str) -> str:
|
||||
"""Extract workspace from an SCP-style Bitbucket base URL.
|
||||
"""Extract the workspace from an SCP-style base URL.
|
||||
|
||||
The host part must be exactly ``bitbucket.org`` — bootstrapping
|
||||
requires the Bitbucket API, so other hosts are rejected.
|
||||
Accepts any host (Bitbucket, Forgejo, GitHub, ...) as long as
|
||||
the URL is SCP-style::
|
||||
|
||||
>>> _parse_base_url("git@bitbucket.org:byteb4rb1e")
|
||||
'byteb4rb1e'
|
||||
git@bitbucket.org:byteb4rb1e/foo.git → byteb4rb1e
|
||||
git@git.code.tiararodney.com:h5p-mirror/foo.git → h5p-mirror
|
||||
"""
|
||||
# SCP-style: git@bitbucket.org:workspace
|
||||
# SCP-style: git@host:workspace/repo
|
||||
if ":" not in base_url or "//" in base_url:
|
||||
raise ValueError(
|
||||
f"Expected SCP-style URL (git@bitbucket.org:workspace), "
|
||||
f"Expected SCP-style URL (git@host:workspace), "
|
||||
f"got: {base_url}"
|
||||
)
|
||||
host_part, workspace = base_url.split(":", 1)
|
||||
# host_part is e.g. "git@bitbucket.org"
|
||||
host = host_part.split("@", 1)[-1]
|
||||
if host != "bitbucket.org":
|
||||
raise ValueError(
|
||||
f"Mirror base URL must target bitbucket.org, "
|
||||
f"got host: {host}"
|
||||
)
|
||||
return Path(workspace).parent
|
||||
_, workspace = base_url.split(":", 1)
|
||||
return str(Path(workspace).parent)
|
||||
|
||||
|
||||
def parse_repo_name(base_url: str) -> str:
|
||||
"""Extract workspace from an SCP-style Bitbucket base URL.
|
||||
"""Extract the repository name from an SCP-style base URL.
|
||||
|
||||
The host part must be exactly ``bitbucket.org`` — bootstrapping
|
||||
requires the Bitbucket API, so other hosts are rejected.
|
||||
Accepts any host (Bitbucket, Forgejo, GitHub, ...) as long as
|
||||
the URL is SCP-style::
|
||||
|
||||
>>> _parse_base_url("git@bitbucket.org:byteb4rb1e")
|
||||
'byteb4rb1e'
|
||||
git@bitbucket.org:byteb4rb1e/foo.git → foo
|
||||
git@git.code.tiararodney.com:h5p-mirror/foo.git → foo
|
||||
"""
|
||||
# SCP-style: git@bitbucket.org:workspace
|
||||
# SCP-style: git@host:workspace/repo
|
||||
if ":" not in base_url or "//" in base_url:
|
||||
raise ValueError(
|
||||
f"Expected SCP-style URL (git@bitbucket.org:workspace), "
|
||||
f"Expected SCP-style URL (git@host:workspace), "
|
||||
f"got: {base_url}"
|
||||
)
|
||||
host_part, workspace = base_url.split(":", 1)
|
||||
# host_part is e.g. "git@bitbucket.org"
|
||||
host = host_part.split("@", 1)[-1]
|
||||
if host != "bitbucket.org":
|
||||
raise ValueError(
|
||||
f"Mirror base URL must target bitbucket.org, "
|
||||
f"got host: {host}"
|
||||
)
|
||||
_, workspace = base_url.split(":", 1)
|
||||
return Path(workspace).name.split('.')[0]
|
||||
|
||||
|
||||
|
|
|
|||
60
tests/unit/byteb4rb1e/utils/vcs/test_git.py
Normal file
60
tests/unit/byteb4rb1e/utils/vcs/test_git.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""Tests for the git subprocess wrapper's URL parsing helpers."""
|
||||
|
||||
import pytest
|
||||
|
||||
from byteb4rb1e.utils.vcs.git import parse_base_url, parse_repo_name
|
||||
|
||||
|
||||
class TestParseBaseUrl:
|
||||
|
||||
def test_bitbucket(self) -> None:
|
||||
result = parse_base_url("git@bitbucket.org:byteb4rb1e/foo.git")
|
||||
assert result == "byteb4rb1e"
|
||||
|
||||
def test_forgejo_host(self) -> None:
|
||||
result = parse_base_url(
|
||||
"git@git.code.tiararodney.com:h5p-mirror/foo.git"
|
||||
)
|
||||
assert result == "h5p-mirror"
|
||||
|
||||
def test_github_host(self) -> None:
|
||||
result = parse_base_url("git@github.com:h5p/h5p-multi-choice.git")
|
||||
assert result == "h5p"
|
||||
|
||||
def test_returns_str(self) -> None:
|
||||
result = parse_base_url("git@bitbucket.org:byteb4rb1e/foo.git")
|
||||
assert isinstance(result, str)
|
||||
|
||||
def test_rejects_https_url(self) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
parse_base_url("https://bitbucket.org/byteb4rb1e/foo.git")
|
||||
|
||||
def test_rejects_url_without_colon(self) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
parse_base_url("bitbucket.org/byteb4rb1e/foo.git")
|
||||
|
||||
|
||||
class TestParseRepoName:
|
||||
|
||||
def test_bitbucket(self) -> None:
|
||||
assert parse_repo_name(
|
||||
"git@bitbucket.org:byteb4rb1e/foo.git"
|
||||
) == "foo"
|
||||
|
||||
def test_forgejo_host(self) -> None:
|
||||
assert parse_repo_name(
|
||||
"git@git.code.tiararodney.com:h5p-mirror/foo.git"
|
||||
) == "foo"
|
||||
|
||||
def test_without_git_suffix(self) -> None:
|
||||
assert parse_repo_name(
|
||||
"git@git.code.tiararodney.com:h5p-mirror/foo"
|
||||
) == "foo"
|
||||
|
||||
def test_rejects_https_url(self) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
parse_repo_name("https://git.code.tiararodney.com/x/foo.git")
|
||||
|
||||
def test_rejects_url_without_colon(self) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
parse_repo_name("git.code.tiararodney.com/x/foo.git")
|
||||
Loading…
Add table
Add a link
Reference in a new issue