Fix local-priority merge to avoid remote reorders in conflicts
This commit is contained in:
+28
-15
@@ -76,6 +76,7 @@ class MergeChunk:
|
||||
base_text: str | None = None
|
||||
local_text: str | None = None
|
||||
remote_text: str | None = None
|
||||
origin: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -126,15 +127,25 @@ def _normalize_inputs(
|
||||
def _merge_chunks(
|
||||
base_paths: Sequence[str], local_paths: Sequence[str], remote_paths: Sequence[str]
|
||||
) -> list[MergeChunk]:
|
||||
"""Run a diff3 merge on normalized playlists and return merge chunks."""
|
||||
|
||||
merger = Merge3(base_paths, local_paths, remote_paths)
|
||||
raw_chunks = list(merger.merge_groups())
|
||||
chunks: list[MergeChunk] = []
|
||||
|
||||
for group in merger.merge_groups():
|
||||
kind = group[0]
|
||||
for kind, *payload in raw_chunks:
|
||||
if kind == "conflict":
|
||||
base_lines, local_lines, remote_lines = group[1], group[2], group[3]
|
||||
base_lines, local_lines, remote_lines = payload # type: ignore[misc]
|
||||
|
||||
# Absorb trailing side-only chunks that actually belong to this
|
||||
# conflicting region (common in reorder scenarios).
|
||||
while chunks and chunks[-1].origin in ("a", "b"):
|
||||
previous = chunks.pop()
|
||||
previous_lines = previous.text.splitlines() if previous.text else []
|
||||
|
||||
if previous.origin == "a":
|
||||
local_lines = previous_lines + local_lines
|
||||
else:
|
||||
remote_lines = previous_lines + remote_lines
|
||||
|
||||
chunks.append(
|
||||
MergeChunk(
|
||||
type="conflict",
|
||||
@@ -144,16 +155,11 @@ def _merge_chunks(
|
||||
)
|
||||
)
|
||||
else:
|
||||
if kind in ("unchanged", "same", "a", "b"):
|
||||
lines = group[1]
|
||||
chunks.append(
|
||||
MergeChunk(
|
||||
type="normal",
|
||||
text=playlist_to_text(lines),
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unsupported merge chunk type: {kind}")
|
||||
lines = payload[0]
|
||||
if not lines:
|
||||
continue
|
||||
chunk = MergeChunk(type="normal", text=playlist_to_text(lines), origin=kind)
|
||||
chunks.append(chunk)
|
||||
|
||||
return chunks
|
||||
|
||||
@@ -213,12 +219,19 @@ def merge_playlists(
|
||||
)
|
||||
|
||||
chunks = _merge_chunks(base_paths, local_paths, remote_paths)
|
||||
has_conflict = any(chunk.type == "conflict" for chunk in chunks)
|
||||
|
||||
merged_lines: list[str] = []
|
||||
conflicts: list[dict] = []
|
||||
|
||||
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 = {
|
||||
|
||||
Reference in New Issue
Block a user