Fix/case insensitive cloud saves - #1598
Conversation
…y having their save files being detected.
resolveCaseInsensitive() gave up case-insensitive matching for the rest
of the path the moment listFiles() returned null (unreadable dirs like
/data on Android, or not-yet-created dirs). Anchored at File("/"), the
walk bailed on the first segment and appended everything verbatim,
including lowercase AppData subfolders like locallow, so Epic cloud saves
never matched the on-disk LocalLow.
Descend with the literal segment instead of bailing, resuming matching at
any level we can read. This fixes the Disco Elysium save detection at the
shared helper, so GOG saves benefit too, and removes the Epic-specific
resolveAbsolutePathCaseInsensitive workaround.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthrough
ChangesCase-Insensitive Path Resolution and Epic Cloud Saves Testing
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt`:
- Around line 103-110: The test method `resolveCaseInsensitive keeps matching
after an unmatched parent segment` has a mismatch between its name and actual
test case. The test name indicates it should validate behavior when there is an
unmatched parent segment in the path, but the current test input path
`existing/nested/locallow` matches all segments in the directory structure
`Existing/Nested/LocalLow`. To fix this, modify the path passed to
`FileUtils.resolveCaseInsensitive` to include at least one unmatched segment
(for example, change one of the segments to a non-existent name) so that the
test actually validates the regression where matching continues even after
encountering an unmatched parent segment, not just a normal fully-matching
case-insensitive path resolution.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a27381fb-76a4-463e-9f42-9200e3a7791e
📒 Files selected for processing (3)
app/src/main/java/app/gamenative/service/epic/EpicCloudSavesManager.ktapp/src/main/java/app/gamenative/utils/FileUtils.ktapp/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt
| fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() { | ||
| val base = tmpDir.newFolder("base") | ||
| val deep = File(base, "Existing/Nested/LocalLow").apply { mkdirs() } | ||
|
|
||
| val resolved = FileUtils.resolveCaseInsensitive(base, "existing/nested/locallow") | ||
|
|
||
| assertEquals(deep.absolutePath, resolved.absolutePath) | ||
| assertTrue(resolved.exists()) |
There was a problem hiding this comment.
Test intent doesn’t match what is being asserted
At Line 103, the case uses existing/nested/locallow, which is a normal mixed-case match and does not include an unmatched parent/fallback condition. This won’t validate the specific regression described by the test name.
Suggested minimal correction
- fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() {
+ fun `resolveCaseInsensitive resolves nested path segments case-insensitively`() {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() { | |
| val base = tmpDir.newFolder("base") | |
| val deep = File(base, "Existing/Nested/LocalLow").apply { mkdirs() } | |
| val resolved = FileUtils.resolveCaseInsensitive(base, "existing/nested/locallow") | |
| assertEquals(deep.absolutePath, resolved.absolutePath) | |
| assertTrue(resolved.exists()) | |
| fun `resolveCaseInsensitive resolves nested path segments case-insensitively`() { | |
| val base = tmpDir.newFolder("base") | |
| val deep = File(base, "Existing/Nested/LocalLow").apply { mkdirs() } | |
| val resolved = FileUtils.resolveCaseInsensitive(base, "existing/nested/locallow") | |
| assertEquals(deep.absolutePath, resolved.absolutePath) | |
| assertTrue(resolved.exists()) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt` around
lines 103 - 110, The test method `resolveCaseInsensitive keeps matching after an
unmatched parent segment` has a mismatch between its name and actual test case.
The test name indicates it should validate behavior when there is an unmatched
parent segment in the path, but the current test input path
`existing/nested/locallow` matches all segments in the directory structure
`Existing/Nested/LocalLow`. To fix this, modify the path passed to
`FileUtils.resolveCaseInsensitive` to include at least one unmatched segment
(for example, change one of the segments to a non-existent name) so that the
test actually validates the regression where matching continues even after
encountering an unmatched parent segment, not just a normal fully-matching
case-insensitive path resolution.
There was a problem hiding this comment.
1 issue found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt">
<violation number="1" location="app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt:103">
P3: Test name is misleading: the test resolves `existing/nested/locallow` against an on-disk `Existing/Nested/LocalLow` where every segment matches case-insensitively. There is no "unmatched parent segment" being exercised here. Consider renaming to accurately describe what it validates, e.g. `resolveCaseInsensitive resolves nested path segments case-insensitively`.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| } | ||
|
|
||
| @Test | ||
| fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() { |
There was a problem hiding this comment.
P3: Test name is misleading: the test resolves existing/nested/locallow against an on-disk Existing/Nested/LocalLow where every segment matches case-insensitively. There is no "unmatched parent segment" being exercised here. Consider renaming to accurately describe what it validates, e.g. resolveCaseInsensitive resolves nested path segments case-insensitively.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt, line 103:
<comment>Test name is misleading: the test resolves `existing/nested/locallow` against an on-disk `Existing/Nested/LocalLow` where every segment matches case-insensitively. There is no "unmatched parent segment" being exercised here. Consider renaming to accurately describe what it validates, e.g. `resolveCaseInsensitive resolves nested path segments case-insensitively`.</comment>
<file context>
@@ -75,6 +82,43 @@ class EpicCloudSavesTest {
+ }
+
+ @Test
+ fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() {
+ val base = tmpDir.newFolder("base")
+ val deep = File(base, "Existing/Nested/LocalLow").apply { mkdirs() }
</file context>
| fun `resolveCaseInsensitive keeps matching after an unmatched parent segment`() { | |
| fun `resolveCaseInsensitive resolves nested path segments case-insensitively`() { |
Description
The CaseInsensitiveFileSystem wasn't working. Disco Elysium saves on Epic were saving to locallow instead of LocalLow. This fixes it.
Recording
Type of Change
Checklist
#code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.CONTRIBUTING.md.Summary by cubic
Fixes case-insensitive path resolution so cloud saves use on-disk casing (e.g., AppData/LocalLow). Removes Epic-specific workaround and relies on the shared resolver to restore save detection for Disco Elysium (and other stores using the shared path resolver).
FileUtils.resolveCaseInsensitiveto continue matching across unreadable/missing parents, using literal segments only when needed; ensuresAppData/LocalLowresolves to on-disk casing and avoids duplicate dirs.Written for commit eb47201. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
Tests