Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion mergin/client_pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,10 @@ def pull_project_async(mc, directory) -> Optional[PullJob]:
# find corresponding local delta item
local_item = next((i for i in local_delta if i.path == change.path), None)
local_item_change = local_item.type if local_item else None
local_item_checksum = local_item.checksum if local_item else None

# compare server and local changes to decide what to do in pull
pull_action_type = mp.get_pull_action(change.type, local_item_change)
pull_action_type = mp.get_pull_action(change.type, local_item_change, change.checksum, local_item_checksum)
if not pull_action_type:
continue # no action needed

Expand Down
16 changes: 13 additions & 3 deletions mergin/merginproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,11 @@ def get_pull_delta(self, server_files: List[Dict], server_version: str) -> Proje
return ProjectDelta(to_version=server_version, changes=result)

def get_pull_action(
self, server_change: DeltaChangeType, local_change: Optional[DeltaChangeType] = None
self,
server_change: DeltaChangeType,
local_change: Optional[DeltaChangeType] = None,
server_checksum: Optional[str] = None,
local_checksum: Optional[str] = None,
) -> Optional[PullActionType]:
"""
Determine pull actions for files by comparing server_change and local_change.
Expand All @@ -520,11 +524,17 @@ def get_pull_action(
self.log.critical(f"Invalid combination of changes: server {server_change}, local {local_change}")
raise ClientError(f"Invalid combination of changes: server {server_change}, local {local_change}")

checksum_conflict = server_checksum != local_checksum if server_checksum and local_checksum else False

pull_action_map = {
(DeltaChangeType.CREATE, None): PullActionType.COPY,
(DeltaChangeType.CREATE, DeltaChangeType.CREATE): PullActionType.COPY_CONFLICT,
(DeltaChangeType.CREATE, DeltaChangeType.CREATE): (
PullActionType.COPY_CONFLICT if checksum_conflict else None
),
(DeltaChangeType.UPDATE, None): PullActionType.COPY,
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE): PullActionType.COPY_CONFLICT,
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE): (
PullActionType.COPY_CONFLICT if checksum_conflict else None
),
(DeltaChangeType.UPDATE, DeltaChangeType.DELETE): PullActionType.COPY,
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE_DIFF): PullActionType.COPY_CONFLICT,
(DeltaChangeType.UPDATE, DeltaChangeType.CREATE): PullActionType.COPY_CONFLICT,
Expand Down
40 changes: 21 additions & 19 deletions mergin/test/test_mergin_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,29 @@ def test_get_pull_action_valid():
with tempfile.TemporaryDirectory() as tmp_dir:
mp = MerginProject(tmp_dir)

# Test cases: (server_change, local_change, expected_action)
# Test cases: (server_change, local_change, server_checksum, local_checksum, expected_action)
test_cases = [
(DeltaChangeType.CREATE, None, PullActionType.COPY),
(DeltaChangeType.CREATE, DeltaChangeType.CREATE, PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE, None, PullActionType.COPY),
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE, PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE, DeltaChangeType.DELETE, PullActionType.COPY),
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE_DIFF, PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE, DeltaChangeType.CREATE, PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE_DIFF, None, PullActionType.APPLY_DIFF_NO_REBASE),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.UPDATE, PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.DELETE, PullActionType.COPY),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.UPDATE_DIFF, PullActionType.APPLY_DIFF_REBASE),
(DeltaChangeType.DELETE, None, PullActionType.DELETE),
(DeltaChangeType.DELETE, DeltaChangeType.UPDATE, None),
(DeltaChangeType.DELETE, DeltaChangeType.DELETE, None),
(DeltaChangeType.DELETE, DeltaChangeType.UPDATE_DIFF, None),
(DeltaChangeType.CREATE, None, None, None, PullActionType.COPY),
(DeltaChangeType.CREATE, DeltaChangeType.CREATE, "c1", "c2", PullActionType.COPY_CONFLICT),
(DeltaChangeType.CREATE, DeltaChangeType.CREATE, "c1", "c1", None),
(DeltaChangeType.UPDATE, None, None, None, PullActionType.COPY),
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE, "c1", "c2", PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE, "c1", "c1", None),
(DeltaChangeType.UPDATE, DeltaChangeType.DELETE, "c1", "c2", PullActionType.COPY),
(DeltaChangeType.UPDATE, DeltaChangeType.UPDATE_DIFF, "c1", "c2", PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE, DeltaChangeType.CREATE, "c1", "c2", PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE_DIFF, None, "c1", "c2", PullActionType.APPLY_DIFF_NO_REBASE),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.UPDATE, "c1", "c2", PullActionType.COPY_CONFLICT),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.DELETE, "c1", "c2", PullActionType.COPY),
(DeltaChangeType.UPDATE_DIFF, DeltaChangeType.UPDATE_DIFF, "c1", "c2", PullActionType.APPLY_DIFF_REBASE),
(DeltaChangeType.DELETE, None, "c1", "c2", PullActionType.DELETE),
(DeltaChangeType.DELETE, DeltaChangeType.UPDATE, None, None, None),
(DeltaChangeType.DELETE, DeltaChangeType.DELETE, None, None, None),
(DeltaChangeType.DELETE, DeltaChangeType.UPDATE_DIFF, None, None, None),
]

for server_change, local_change, expected_action in test_cases:
action = mp.get_pull_action(server_change, local_change)
for server_change, local_change, server_checksum, local_checksum, expected_action in test_cases:
action = mp.get_pull_action(server_change, local_change, server_checksum, local_checksum)
assert (
action == expected_action
), f"Failed for {server_change}, {local_change}. Expected {expected_action}, got {action}"
Expand All @@ -123,7 +125,7 @@ def test_get_pull_action_fatal():

for server_change, local_change in fatal_cases:
with pytest.raises(ClientError, match="Invalid combination of changes"):
mp.get_pull_action(server_change, local_change)
mp.get_pull_action(server_change, local_change, None, None)


def test_get_pull_delta():
Expand Down
Loading