Skip to content

refactor: Symlink imagefs_shared home in the variants + migrate old home contents#1030

Open
unbelievableflavour wants to merge 1 commit intoutkarshdalal:masterfrom
unbelievableflavour:home-in-imagefs-shared
Open

refactor: Symlink imagefs_shared home in the variants + migrate old home contents#1030
unbelievableflavour wants to merge 1 commit intoutkarshdalal:masterfrom
unbelievableflavour:home-in-imagefs-shared

Conversation

@unbelievableflavour
Copy link
Copy Markdown
Contributor

@unbelievableflavour unbelievableflavour commented Mar 26, 2026


Summary by cubic

Share a single user home across container variants by backing /home with imagefs_shared/home. Adds safe migration from legacy home and ensures the symlink is created on install and when the imagefs is already current.

  • New Features
    • Ensure imagefs_shared/home exists via ImageFs.getImageFsSharedDir() and symlink each variant’s /home to it on fresh install and when the imagefs is already valid.
    • Migrate legacy imagefs/home into the shared path with ImageFSLegacyMigrator; no-op if already a symlink, overwrite existing shared home, fallback to copy+delete, and abort install on failure.

Written for commit 6f62240. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Better preserves user home data during image filesystem installs and upgrades to avoid file loss.
    • Ensures the shared home location is created and used consistently, preventing duplicate or conflicting directories.
    • Adds safe migration from legacy home directories with non-destructive fallback if direct move fails.
    • Improves robustness for varied filesystem layouts, handling symlink, existing shared, and conflict scenarios more gracefully.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

ImageFsInstaller now enforces a shared backing for the imagefs /home directory: it creates/uses files/imagefs_shared, migrates legacy files/imagefs/home when appropriate, and ensures rootDir/home is a symlink to the shared location during install and fast-path checks.

Changes

Cohort / File(s) Summary
Shared Home Directory Management
app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java
Added helpers getImageFsSharedDir(), migrateLegacyHomeToShared(), and ensureSharedHomeRoot(). Install flow now calls ensureSharedHomeRoot(context, rootDir) after clearRootDir(...) before extracting payload. Fast-path for already-valid imagefs now runs ensureSharedHomeRoot(context, imageFs.getRootDir()) before returning. New control flow handles symlink detection, migration, and conflict/error early exits.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hop and nudge a shared domain,
I link the burrows, move the grain,
Old homes migrate without a fight,
One shared cozy, snug and bright,
Hooray—our warren sleeps tonight! 🥕✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides clear context via the auto-generated summary explaining the feature and changes, though it lacks a recorded demonstration and does not explicitly confirm the contribution guidelines checklist items. Consider adding a recording/GIF demonstrating the home directory sharing behavior and explicitly confirming the checklist items from the template (code-changes discussion, recording, and contribution guidelines agreement).
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'refactor: Symlink imagefs_shared home in the variants + migrate old home contents' directly and specifically describes the main changes: symlinking shared home across variants and migrating legacy home contents.

✏️ 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.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 1 file

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/main/java/com/winlator/xenvironment/ImageFsInstaller.java">

<violation number="1" location="app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java:397">
P2: Unconditionally deleting the existing shared home before migration can wipe shared user data when multiple variants or repeated runs already populated imagefs_shared/home.</violation>

<violation number="2" location="app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java:444">
P2: ensureSharedHomeRoot will attempt to create the /home symlink even when an existing non-symlink /home directory remains. If migration fails, FileUtils.symlink will fail because it only deletes the path (non-empty directories aren’t removed), leaving /home unshared and breaking the intended shared-home invariant.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java`:
- Around line 211-213: The code calls ensureSharedHomeRoot(context,
imageFs.getRootDir()) synchronously before creating the Future in
installIfNeededFuture(), which can block the caller; move that work into the
submitted task so the method remains fully asynchronous — replace the current
sequence (ensureSharedHomeRoot(...); return
Executors.newSingleThreadExecutor().submit(() -> true);) with a single
submit(...) that runs ensureSharedHomeRoot(context, imageFs.getRootDir()) inside
the callable/runnable and then returns true (i.e.,
Executors.newSingleThreadExecutor().submit(() -> { ensureSharedHomeRoot(context,
imageFs.getRootDir()); return true; })).
- Around line 395-445: ensureSharedHomeRoot currently pre-creates and may delete
an existing sharedHomeRoot during migration; change migrate flow so you do NOT
clobber an existing sharedHomeRoot and only create/replace it when migration
succeeds. Specifically, in ensureSharedHomeRoot/ migrateLegacyHomeToShared: stop
precreating sharedHomeRoot in getImageFsSharedDir/ensureSharedHomeRoot, first
check if sharedHomeRoot exists and is non-empty and if so skip migration; when
migrating (migrateLegacyHomeToShared), attempt a safe move or copy into a
temporary directory and on success atomically rename into sharedHomeRoot (or
create sharedHomeRoot only after copy succeeds), do not delete an existing
populated sharedHomeRoot, and only create the symlink (FileUtils.symlink) from
homePathInImageFs to sharedHomeRoot after migration completed successfully and
homePathInImageFs is absent or confirmed safe to replace. Reference
ensureSharedHomeRoot, migrateLegacyHomeToShared, getImageFsSharedDir,
sharedHomeRoot, and homePathInImageFs.
🪄 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: 76b66bf7-d9be-4f58-9c26-867cd4bc3630

📥 Commits

Reviewing files that changed from the base of the PR and between 460dadc and bf53a6c.

📒 Files selected for processing (3)
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/com/winlator/core/WineUtils.java
  • app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java

@unbelievableflavour unbelievableflavour force-pushed the home-in-imagefs-shared branch 3 times, most recently from 889ca5e to 741ec6a Compare March 27, 2026 05:32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java`:
- Around line 405-413: The copy branch in ImageFsInstaller currently leaves
partial contents in sharedHomeRoot when FileUtils.copy(legacyHome,
sharedHomeRoot) returns false; modify the failure path in the method containing
this logic so that on a failed copy you remove the partially-created
sharedHomeRoot (recursively delete sharedHomeRoot or its contents) before
returning false, and also catch and log any exception thrown during the cleanup;
reference the FileUtils.copy call, sharedHomeRoot and legacyHome to locate the
code and ensure the cleanup runs only on failure and does not run when copy
returns true.
- Around line 449-457: The code may call sharedHomeRoot.mkdirs() without
checking its result, leading to creating a symlink to a non-existent target;
update ImageFsInstaller to verify directory creation by checking the boolean
return of sharedHomeRoot.mkdirs() (and/or re-checking sharedHomeRoot.exists()
after the call), and if creation failed log an error via Log.e with context
(including sharedHomeRoot.getPath()), abort the install path (return or throw)
before calling FileUtils.symlink, so the symlink is never created when the
directory does not actually exist; locate the logic around sharedHomeRoot,
homePathInImageFs and the FileUtils.symlink call to implement this check.
🪄 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: 79f10c8c-bb1d-4357-9d9e-75958b631afe

📥 Commits

Reviewing files that changed from the base of the PR and between 889ca5e and 741ec6a.

📒 Files selected for processing (1)
  • app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java

@unbelievableflavour unbelievableflavour force-pushed the home-in-imagefs-shared branch 2 times, most recently from abf2ec2 to 36fbd11 Compare April 1, 2026 11:21
@unbelievableflavour unbelievableflavour changed the title Symlink imagefs_shared home in the variants + migrate old home contents refactor: Symlink imagefs_shared home in the variants + migrate old home contents Apr 8, 2026
@unbelievableflavour unbelievableflavour force-pushed the home-in-imagefs-shared branch 2 times, most recently from 03afa96 to accb3d2 Compare April 9, 2026 13:44
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.

1 participant