Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1f39d80

Browse files
committed
refactor(url): reversible SSH-style URL patch
why: - Previously, enabling SSH-style URL detection mutated libvcs’s DEFAULT_RULES on import and lost the rule’s original metadata. - Users couldn’t cleanly disable the patch or restore upstream defaults if libvcs changed. - Implicit module-import side-effects are harder to reason about. what: - Introduce private `_orig_rule_meta` to snapshot rule’s original metadata. - Store original metadata on first enable and apply `(True, 100)`. - Restore saved metadata (or safe defaults) on disable, clearing snapshot. - Remove auto-patch on import; require explicit call. - Add `ssh_style_url_detection` context manager. - Call `enable_ssh_style_url_detection()` in `update_repo()` to maintain behavior. - Add pytest tests for enable/disable roundtrip and context manager.
1 parent f8375ed commit 1f39d80

File tree

3 files changed

+92
-10
lines changed

3 files changed

+92
-10
lines changed

‎src/vcspull/cli/sync.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from vcspull import exc
1414
from vcspull.config import filter_repos, find_config_files, load_configs
15+
from vcspull.url import enable_ssh_style_url_detection
1516

1617
if t.TYPE_CHECKING:
1718
import argparse
@@ -147,6 +148,8 @@ def update_repo(
147148
# repo_dict: Dict[str, Union[str, Dict[str, GitRemote], pathlib.Path]]
148149
) -> GitSync:
149150
"""Synchronize a single repository."""
151+
# Ensure SSH-style URLs are recognized as explicit Git URLs
152+
enable_ssh_style_url_detection()
150153
repo_dict = deepcopy(repo_dict)
151154
if "pip_url" not in repo_dict:
152155
repo_dict["pip_url"] = repo_dict.pop("url")

‎src/vcspull/url.py‎

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
from __future__ import annotations
44

5+
from typing import Any
6+
57
from libvcs.url.git import DEFAULT_RULES
68

9+
_orig_rule_meta: dict[str, tuple[bool, int]] = {}
10+
711

812
def enable_ssh_style_url_detection() -> None:
913
"""Enable detection of SSH-style URLs as explicit Git URLs.
@@ -23,12 +27,14 @@ def enable_ssh_style_url_detection() -> None:
2327
>>> GitURL.is_valid('user@hostname:path/to/repo.git', is_explicit=True)
2428
True
2529
"""
30+
# Patch the core-git-scp rule, storing its original state if not already stored
2631
for rule in DEFAULT_RULES:
2732
if rule.label == "core-git-scp":
28-
# Make the rule explicit so it can be detected with is_explicit=True
33+
if rule.label not in _orig_rule_meta:
34+
_orig_rule_meta[rule.label] = (rule.is_explicit, rule.weight)
2935
rule.is_explicit = True
30-
# Increase the weight to ensure it takes precedence
3136
rule.weight = 100
37+
break
3238

3339

3440
def disable_ssh_style_url_detection() -> None:
@@ -39,7 +45,8 @@ def disable_ssh_style_url_detection() -> None:
3945
4046
Examples
4147
--------
42-
>>> from vcspull.url import enable_ssh_style_url_detection, disable_ssh_style_url_detection
48+
>>> from vcspull.url import enable_ssh_style_url_detection
49+
>>> from vcspull.url import disable_ssh_style_url_detection
4350
>>> from libvcs.url.git import GitURL
4451
>>> # Enable the patch
4552
>>> enable_ssh_style_url_detection()
@@ -50,11 +57,18 @@ def disable_ssh_style_url_detection() -> None:
5057
>>> GitURL.is_valid('user@hostname:path/to/repo.git', is_explicit=True)
5158
False
5259
"""
60+
# Restore the core-git-scp rule to its original state, if known
5361
for rule in DEFAULT_RULES:
5462
if rule.label == "core-git-scp":
55-
# Revert to original state
56-
rule.is_explicit = False
57-
rule.weight = 0
63+
orig = _orig_rule_meta.get(rule.label)
64+
if orig:
65+
rule.is_explicit, rule.weight = orig
66+
_orig_rule_meta.pop(rule.label, None)
67+
else:
68+
# Fallback to safe defaults
69+
rule.is_explicit = False
70+
rule.weight = 0
71+
break
5872

5973

6074
def is_ssh_style_url_detection_enabled() -> bool:
@@ -70,5 +84,30 @@ def is_ssh_style_url_detection_enabled() -> bool:
7084
return False
7185

7286

73-
# Enable SSH-style URL detection by default
74-
enable_ssh_style_url_detection()
87+
"""
88+
Context manager and utility for SSH-style URL detection.
89+
"""
90+
91+
92+
class ssh_style_url_detection:
93+
"""Context manager to enable/disable SSH-style URL detection."""
94+
95+
def __init__(self, enabled: bool = True) -> None:
96+
self.enabled = enabled
97+
98+
def __enter__(self) -> None:
99+
"""Enable or disable SSH-style URL detection on context enter."""
100+
if self.enabled:
101+
enable_ssh_style_url_detection()
102+
else:
103+
disable_ssh_style_url_detection()
104+
105+
def __exit__(
106+
self,
107+
exc_type: type[BaseException] | None,
108+
exc_val: BaseException | None,
109+
exc_tb: Any,
110+
) -> None:
111+
"""Restore original SSH-style URL detection state on context exit."""
112+
# Always restore to disabled after context
113+
disable_ssh_style_url_detection()

‎tests/test_url.py‎

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
from __future__ import annotations
44

55
import pytest
6-
from libvcs.url.git import GitURL
6+
from libvcs.url.git import DEFAULT_RULES, GitURL
77

8-
from vcspull.url import disable_ssh_style_url_detection, enable_ssh_style_url_detection
8+
from vcspull.url import (
9+
disable_ssh_style_url_detection,
10+
enable_ssh_style_url_detection,
11+
ssh_style_url_detection,
12+
)
913

1014

1115
def test_ssh_style_url_detection_toggle() -> None:
@@ -99,3 +103,39 @@ def test_ssh_style_url_parsing(
99103
assert git_url.hostname == expected_hostname
100104
assert git_url.path == expected_path
101105
assert git_url.suffix == ".git"
106+
107+
108+
def test_enable_disable_restores_original_state() -> None:
109+
"""Original rule metadata is preserved and restored after enable/disable."""
110+
# Ensure any prior patch is cleared
111+
disable_ssh_style_url_detection()
112+
# Find the core-git-scp rule and capture its original state
113+
rule = next(r for r in DEFAULT_RULES if r.label == "core-git-scp")
114+
orig_state = (rule.is_explicit, rule.weight)
115+
116+
# Disabling without prior enable should leave original state
117+
disable_ssh_style_url_detection()
118+
assert (rule.is_explicit, rule.weight) == orig_state
119+
120+
# Enable should patch
121+
enable_ssh_style_url_detection()
122+
assert rule.is_explicit is True
123+
assert rule.weight == 100
124+
125+
# Disable should restore to original
126+
disable_ssh_style_url_detection()
127+
assert (rule.is_explicit, rule.weight) == orig_state
128+
129+
130+
def test_context_manager_restores_original_state() -> None:
131+
"""Context manager enables then restores original rule state."""
132+
rule = next(r for r in DEFAULT_RULES if r.label == "core-git-scp")
133+
orig_state = (rule.is_explicit, rule.weight)
134+
135+
# Use context manager
136+
with ssh_style_url_detection():
137+
assert rule.is_explicit is True
138+
assert rule.weight == 100
139+
140+
# After context, state should be back to original
141+
assert (rule.is_explicit, rule.weight) == orig_state

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /