fix crashes on migrateGSESavesToSteamUserdata#1207
fix crashes on migrateGSESavesToSteamUserdata#1207utkarshdalal merged 1 commit intoutkarshdalal:masterfrom
Conversation
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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.
🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/utils/SteamUtils.kt (1)
929-934: Implement atomic move fallback for improved compatibility on filesystems without atomic move support.At lines 929–934,
Files.move(...)withATOMIC_MOVEwill throwAtomicMoveNotSupportedExceptionif the filesystem cannot guarantee atomicity. The recommended pattern is to retry without the flag; retrying with justREPLACE_EXISTINGfalls back to copy+delete. Also narrow the catch block fromExceptiontoIOExceptionandSecurityException(currently line 941–943), and make timestamp preservation non-fatal to improve resilience:Suggested approach
+import java.nio.file.AtomicMoveNotSupportedException try { Files.createDirectories(targetFile.parent) val fileTimestamp = file.lastModified() - Files.move( - file.toPath(), - targetFile, - StandardCopyOption.REPLACE_EXISTING, - StandardCopyOption.ATOMIC_MOVE - ) + try { + Files.move( + file.toPath(), + targetFile, + StandardCopyOption.REPLACE_EXISTING, + StandardCopyOption.ATOMIC_MOVE + ) + } catch (_: AtomicMoveNotSupportedException) { + Files.move( + file.toPath(), + targetFile, + StandardCopyOption.REPLACE_EXISTING + ) + } - targetFile.setLastModifiedTime(FileTime.fromMillis(fileTimestamp)) + runCatching { + targetFile.setLastModifiedTime(FileTime.fromMillis(fileTimestamp)) + }.onFailure { err -> + Timber.tag("migrateGSESavesToSteamUserdata") + .w(err, "Migrated ${file.name} but failed to preserve timestamp") + } Timber.tag("migrateGSESavesToSteamUserdata").i("Migrated ${file.name} from GSE saves to Steam userdata") migratedCount++ -} catch (e: Exception) { +} catch (e: IOException) { + migrationFailed = true + Timber.tag("migrateGSESavesToSteamUserdata").w(e, "Failed to migrate ${file.name}") +} catch (e: SecurityException) { migrationFailed = true Timber.tag("migrateGSESavesToSteamUserdata").w(e, "Failed to migrate ${file.name}") }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/app/gamenative/utils/SteamUtils.kt` around lines 929 - 934, The Files.move call using StandardCopyOption.ATOMIC_MOVE can throw AtomicMoveNotSupportedException; update the move logic in SteamUtils (the block calling Files.move(file.toPath(), targetFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE)) to catch AtomicMoveNotSupportedException and retry the move without ATOMIC_MOVE (i.e., only REPLACE_EXISTING) so the operation falls back to copy+delete on non-atomic filesystems, and narrow exception handling to catch IOException and SecurityException rather than a broad Exception; also make timestamp preservation (where file times are copied) non-fatal by logging failures instead of propagating exceptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@app/src/main/java/app/gamenative/utils/SteamUtils.kt`:
- Around line 929-934: The Files.move call using StandardCopyOption.ATOMIC_MOVE
can throw AtomicMoveNotSupportedException; update the move logic in SteamUtils
(the block calling Files.move(file.toPath(), targetFile,
StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE)) to catch
AtomicMoveNotSupportedException and retry the move without ATOMIC_MOVE (i.e.,
only REPLACE_EXISTING) so the operation falls back to copy+delete on non-atomic
filesystems, and narrow exception handling to catch IOException and
SecurityException rather than a broad Exception; also make timestamp
preservation (where file times are copied) non-fatal by logging failures instead
of propagating exceptions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 10af7074-422b-4a25-bbd5-37cd3baacad8
📒 Files selected for processing (1)
app/src/main/java/app/gamenative/utils/SteamUtils.kt
Description
Quote from discord: COPY_ATTRIBUTES is not a valid/supported option for Files.move on Android’s NIO implementation, so Files.move throws UnsupportedOperationException immediately. The code only catches IOException, so the exception escapes and crashes the app.
Recording
None
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 crashes when migrating GSE saves to Steam userdata on Android. Removes an unsupported move option, preserves file timestamps manually, and hardens error handling.
StandardCopyOption.COPY_ATTRIBUTESfromFiles.move(unsupported on Android); set timestamp viasetLastModifiedTime.Exceptioninstead of onlyIOExceptionsoUnsupportedOperationExceptionis handled and migration continues.StandardCopyOption.ATOMIC_MOVEand create parent directories before moving.Written for commit fa5ef46. Summary will update on new commits.
Summary by CodeRabbit