Problem
When a user specifies an SCP-shorthand SSH dependency with a port number — e.g. from a Bitbucket Datacenter server — the parser silently treats the port as part of the repo path instead of raising an actionable error:
dependencies:
apm:
- git@bitbucket.example.com:7999/project/repo.git
Parsed result:
| Field |
Value |
host |
bitbucket.example.com |
port |
None |
repo_url |
7999/project/repo |
The user intended port 7999 with repo project/repo, but APM accepted 7999/project/repo as a valid three-segment repo path. The subsequent git clone fails with a 404 from the remote — not an APM error message pointing at the SCP/port mismatch.
To Reproduce
# apm.yml
dependencies:
apm:
- git@bitbucket.example.com:7999/project/repo.git
- Run
apm install --verbose
- Clone fails with
repository not found from git
- No APM-level warning about the SCP/port ambiguity
Expected behavior
APM should detect the leading numeric segment and raise an actionable error:
Error: 'git@bitbucket.example.com:7999/project/repo.git' — '7999' looks like
a port number, but SCP shorthand (git@host:path) cannot carry a port.
Use: ssh://git@bitbucket.example.com:7999/project/repo.git
Root cause
_parse_ssh_url (reference.py:648) uses the regex ^git@([^:]+):(.+)$ which captures everything after : as the repo path. Phase 3 validation ([a-zA-Z0-9._-]+ per segment) accepts purely numeric segments like 7999. No heuristic exists to detect the ambiguity.
Suggested fix
After extracting repo_url in _parse_ssh_url (line 671), check if the first path segment is a valid port number:
segments = repo_url.split("/")
first = segments[0]
if first.isdigit():
port_candidate = int(first)
if 1 <= port_candidate <= 65535:
remaining = "/".join(segments[1:])
raise ValueError(
f"It looks like '{first}' in 'git@{host}:{repo_url}' is a port number, "
f"but SCP shorthand cannot carry a port. "
f"Use: ssh://git@{host}:{first}/{remaining}.git"
)
False positive analysis: purely numeric org/owner names are not allowed on GitHub and extremely rare on other hosts (GitLab namespaces require at least one letter). If a user does have one, the error message directs them to the ssh:// form which unambiguously separates port from path.
Tests to add
git@host:7999/project/repo.git → raises ValueError with suggestion
git@host:22/project/repo.git → same (default port, still a port intention)
git@host:acme/repo.git → no error (non-numeric first segment, existing behavior)
git@host:v2/repo.git → no error (starts with letter)
Context
Follow-up from PR #665 (port preservation). Identified in the review panel's devx-ux-expert finding.
Refs: #661, #665
Problem
When a user specifies an SCP-shorthand SSH dependency with a port number — e.g. from a Bitbucket Datacenter server — the parser silently treats the port as part of the repo path instead of raising an actionable error:
Parsed result:
hostbitbucket.example.comportNonerepo_url7999/project/repoThe user intended port 7999 with repo
project/repo, but APM accepted7999/project/repoas a valid three-segment repo path. The subsequentgit clonefails with a 404 from the remote — not an APM error message pointing at the SCP/port mismatch.To Reproduce
apm install --verboserepository not foundfrom gitExpected behavior
APM should detect the leading numeric segment and raise an actionable error:
Root cause
_parse_ssh_url(reference.py:648) uses the regex^git@([^:]+):(.+)$which captures everything after:as the repo path. Phase 3 validation ([a-zA-Z0-9._-]+per segment) accepts purely numeric segments like7999. No heuristic exists to detect the ambiguity.Suggested fix
After extracting
repo_urlin_parse_ssh_url(line 671), check if the first path segment is a valid port number:False positive analysis: purely numeric org/owner names are not allowed on GitHub and extremely rare on other hosts (GitLab namespaces require at least one letter). If a user does have one, the error message directs them to the
ssh://form which unambiguously separates port from path.Tests to add
git@host:7999/project/repo.git→ raisesValueErrorwith suggestiongit@host:22/project/repo.git→ same (default port, still a port intention)git@host:acme/repo.git→ no error (non-numeric first segment, existing behavior)git@host:v2/repo.git→ no error (starts with letter)Context
Follow-up from PR #665 (port preservation). Identified in the review panel's devx-ux-expert finding.
Refs: #661, #665