Adjust local-priority merge postprocessing
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user