Adjust local-priority merge postprocessing

This commit is contained in:
Koha9
2025-11-25 10:08:49 +09:00
parent 97aa598775
commit 0bb624f3c9
+57 -6
View File
@@ -1,4 +1,5 @@
import os import os
from collections import Counter
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Literal, Sequence from typing import Literal, Sequence
@@ -200,6 +201,57 @@ def _resolve_conflict(conflict: dict, strategy: ConflictResolutionStrategy) -> l
raise ValueError(f"Unsupported conflict resolution strategy: {strategy}") raise ValueError(f"Unsupported conflict resolution strategy: {strategy}")
def _postprocess_local_priority_merge(
merged_lines: list[str],
base_paths: Sequence[str],
local_paths: Sequence[str],
remote_paths: Sequence[str],
) -> list[str]:
"""Fix local-priority edge cases without disturbing existing order."""
base_counter = Counter(base_paths)
local_counter = Counter(local_paths)
remote_counter = Counter(remote_paths)
merged_counter = Counter(merged_lines)
merged = list(merged_lines)
# 1) Preserve tracks that only Remote added (not in Base or Local).
for track, remote_count in remote_counter.items():
if base_counter[track] == 0 and local_counter[track] == 0 and remote_count > 0:
current = merged_counter.get(track, 0)
while current < remote_count:
merged.append(track)
merged_counter[track] += 1
current += 1
# 2) For tracks only new in Local+Remote (not in Base), keep Local's count.
candidate_tracks = set(local_counter.keys()) | set(remote_counter.keys())
for track in candidate_tracks:
if base_counter[track] == 0 and local_counter[track] > 0 and remote_counter[track] > 0:
target = local_counter[track]
current = merged_counter.get(track, 0)
if current > target:
remove_needed = current - target
trimmed: list[str] = []
for path in reversed(merged):
if remove_needed and path == track:
remove_needed -= 1
continue
trimmed.append(path)
trimmed.reverse()
merged = trimmed
merged_counter = Counter(merged)
current = merged_counter.get(track, 0)
while current < target:
merged.append(track)
current += 1
merged_counter[track] = current
return merged
def merge_playlists( def merge_playlists(
base_text: str, base_text: str,
local_text: str, local_text: str,
@@ -226,12 +278,6 @@ def merge_playlists(
for chunk in chunks: for chunk in chunks:
if chunk.type == "normal": if chunk.type == "normal":
if (
strategy == ConflictResolutionStrategy.LOCAL_PRIORITY
and has_conflict
and chunk.origin == "b"
):
continue
merged_lines.extend(chunk.text.splitlines()) merged_lines.extend(chunk.text.splitlines())
else: else:
conflict_info = { conflict_info = {
@@ -243,6 +289,11 @@ def merge_playlists(
resolved = _resolve_conflict(conflict_info, strategy) resolved = _resolve_conflict(conflict_info, strategy)
merged_lines.extend(resolved) merged_lines.extend(resolved)
if strategy == ConflictResolutionStrategy.LOCAL_PRIORITY:
merged_lines = _postprocess_local_priority_merge(
merged_lines, base_paths, local_paths, remote_paths
)
_write_results(merged_lines, test_folder) _write_results(merged_lines, test_folder)
return MergeResult(merged_paths=merged_lines, conflicts=conflicts) return MergeResult(merged_paths=merged_lines, conflicts=conflicts)