Skip to content

Combine directory monitoring fixes into one implementation#565

Open
moreaki wants to merge 2 commits intomangerlahn:mainfrom
moreaki:fix/combined-directory-monitoring
Open

Combine directory monitoring fixes into one implementation#565
moreaki wants to merge 2 commits intomangerlahn:mainfrom
moreaki:fix/combined-directory-monitoring

Conversation

@moreaki
Copy link
Copy Markdown

@moreaki moreaki commented Mar 15, 2026

Summary

This PR combines the work that was previously split across #559, #561, and #562 into one coherent implementation for app-directory discovery and monitoring.

Instead of merging three overlapping changes that each patch one failure mode, this PR reshapes the AppDirectory / AppLibrary path so Latest now has a single directory-monitoring design that:

  • keeps startup resilient when a configured scan directory cannot be observed
  • prevents the startup DispatchGroup imbalance that could crash during initial directory setup
  • watches application directories recursively so nested subfolder changes are detected
  • visibly alerts the user when a directory cannot be monitored, including the failing path and the system error

Supersedes:

What Changed

1. Replace the root-only watcher with recursive monitoring

AppDirectory now uses a recursive FSEvents-based monitor instead of a single DispatchSourceFileSystemObject on the root directory.

That means the live watcher now matches what the initial scan already did: recursively discover apps below the configured application roots.

This resolves the subfolder refresh gap described in #562.

2. Keep startup alive when monitoring cannot be established

If a configured scan path cannot be monitored, Latest no longer crashes.

Instead:

  • the path is still scanned once, so startup can continue
  • the observation failure is captured as a real error with the relevant path
  • the rest of the update-check flow proceeds normally

This preserves the resilience work from #559.

3. Surface observation failures to the user through native macOS UI

Following the request in the last user comment on #559, Latest now visibly alerts the user when a scan directory cannot be monitored.

The app:

  • requests user attention from macOS
  • presents a native warning sheet on the main window
  • shows the exact folder path that failed
  • includes the localized system error
  • adds an extra hint when the failure looks like a permissions problem (EACCES / EPERM)

This turns the degraded path from a silent fallback into something the user can actually act on.

4. Fix startup callback accounting in AppLibrary

AppLibrary.setupDirectoryObservers() still uses a DispatchGroup to wait for each newly created AppDirectory to complete its initial scan.

The previous implementation assumed that a new observer would only produce one callback during startup. In practice, that assumption could fail and lead to an unbalanced dispatch_group_leave() crash.

This PR makes the startup completion path one-shot per new observer, and routes all later callbacks through the existing deferred update scheduler.

This absorbs the fix from #561.

Files / Areas Touched

  • Latest/Model/Directory/AppDirectory.swift
  • Latest/Model/Directory/AppLibrary.swift
  • Latest/Model/UpdateCheckCoordinator.swift
  • Latest/Interface/Main Window/Window Controllers/MainWindowController.swift
  • Latest/Resources/en.lproj/Localizable.strings
  • Tests/OSVersionTest.swift

Behavioral Result

After this PR:

  • Latest no longer crashes when a scan directory cannot be observed
  • nested app folders trigger refreshes without needing a restart or manual rescan
  • startup no longer risks the duplicate DispatchGroup.leave() crash
  • users get a visible in-app warning when directory observation fails, with enough detail to identify the problematic path

Verification

Build:

  • xcodebuild -project Latest.xcodeproj -scheme Latest -configuration Debug CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= build
  • result: succeeded

Tests:

  • the regression coverage added here includes:
    • fallback when a directory cannot be observed
    • recursive refresh when an app bundle appears in a nested subfolder
  • full xcodebuild test is still blocked in this environment by the existing test-target dependency problem resolving CommerceKit / StoreFoundation when importing Latest

Notes

The point of this PR is to leave the project with one maintainable end state instead of three partially overlapping branches that all modify directory observation for different reasons.

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