Skip to content

fix(versions): normalize folder paths before the foldersInUse check - #153

Merged
Zaldaryon merged 2 commits into
devfrom
fix/version-folder-path-normalize
Aug 18, 2026
Merged

fix(versions): normalize folder paths before the foldersInUse check#153
Zaldaryon merged 2 commits into
devfrom
fix/version-folder-path-normalize

Conversation

@Zaldaryon

Copy link
Copy Markdown
Collaborator

The folder-in-use guard used Array.includes(), which does raw string equality. A trailing slash, different casing on Windows, or mixed separators let the user register two versions pointing at the same physical directory.

What changed

  • New src/domain/paths.ts: exports normalizeFolderForComparison() (strips trailing separators, lowercases on Windows) and folderIsInUse() (normalizes both sides before comparing).
  • src/domain/versions/install.ts: replace raw .includes() with folderIsInUse().
  • src/domain/installations/create.ts: same replacement.
  • New tests/domain/paths.test.ts: 12 tests covering trailing slashes, case insensitivity on Windows paths, Linux case preservation, and edge cases.

What was tested

  • npm run typecheck passes
  • npm run lint:ci passes
  • npm run test:coverage passes (1122 tests, up from 1110)
  • New tests validate trailing slash, case, and backslash normalization

Fixes #147

The folder-in-use guard used Array.includes(), which does raw string
equality. A trailing slash, different casing on Windows, or mixed
separators let the user register two versions pointing at the same
physical directory.

Introduce normalizeFolderForComparison() in src/domain/paths.ts: strips
trailing separators and lowercases on Windows (detected by drive letter
or backslash presence). Replace the raw .includes() in both
installGameVersion and createInstallation with folderIsInUse(), which
normalizes both sides before comparing.

12 new unit tests cover the normalizer and the comparison helper.

Fixes #147
@Zaldaryon
Zaldaryon requested a review from Pixnop August 18, 2026 18:53

@Pixnop Pixnop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right direction and the right home for it, a pure domain module both call sites share. But I probed the implementation against the two cases the body itself names, and one of them is still open while a new one appeared.

Mixed separators are not handled: folderIsInUse('C:/Games/VS', ['C:\Games\VS']) returns false on this branch, probed directly. Stripping trailing separators and lowercasing does nothing about the separators in the middle, so the same physical directory registered once through the picker (backslashes) and once typed with forward slashes still slips the guard, which is the exact scenario issue #147 describes. Unifying separators when the path is Windows-like (replace both kinds with one) closes it, and two test rows pin it.

The looksLikeWindows heuristic misfires on Linux: a backslash is a legal filename character there, so '/home/a/dir\x' and '/home/a/DIR\x', two genuinely distinct folders, get lowercased into a false in-use refusal, also probed. The heuristic is not needed at the install call site: installGameVersion already receives platform in its input, so folderIsInUse can take platform as an argument and only fold case on win32. If createInstallation lacks the platform today, threading it through is a smaller wart than deciding the OS from string shape.

With the separator unification, the platform parameter, and tests for both probed cases, this is an approve.

…mparison

Replace the looksLikeWindows heuristic with an explicit platform parameter
(defaults to auto-detect from drive letter). Unify backslashes to forward
slashes before comparison, so C:/Games/VS and C:\Games\VS match correctly.
On posix, a backslash in a filename is normalized the same way (unified to /)
but case is preserved, preventing the false-positive where two genuinely
distinct Linux paths got lowercased into a collision.

Tests cover: mixed separators on Windows, explicit posix with backslash
filename chars, and the platform param threading through folderIsInUse.
@Zaldaryon

Copy link
Copy Markdown
Collaborator Author

Addressed in 5af7eed.

  1. Separator unification: all backslashes are replaced with forward slashes before comparison, so C:/Games/VS and C:\\Games\\VS match.
  2. Explicit platform param: folderIsInUse and normalizeFolderForComparison take an optional platform argument ("win32" | "posix"). installGameVersion passes its existing input.platform, createInstallation accepts an optional platform field. Auto-detection falls back to drive-letter presence when the param is omitted.
  3. No false-positive on Linux backslash filenames: on posix, backslashes are unified to / but case is preserved. Two distinct Linux paths (/home/a/dir\\x vs /home/a/DIR\\x) stay distinct. Test pins this.
  4. Test rows: mixed separators on win32, posix backslash filename, platform param threading.

@Pixnop Pixnop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Re-probed everything from the previous round on the new commit: the mixed-separator pair is now detected as the same folder, and with the explicit posix parameter two Linux folders differing only by case stay distinct, so both misfires are closed. The platform parameter threaded through install and create is the right shape, with the shape-detection heuristic surviving only as a fallback default. Sixteen tests pass including the new separator rows.

One residual quirk for the record, not blocking: the separator unification runs unconditionally, so on posix a folder with a literal backslash in its name ('dir\x') normalizes to the same string as a nested 'dir/x' and produces a false in-use refusal. Probed real, but it needs a backslash-named folder AND its slash twin to coexist, which I am comfortable calling theoretical. If paths.ts is ever touched again, making the backslash replacement win32-only removes it.

@Zaldaryon
Zaldaryon merged commit 0b3564d into dev Aug 18, 2026
7 checks passed
@Zaldaryon
Zaldaryon deleted the fix/version-folder-path-normalize branch August 18, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants