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