diff --git a/arbiter/backend.py b/arbiter/backend.py index fcf12c3..a49cc02 100644 --- a/arbiter/backend.py +++ b/arbiter/backend.py @@ -25,9 +25,19 @@ def _quote_ref_path(ref: str) -> str: - """ref 路径段编码('/'→'%' 之外的保留字符按 RFC 3986 编码)。""" + """ref 路径段编码('/'→'%' 之外的保留字符按 RFC 3986 编码)。 + + 前缀剥离(e2e .github#206 /release 实测,2026-08-21):GET /git/ref/、 + PATCH/DELETE /git/refs/ 这三类"按路径寻址 ref"的端点对自定义命名空间 + (refs/leases/…)要求相对形态——带完整 "refs/" 前缀一律 404/422 + (探针实测:带前缀 GET 404、DELETE 422 Reference does not exist; + 去前缀全部 200/204;%2F 编码两形态均接受)。createRef 的 POST /git/refs + 用 body 传完整 "refs/…" 名不受影响(claim 链路实证)。 + """ import urllib.parse + if ref.startswith("refs/"): + ref = ref[len("refs/"):] return urllib.parse.quote(ref, safe="") diff --git a/tests/test_github_backend_wire.py b/tests/test_github_backend_wire.py index 470c7d9..6f8cd79 100644 --- a/tests/test_github_backend_wire.py +++ b/tests/test_github_backend_wire.py @@ -64,3 +64,14 @@ def test_empty_tree_sha_is_the_git_canonical_constant(self): if __name__ == "__main__": unittest.main() + + +class TestQuoteRefPathWire(unittest.TestCase): + def test_prefix_stripped_for_path_addressed_endpoints(self): + """按路径寻址 ref 的端点(GET/PATCH/DELETE)要求相对形态——带 refs/ 前缀一律 404/422。""" + from arbiter.backend import _quote_ref_path + self.assertEqual( + _quote_ref_path("refs/leases/o__r__1"), + "leases%2Fo__r__1", + ) + self.assertEqual(_quote_ref_path("heads/main"), "heads%2Fmain") # 已相对形态原样