Skip to content

fix(): Fixed AppData subfolder detection bug to fix Disco Eslysium save path resolution - #1557

Closed
phobos665 wants to merge 1 commit into
utkarshdalal:masterfrom
phobos665:fix/epic-saves-disco-elysium-fix
Closed

fix(): Fixed AppData subfolder detection bug to fix Disco Eslysium save path resolution#1557
phobos665 wants to merge 1 commit into
utkarshdalal:masterfrom
phobos665:fix/epic-saves-disco-elysium-fix

Conversation

@phobos665

@phobos665 phobos665 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Description

AppData subfolders weren't be capitlized correctly and thus were being missed out by Epic's CloudSavesManager.

This was seen in Disco Elysium where saves weren't being uploaded or downloaded correctly as it couldn't detect the folder:

Here's what the fix now gives:

Uploading:

06-09 13:22:23.905  6332  8738 I Epic    : [Cloud Saves] Found 2 files to package
06-09 13:22:23.905  6332  8738 D Epic    : [Cloud Saves] Processing file: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).jpg (46829 bytes)
06-09 13:22:23.908  6332  8738 D Epic    : [Cloud Saves] Processing file: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).ntwtf.zip (879648 bytes)
06-09 13:22:23.990  6332  8738 D Epic    : [Cloud Saves] Finalized chunk #0: 923edbcd-6fee95ce-bdc08cb7-181e2643 groupNum=81 (870634 bytes)
06-09 13:22:23.991  6332  8738 I Epic    : [Cloud Saves] Packaged 2 files into 1 chunks
06-09 13:22:23.991  6332  8738 D Epic    : [Cloud Saves] Requesting write links for 2 files
06-09 13:22:23.991  6332  8738 D Epic    : [Cloud Saves] Requesting write link for: ChunksV4/81/AEA94C6F932CB580_923EDBCD6FEE95CEBDC08CB7181E2643.chunk
06-09 13:22:23.991  6332  8738 D Epic    : [Cloud Saves] Requesting write link for: manifests/2026.06.09-13.22.23.manifest
06-09 13:22:23.991  6332  8738 D Epic    : [Cloud Saves] Request body: {"files":["ChunksV4\/81\/AEA94C6F932CB580_923EDBCD6FEE95CEBDC08CB7181E2643.chunk","manifests\/2026.06.09-13.22.23.manifest"]}
06-09 13:22:24.139  6332  8738 D Epic    : [Cloud Saves] Response code: 200
06-09 13:22:24.139  6332  8738 I Epic    : [Cloud Saves] Received 2 write links
06-09 13:22:24.140  6332  8738 D Epic    : [Cloud Saves] Uploading chunk: ChunksV4/81/AEA94C6F932CB580_923EDBCD6FEE95CEBDC08CB7181E2643.chunk (870634 bytes)
06-09 13:22:25.573  6332  8738 I Epic    : [Cloud Saves] Uploaded chunk: ChunksV4/81/AEA94C6F932CB580_923EDBCD6FEE95CEBDC08CB7181E2643.chunk (870634 bytes)
06-09 13:22:25.573  6332  8738 D Epic    : [Cloud Saves] Uploading manifest: manifests/2026.06.09-13.22.23.manifest (430 bytes)
06-09 13:22:25.697  6332  8738 I Epic    : [Cloud Saves] Uploaded manifest: manifests/2026.06.09-13.22.23.manifest (430 bytes)
06-09 13:22:25.698  6332  8738 I Epic    : [Cloud Saves] Upload complete: 1 chunks uploaded

Downloading:

06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves] Scanning path: /data/user/0/app.gamenative/files/imagefs/home/xuser-EPIC_362/.wine/drive_c/users/xuser/AppData/LocalLow/ZAUM Studio/Disco Elysium/SaveGames
06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves] Path exists: true
06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves] Total items in path: 2
06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves]   FILE: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).jpg (46829 bytes)
06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves]   FILE: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).ntwtf.zip (879648 bytes)

06-09 13:25:04.668  6332  8753 D Epic    : [Cloud Saves] Reconstructing file: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).jpg
06-09 13:25:04.669  6332  8753 I Epic    : [Cloud Saves] Reconstructed: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).jpg (46829 bytes)
06-09 13:25:04.669  6332  8753 D Epic    : [Cloud Saves] Reconstructing file: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).ntwtf.zip
06-09 13:25:04.670  6332  8753 I Epic    : [Cloud Saves] Reconstructed: WHIRLING-IN-RAGS, DAY 1, 08-06(6_9_2026 9-36-35 AM).ntwtf.zip (879648 bytes)
06-09 13:25:04.670  6332  8753 I Epic    : [Cloud Saves] Download complete: 2 files reconstructed
06-09 13:25:04.670  6332  8753 I Epic    : [Cloud Saves] Sync completed successfully

This is based on my testing with both unit tests & uploading & downloading saves back and forth between 2 devices.

Changes

Recording

Type of Change

  • Bug fix
  • Performance / stability improvement
  • Compatibility improvements
  • Other (requires prior approval)

Checklist

  • If I have access to #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.
  • This change aligns with the current project scope (core functionality, stability, or performance). If not, it has been explicitly approved beforehand.
  • I have attached a recording of the change.
  • I have read and agree to the contribution guidelines in CONTRIBUTING.md.

Summary by cubic

Fixes AppData casing resolution so Epic Cloud Saves correctly detects Disco Elysium save paths. Saves now upload and download reliably.

  • Bug Fixes
    • Canonicalize AppData child segments to Local, LocalLow, and Roaming.
    • Resolve absolute paths case-insensitively within trusted roots to match on-disk casing and avoid duplicate directories.
    • Added unit tests for LocalLow path resolution and AppData canonicalization.

Written for commit 08c8d8d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved Epic cloud save directory resolution to handle system path variations more reliably, ensuring saves are consistently stored in the correct location regardless of configuration differences.
  • Tests

    • Added test coverage to validate cloud save path resolution and verify proper system directory naming and consistency.

@phobos665
phobos665 requested a review from utkarshdalal as a code owner June 9, 2026 13:30
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR modifies Epic cloud-save directory resolution to canonicalize AppData path segments and resolve paths against trusted root directories (user, Wine prefix, install) instead of the filesystem root, with accompanying tests to validate the new behavior.

Changes

Epic Cloud Save Path Resolution

Layer / File(s) Summary
Path Resolution Helper Functions and Integration
app/src/main/java/app/gamenative/service/epic/EpicCloudSavesManager.kt
Two new internal helpers—resolveAbsolutePathCaseInsensitive(path, trustedRoots) for case-insensitive path resolution against trusted roots, and canonicalizeAppDataSegments(segments) for normalizing AppData-related casing (e.g., locallowLocalLow, roamingRoaming)—are added and integrated into resolveSaveDirectory, replacing the prior root-relative resolution approach.
Path Resolution Tests and Test Infrastructure
app/src/test/java/app/gamenative/service/epic/EpicCloudSavesTest.kt
Test file imports File and JUnit rules; a TemporaryFolder rule (tmpDir) is added to the test class, followed by two new @Test methods that validate case-insensitive resolution of AppData/LocalLow cloud-save paths and AppData segment canonicalization against on-disk directory structures.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • utkarshdalal/GameNative#941: Modifies EpicCloudSavesManager cloud-save path resolution logic and extends related save-path tests.
  • utkarshdalal/GameNative#589: Also modifies EpicCloudSavesManager.resolveSaveDirectory to adjust cloud save directory construction and normalization.

Suggested reviewers

  • utkarshdalal
  • kiequoo

Poem

🐰 Paths that dance with casing free,
Trusted roots guide them, you will see,
AppData segments, now canonized,
Save directories—finally prized! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the bug being fixed (AppData subfolder detection) and its impact (Disco Elysium save path resolution), directly reflecting the main change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is mostly complete with clear explanation of the bug, fix rationale, and evidence from logs. All required checklist items are marked.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cubic-dev-ai cubic-dev-ai Bot 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.

1 issue found across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@utkarshdalal

Copy link
Copy Markdown
Owner

@phobos665 - question, why was it not fixed by this PR? #941

Also, the CaseInsensitiveFileSystem seems to be the right place to fix it rather than just overriding for Epic. Could you look please?

@phobos665

phobos665 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@phobos665 - question, why was it not fixed by this PR? #941

Also, the CaseInsensitiveFileSystem seems to be the right place to fix it rather than just overriding for Epic. Could you look please?

Thanks.

It's because it's specifically around LocalLow, from what I understood Linux was matching insensitively to locallow, which worked for Windows, but not for Linux.

So we'd match for locallow instead of LocalLow.

Example:

Before:

[Cloud Saves] Scanning path: /data/user/0/app.gamenative/files/imagefs/home/xuser-EPIC_359/.wine/drive_c/users/xuser/AppData/locallow/ZAUM Studio/Disco Elysium/SaveGames

06-09 09:22:04.323 32665 14772 D Epic : [Cloud Saves] Resolved: /data/user/0/app.gamenative/files/imagefs/home/xuser-EPIC_359/.wine/drive_c/users/xuser/AppData/locallow/ZAUM Studio/Disco Elysium/SaveGames

You can see above that it case-insensitvely matched, but they're different folders in Linux. So the actual fix is not to do case-insensitivity on its own, but to match it correctly to the right capitlisation.

After:

Original: {appdata}/../locallow/ZAUM Studio/Disco Elysium/SaveGames/

Resolved: /data/user/0/app.gamenative/files/imagefs/home/xuser-EPIC_362/.wine/drive_c/users/xuser/AppData/LocalLow/ZAUM Studio/Disco Elysium/SaveGames

TL;DR The specific casing is very important for the subfolders of Appdata. Matching case-insensitively breaks the folder structure and causing misses. Before it would match on locallow, but needs to be case-sensitively linked to LocalLow.

@utkarshdalal

Copy link
Copy Markdown
Owner

Hey I've made a PR to this branch, can you check? And also confirm if it fixes the issue?

Basically this should be fixed at the caseinsensitivefilesystem level so that it applies to all stores

@utkarshdalal

Copy link
Copy Markdown
Owner

Done in #1598 - closing

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