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
from collections import Counter
from dataclasses import dataclass
from enum import Enum
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}")
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(
base_text: str,
local_text: str,
@@ -226,12 +278,6 @@ def merge_playlists(
for chunk in chunks:
if chunk.type == "normal":
if (
strategy == ConflictResolutionStrategy.LOCAL_PRIORITY
and has_conflict
and chunk.origin == "b"
):
continue
merged_lines.extend(chunk.text.splitlines())
else:
conflict_info = {
@@ -243,6 +289,11 @@ def merge_playlists(
resolved = _resolve_conflict(conflict_info, strategy)
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)
return MergeResult(merged_paths=merged_lines, conflicts=conflicts)