Files
orca/src/shared/wsl-paths.test.ts
T
JinjingandOrca 6ee81dcfb1 Fix Codex WSL project trust conflating case-distinct Linux paths (#8333)
* Fix Codex WSL project trust conflating case-distinct Linux paths

normalizeCodexProjectPathForLookup lowercased the entire Windows/UNC
path, including the case-sensitive Linux portion under \\wsl$\<distro>.
Two distinct WSL project dirs (.../Repo vs .../repo) collapsed onto one
trust key, and the mirror dedupe (codex-config-mirror) inherited it.

Preserve case for the Linux path after the case-insensitive
\\wsl$\<distro> / \\wsl.localhost\<distro> share prefix; true Windows
drive letters and normal UNC shares still case-fold as before.

Co-authored-by: Orca <help@stably.ai>

* Apply the same WSL case-fold fix to hook-trust key lookup

normalizeHookTrustKeyForLookup had the identical latent bug: on a win32
host it lowercased the whole Windows-shaped path, folding the
case-sensitive Linux tail of a \\wsl$\<distro> UNC hook path — contrary
to its own comment that WSL sources stay case-sensitive.

Extract foldWindowsCaseInsensitivePath (shared with the project-path
normalizer): fold only the case-insensitive drive/\\wsl$ share prefix,
preserve the Linux tail. Existing suffix (event:group:handler) is already
lowercase, so behavior is unchanged there.

Co-authored-by: Orca <help@stably.ai>

* Fix Codex WSL trust revocation and hook-key case folding

- Case-drifted or share-spelling-varied WSL revocations were being
  ignored on merge, letting stale "trusted" entries survive; fold
  revocation lookups fully so matching errs toward revoked.
- Hook-trust key folding was gated on process.platform === 'win32',
  so WSL/SSH-remote hook sources weren't folded when Orca itself ran
  on macOS/Linux; fold by path shape instead, via the new shared
  foldWslUncPathCaseInsensitiveParts helper (also covers /mnt drvfs
  automounts and wsl$/wsl.localhost share aliasing).

* Fix Codex WSL trust key case-folding regressions

- Don't fold case-variant `/MNT` dirs as if they were the drvfs
  automount; only literal lowercase `/mnt/<drive>` folds.
- Preserve an exact-cased trusted project entry in ~/.codex during
  runtime merge instead of letting a loosely-matched, case-drifted
  revocation clobber a user's re-granted trust on every mirror pass.
- Minor cleanup: inline foldWindowsCaseInsensitivePath and hoist the
  repeated normalizeHookTrustKeyForLookup call in findTrustBlockRanges.

* Refactor case-fold WSL trust test to assert real serializer output

Extract path variables and assert against escapeTomlString(incomingPath) instead of a hardcoded escaped string literal, so the fixture can't silently drift from the actual TOML header serialization.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-12 00:36:51 -07:00

53 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { foldWslUncPathCaseInsensitiveParts, isWslUncPath, parseWslUncPath } from './wsl-paths'
describe('wsl path helpers', () => {
it('parses modern and legacy WSL UNC paths without platform checks', () => {
expect(parseWslUncPath('\\\\wsl.localhost\\Ubuntu\\home\\jin\\repo')).toEqual({
distro: 'Ubuntu',
linuxPath: '/home/jin/repo'
})
expect(parseWslUncPath('\\\\wsl$\\Debian\\home\\jin')).toEqual({
distro: 'Debian',
linuxPath: '/home/jin'
})
})
it('rejects ordinary Windows and POSIX paths', () => {
expect(isWslUncPath('C:\\Users\\jin\\repo')).toBe(false)
expect(isWslUncPath('/home/jin/repo')).toBe(false)
})
})
describe('foldWslUncPathCaseInsensitiveParts', () => {
it('folds share spelling, distro casing, and separators but not the Linux tail', () => {
expect(foldWslUncPathCaseInsensitiveParts('\\\\WSL$\\Ubuntu\\home\\jin\\Repo')).toBe(
'//wsl.localhost/ubuntu/home/jin/Repo'
)
expect(foldWslUncPathCaseInsensitiveParts('//wsl.localhost/UBUNTU/home/jin/Repo')).toBe(
'//wsl.localhost/ubuntu/home/jin/Repo'
)
})
it('folds drvfs automount tails but not other /mnt entries', () => {
expect(foldWslUncPathCaseInsensitiveParts('\\\\wsl$\\Ubuntu\\mnt\\C\\Users\\Jin')).toBe(
'//wsl.localhost/ubuntu/mnt/c/users/jin'
)
expect(foldWslUncPathCaseInsensitiveParts('\\\\wsl$\\Ubuntu\\mnt\\wsl\\Data')).toBe(
'//wsl.localhost/ubuntu/mnt/wsl/Data'
)
})
it('does not treat a case-variant /MNT dir as the drvfs automount', () => {
expect(foldWslUncPathCaseInsensitiveParts('\\\\wsl$\\Ubuntu\\MNT\\c\\Repo')).toBe(
'//wsl.localhost/ubuntu/MNT/c/Repo'
)
})
it('returns null for non-WSL paths', () => {
expect(foldWslUncPathCaseInsensitiveParts('C:\\Users\\jin')).toBeNull()
expect(foldWslUncPathCaseInsensitiveParts('//server/share/x')).toBeNull()
expect(foldWslUncPathCaseInsensitiveParts('/home/jin')).toBeNull()
})
})