|
| 1 | +"""Unified sync-action logic for save sync v2. |
| 2 | +
|
| 3 | +Extends the existing conflict detection (save_conflicts.py) with |
| 4 | +RomM v4.7 device sync awareness (is_current flag from device_syncs). |
| 5 | +
|
| 6 | +No I/O, no service/adapter/lib imports. Pure functions only. |
| 7 | +""" |
| 8 | + |
| 9 | +from __future__ import annotations |
| 10 | + |
| 11 | +from domain.save_conflicts import check_server_changes_fast, determine_action |
| 12 | + |
| 13 | + |
| 14 | +def check_server_changed_v47(device_sync_info: dict | None) -> bool | None: |
| 15 | + """Check server change using v4.7 device_syncs info. |
| 16 | +
|
| 17 | + Parameters |
| 18 | + ---------- |
| 19 | + device_sync_info: |
| 20 | + A single device sync record from the server's device_syncs array, |
| 21 | + or None if not available (v4.6 / no device registered). |
| 22 | +
|
| 23 | + Returns |
| 24 | + ------- |
| 25 | + bool | None |
| 26 | + True if server changed (is_current == False), |
| 27 | + False if server unchanged (is_current == True), |
| 28 | + None if indeterminate (no device_sync_info provided, or is_current is |
| 29 | + absent/None). |
| 30 | + """ |
| 31 | + if device_sync_info is None: |
| 32 | + return None |
| 33 | + is_current = device_sync_info.get("is_current") |
| 34 | + if is_current is None: |
| 35 | + return None |
| 36 | + return not is_current |
| 37 | + |
| 38 | + |
| 39 | +def determine_sync_action( |
| 40 | + local_changed: bool, |
| 41 | + server_save: dict | None, |
| 42 | + device_sync_info: dict | None = None, |
| 43 | + file_state: dict | None = None, |
| 44 | +) -> str: |
| 45 | + """Determine the sync action combining local and server change detection. |
| 46 | +
|
| 47 | + Parameters |
| 48 | + ---------- |
| 49 | + local_changed: |
| 50 | + Whether the local file has changed since last sync (caller computes this). |
| 51 | + server_save: |
| 52 | + Server save metadata dict, or None if no server save exists. |
| 53 | + device_sync_info: |
| 54 | + v4.7 device sync record (has "is_current" key), or None for v4.6 fallback. |
| 55 | + file_state: |
| 56 | + Per-file sync state dict (used for v4.6 fallback via check_server_changes_fast). |
| 57 | + Only needed when device_sync_info is None. |
| 58 | +
|
| 59 | + Returns |
| 60 | + ------- |
| 61 | + str |
| 62 | + One of "skip", "upload", "download", "conflict", "initial_upload", |
| 63 | + "initial_download". |
| 64 | + """ |
| 65 | + # No server save at all |
| 66 | + if server_save is None: |
| 67 | + return "initial_upload" if local_changed else "skip" |
| 68 | + |
| 69 | + # Server save exists — determine whether server has changed |
| 70 | + server_changed: bool |
| 71 | + |
| 72 | + # Priority 1: v4.7 device_sync_info |
| 73 | + v47_result = check_server_changed_v47(device_sync_info) |
| 74 | + if v47_result is not None: |
| 75 | + server_changed = v47_result |
| 76 | + else: |
| 77 | + # Priority 2: v4.6 fast-path using file_state |
| 78 | + if file_state is not None: |
| 79 | + v46_result = check_server_changes_fast(file_state, server_save) |
| 80 | + server_changed = v46_result if v46_result is not None else True |
| 81 | + else: |
| 82 | + # Priority 3: no info at all — safe default: assume server changed |
| 83 | + server_changed = True |
| 84 | + |
| 85 | + return determine_action(local_changed, server_changed) |
0 commit comments