export function normalizeRemote(url: string): string { const trimmed = url.trim(); if (trimmed.length === 0) return ''; if (!trimmed.includes('://')) { const scpLike = /^(?:[^@\s]+@)?([^:\s]+):(.+)$/.exec(trimmed); if (scpLike !== null) { return joinRemoteParts(scpLike[1], undefined, scpLike[2]); } return stripGitSuffix(trimmed); } try { const parsed = new URL(trimmed); if (parsed.hostname.length === 0) return stripGitSuffix(trimmed); return joinRemoteParts(parsed.hostname, parsed.port, parsed.pathname); } catch { return stripGitSuffix(trimmed); } } function joinRemoteParts( host: string | undefined, port: string | undefined, path: string | undefined, ): string { const normalizedHost = host?.trim() ?? ''; const normalizedPort = port?.trim() ?? ''; const normalizedPath = stripGitSuffix(path ?? ''); const parts = [normalizedHost]; if (normalizedPort.length > 0) parts.push(normalizedPort); if (normalizedPath.length > 0) parts.push(normalizedPath); return parts.join('/'); } function stripGitSuffix(value: string): string { let normalized = value.trim().replace(/^\/+/, '').replace(/\/+$/, ''); if (normalized.endsWith('.git')) { normalized = normalized.slice(0, -4); } return normalized; }