(url: string | null | undefined)
| 91 | * (empty / null) → "" |
| 92 | */ |
| 93 | export function canonicalizeRemote(url: string | null | undefined): string { |
| 94 | if (!url) return ""; |
| 95 | let s = url.trim(); |
| 96 | if (!s) return ""; |
| 97 | // strip surrounding quotes that some configs add |
| 98 | s = s.replace(/^['"]|['"]$/g, ""); |
| 99 | // git@host:path/repo → host/path/repo |
| 100 | const scpMatch = s.match(/^[^@\s]+@([^:]+):(.+)$/); |
| 101 | if (scpMatch) { |
| 102 | s = `${scpMatch[1]}/${scpMatch[2]}`; |
| 103 | } else { |
| 104 | // strip scheme (https://, ssh://, git://, http://) |
| 105 | s = s.replace(/^[a-z][a-z0-9+.-]*:\/\//i, ""); |
| 106 | // strip user@ prefix on URL-style remotes |
| 107 | s = s.replace(/^[^@\/]+@/, ""); |
| 108 | } |
| 109 | // strip trailing .git |
| 110 | s = s.replace(/\.git$/i, ""); |
| 111 | // strip trailing slash |
| 112 | s = s.replace(/\/+$/, ""); |
| 113 | // collapse multiple slashes (after path normalization) |
| 114 | s = s.replace(/\/{2,}/g, "/"); |
| 115 | return s.toLowerCase(); |
| 116 | } |
| 117 | |
| 118 | // ── Public: secretScanFile (gitleaks wrapper) ───────────────────────────── |
| 119 |
no outgoing calls
no test coverage detected