From e639592852ebd179948c97f77c4838cf0fafb3d7 Mon Sep 17 00:00:00 2001 From: bensynapse <118375461+bensynapse@users.noreply.github.com> Date: Sat, 10 Oct 2026 12:39:52 +0300 Subject: [PATCH] Fix HTTP formatting for generic Git hosts --- changes/97.bugfix | 1 + giturlparse/platforms/base.py | 8 +++--- giturlparse/tests/test_rewrite.py | 42 +++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 changes/97.bugfix diff --git a/changes/97.bugfix b/changes/97.bugfix new file mode 100644 index 0000000..659b226 --- /dev/null +++ b/changes/97.bugfix @@ -0,0 +1 @@ +Fix HTTP normalization and protocol rewrites for generic Git hosts. diff --git a/giturlparse/platforms/base.py b/giturlparse/platforms/base.py index 8ca9bad..4e717ec 100644 --- a/giturlparse/platforms/base.py +++ b/giturlparse/platforms/base.py @@ -1,15 +1,17 @@ import itertools import re +from typing import ClassVar class BasePlatform: - FORMATS = { + FORMATS: ClassVar[dict] = { + "http": r"http://%(domain)s/%(repo)s%(dot_git)s", "https": r"https://%(domain)s/%(repo)s%(dot_git)s", "ssh": r"git@%(domain)s:%(repo)s%(dot_git)s%(path_raw)s", "git": r"git://%(domain)s/%(repo)s%(dot_git)s%(path_raw)s", } - PATTERNS = { + PATTERNS: ClassVar[dict] = { "ssh": r"(?P<_user>.+)@(?P[^/]+?):(?P.+)(?:(\.git)?(/)?)", "http": r"(?P(?Phttp))://(?P[^/]+?)/(?P.+)(?:(\.git)?(/)?)", "https": r"(?P(?Phttps))://(?P[^/]+?)/(?P.+)(?:(\.git)?(/)?)", @@ -19,7 +21,7 @@ class BasePlatform: # None means it matches all domains DOMAINS = None SKIP_DOMAINS = None - DEFAULTS = {} + DEFAULTS: ClassVar[dict] = {} def __init__(self): # Precompile PATTERNS diff --git a/giturlparse/tests/test_rewrite.py b/giturlparse/tests/test_rewrite.py index 3077983..cd7c7e7 100644 --- a/giturlparse/tests/test_rewrite.py +++ b/giturlparse/tests/test_rewrite.py @@ -88,7 +88,7 @@ class UrlRewriteTestCase(unittest.TestCase): def _test_rewrite(self, source, protocol, expected): parsed = parse(source) - self.assertTrue(parsed.valid, "Invalid Url: %s" % source) + self.assertTrue(parsed.valid, f"Invalid Url: {source}") return self.assertEqual(parse(source).format(protocol), expected) def test_rewrites(self): @@ -98,13 +98,51 @@ def test_rewrites(self): def _test_rewrite_components(self, field, data): parsed = parse(data["source"]) setattr(parsed, field, data["value"]) - self.assertTrue(parsed.valid, "Invalid Url: %s" % data["source"]) + self.assertTrue(parsed.valid, f"Invalid Url: {data['source']}") return self.assertEqual(parsed.url, data["expected"]) def test_rewrite_components(self): for field, data in REWRITE_COMPONENTS.items(): self._test_rewrite_components(field, data) + def test_generic_http_normalized(self): + for domain in ("git.example.org", "git.example.org:8080"): + for repo in ("project", "project.git", "Org/project.git"): + source = f"http://{domain}/{repo}" + expected = source if repo.endswith(".git") else source + ".git" + with self.subTest(source=source): + parsed = parse(source) + self.assertTrue(parsed.valid) + self.assertEqual(parsed.platform, "base") + self.assertEqual(parsed.normalized, expected) + + def test_generic_http_rewrites(self): + expected = { + "ssh": "git@git.example.org:project.git", + "http": "http://git.example.org/project.git", + "https": "https://git.example.org/project.git", + "git": "git://git.example.org/project.git", + } + for url in expected.values(): + for suffix in ("", ".git"): + source = url[:-4] + suffix + parsed = parse(source) + with self.subTest(source=source, operation="urls"): + self.assertTrue(parsed.valid) + self.assertEqual(parsed.platform, "base") + self.assertEqual(parsed.urls, expected) + with self.subTest(source=source, operation="url2http"): + self.assertEqual(parsed.url2http, expected["http"]) + self.assertEqual(parsed.format("http"), expected["http"]) + + def test_generic_http_name_update(self): + for source in ("http://git.example.org/project", "http://git.example.org/project.git"): + with self.subTest(source=source): + parsed = parse(source) + parsed.name = "new-project" + self.assertEqual(parsed.url, "http://git.example.org/new-project.git") + self.assertEqual(parsed.normalized, parsed.url) + # Test Suite suite = unittest.TestLoader().loadTestsFromTestCase(UrlRewriteTestCase)