Home

dev / openkara

publicthedavidweng/OpenKara· sync paused
Overview Code History Branches Pull requestsIssuesInsights
main
HomeOverview Code PRsIssues

feat(remote): give a Pre-Publish Conflict a way out, and clear the dead code behind it (#283)

2 months ago

15ef164
Authored
Davy7/27/2026, 10:37:49 AM
* feat(remote): give a Pre-Publish Conflict a way out

The executor has implemented the conflict resolution strategies since the
publish protocol landed, with a comment saying they "will be called from
the UI layer in a subsequent PR". That PR never happened, so the
repository could enter Conflicted, Settings would render the word in
red, and there was nothing to do about it. CONTEXT.md calls a
Pre-Publish Conflict a safety stop; a stop with no exit is not one.

Wire the two real exits end to end: a resolve_remote_conflict command, a
sync/conflict module that locates the active repository and pulls the
winning remote database to a candidate path, and two buttons that appear
in Remote Diagnostics only while the state is conflicted.

The candidate is deliberately not the working copy: until the user
chooses to discard them, the local pending changes are their only copy.

Deleted rather than wired:

- conflict_cancel_for_now was a documented no-op that existed "so PR#8's
  UI has an explicit backend action to call". A button that calls a
  backend no-op is ceremony; the panel just stays as it is.
- ConflictMetadata was documented as living in the operation row's
  error_detail as JSON, but nothing ever wrote it, and the conflict
  detection site is a generic error-to-state mapping with no access to
  the affected song IDs. It can come back with a writer if the richer
  "which songs collided" view gets built.

* chore(remote): delete the code nothing referenced, keep what tests use

Went through the unreferenced items one at a time. Reference counts, not
a lint sweep - the lint could not answer the question, because
--all-targets reports the union of per-target analyses and the plain lib
target (no cfg(test)) flags everything only tests use.

Deleted, zero references anywhere:

- the upload_directory trait method, its three provider implementations,
  and the free functions they delegated to. Mirroring reaches the
  provider through a different path.
- schedule_gc, list_repository_states, mark_pending_and_dirty_tx and its
  only caller mark_operation_pending_and_dirty, set_publish_result,
  set_mirror_result, remote_result_from_command, tombstones_dir,
  prepare_active_remote_database_for_mutation, get_library_publish_outbox
  is kept (tests use it), classify_fetch_status,
  credential_generation_observer.
- ReconnectError::from_remote and its test. Production classifies
  reconnect outcomes in playback.rs by direct construction and
  from_playback_error; from_remote was a parallel path nothing entered,
  and its only caller was to_reconnect_error, which had no callers of its
  own.

Kept, with the reason recorded where it was missing:

- The resumable download driver. An earlier pass deleted it as untested;
  that was wrong. fault_injection has
  t5_mid_transfer_disconnect_resumable_download_completes, a real 16 MiB
  mid-transfer disconnect and resume with digest verification.
- ExecutionProviderPlatform now has the test its non-host variants were
  waiting for: the policy table is exercised for all five platforms from
  any host, which is the entire reason the seam exists.
- ReconnectAttempt::from_cache and seek keep an allow, but the comment
  now says they carry data for a reconnect UI that was never built rather
  than claiming a PR that will read them.

40 dead-code allowances became 30, and every remaining one is load
bearing on some target.

Parent62ace29

43 files changed
  • docs/references/contracts/library.md+15−8
  • src-tauri/src/audio/remote_source.rs+0−18
  • src-tauri/src/commands/remote_library/mod.rs+15−0
  • src-tauri/src/config.rs+57−0
  • src-tauri/src/lib.rs+1−0
  • src-tauri/src/remote/atomic_download.rs+2−7
  • src-tauri/src/remote/control_db.rs+0−90
  • src-tauri/src/remote/dropbox.rs+1
−69
  • src-tauri/src/remote/errors.rs+1−13
  • src-tauri/src/remote/executor.rs+5−57
  • src-tauri/src/remote/fault_injection.rs+1−6
  • src-tauri/src/remote/google_drive.rs+1−70
  • src-tauri/src/remote/manifest.rs+0−9
  • src-tauri/src/remote/mod.rs+1−1
  • src-tauri/src/remote/mutation.rs+0−23
  • src-tauri/src/remote/provider.rs+0−6
  • src-tauri/src/remote/sync.rs+2−0
  • src-tauri/src/remote/sync/conflict.rs+154−0
  • src-tauri/src/remote/sync/revision.rs+0−12
  • src-tauri/src/remote/webdav.rs+1−46
  • src-tauri/src/services/playback.rs+2−10
  • src-tauri/src/services/playback_source.rs+0−8
  • src-tauri/src/services/reconnect.rs+7−65
  • src/components/Settings/SettingsRemoteDiagnosticsSection.test.tsx+67−4
  • src/components/Settings/SettingsRemoteDiagnosticsSection.tsx+54−0
  • src/lib/tauri/remote-repository.ts+14−0
  • src/locales/de.json+5−1
  • src/locales/en.json+5−1
  • src/locales/es.json+5−1
  • src/locales/fr.json+5−1
  • src/locales/id.json+5−1
  • src/locales/it.json+5−1
  • src/locales/ja.json+5−1
  • src/locales/ko.json+5−1
  • src/locales/nl.json+5−1
  • src/locales/pl.json+5−1
  • src/locales/pt-BR.json+5−1
  • src/locales/ru.json+5−1
  • src/locales/th.json+5−1
  • src/locales/tr.json+5−1
  • src/locales/vi.json+5−1
  • src/locales/zh-CN.json+5−1
  • src/locales/zh-TW.json+5−1