* Normalize PS arg text → canonical path for git-internal matching. * Order matters: structural strips first (colon-bound param, quotes, * backtick escapes, provider prefix, drive-relative prefix), then NTFS * per-component trailing-strip (spaces always; dots only if not `./..` * after space-str
(arg: string)
| 46 | * then case-fold. |
| 47 | */ |
| 48 | function normalizeGitPathArg(arg: string): string { |
| 49 | let s = arg |
| 50 | // Normalize parameter prefixes: dash chars (–, —, ―) and forward-slash |
| 51 | // (PS 5.1). /Path:hooks/pre-commit → extract colon-bound value. (bug #28) |
| 52 | if (s.length > 0 && (PS_TOKENIZER_DASH_CHARS.has(s[0]!) || s[0] === '/')) { |
| 53 | const c = s.indexOf(':', 1) |
| 54 | if (c > 0) s = s.slice(c + 1) |
| 55 | } |
| 56 | s = s.replace(/^['"]|['"]$/g, '') |
| 57 | s = s.replace(/`/g, '') |
| 58 | // PS provider-qualified path: FileSystem::hooks/pre-commit → hooks/pre-commit |
| 59 | // Also handles fully-qualified form: Microsoft.PowerShell.Core\FileSystem::path |
| 60 | s = s.replace(/^(?:[A-Za-z0-9_.]+\\){0,3}FileSystem::/i, '') |
| 61 | // Drive-relative C:foo (no separator after colon) is cwd-relative on that |
| 62 | // drive. C:\foo (WITH separator) is absolute and must NOT match — the |
| 63 | // negative lookahead preserves it. |
| 64 | s = s.replace(/^[A-Za-z]:(?![/\\])/, '') |
| 65 | s = s.replace(/\\/g, '/') |
| 66 | // Win32 CreateFileW per-component: iteratively strip trailing spaces, |
| 67 | // then trailing dots, stopping if the result is `.` or `..` (special). |
| 68 | // `.. ` → `..`, `.. .` → `..`, `...` → '' → `.`, `hooks .` → `hooks`. |
| 69 | // Originally-'' (leading slash split) stays '' (absolute-path marker). |
| 70 | s = s |
| 71 | .split('/') |
| 72 | .map(c => { |
| 73 | if (c === '') return c |
| 74 | let prev |
| 75 | do { |
| 76 | prev = c |
| 77 | c = c.replace(/ +$/, '') |
| 78 | if (c === '.' || c === '..') return c |
| 79 | c = c.replace(/\.+$/, '') |
| 80 | } while (c !== prev) |
| 81 | return c || '.' |
| 82 | }) |
| 83 | .join('/') |
| 84 | s = posix.normalize(s) |
| 85 | if (s.startsWith('./')) s = s.slice(2) |
| 86 | return s.toLowerCase() |
| 87 | } |
| 88 | |
| 89 | const GIT_INTERNAL_PREFIXES = ['head', 'objects', 'refs', 'hooks'] as const |
| 90 |
no test coverage detected