You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: server/mergin/sync/models.py
+45-27Lines changed: 45 additions & 27 deletions
Original file line number
Diff line number
Diff line change
@@ -69,10 +69,12 @@ class ChangeComparisonAction(Enum):
69
69
"""Actions to take when comparing two changes"""
70
70
71
71
REPLACE="replace"
72
-
DELETE="delete"
73
-
UPDATE="update"
74
-
UPDATE_DIFF="update_diff"
72
+
UPDATE_METADATA="update_metadata"# Update metadata and keep diffs (used for update + update sequence)
73
+
REPLACE_DIFFS="replace_diffs"# Replace diffs but keep metadata (used for update + update sequence when only diffs are changed)
75
74
EXCLUDE="exclude"# Return None to exclude the file
75
+
FORCE_UPDATE= (
76
+
"force_update"# Force update even if it looks like a delete + create sequence
77
+
)
76
78
77
79
78
80
classProject(db.Model):
@@ -1089,9 +1091,11 @@ def merge_changes(
1089
1091
continue
1090
1092
1091
1093
# Compare and merge with previous change for this file
1092
-
can_delete=pathinupdating_files
1094
+
# If file did not exist before this range (first change was CREATE),
1095
+
# a CREATE+DELETE sequence is transparent — exclude the pair.
1096
+
exclude_delete=pathnotinupdating_files
1093
1097
new_change=ProjectVersionDelta._compare_changes(
1094
-
result[path], current, can_delete
1098
+
result[path], current, exclude_delete
1095
1099
)
1096
1100
1097
1101
# Update result (or remove if no change is detected)
@@ -1106,45 +1110,54 @@ def merge_changes(
1106
1110
def_compare_changes(
1107
1111
previous: DeltaChangeMerged,
1108
1112
new: DeltaChangeMerged,
1109
-
prevent_delete_change: bool,
1113
+
exclude_delete: bool,
1110
1114
) ->Optional[DeltaChangeMerged]:
1111
1115
"""
1112
1116
Compare and merge two changes for the same file.
1113
1117
1114
1118
Args:
1115
1119
previous: Previously accumulated change
1116
1120
new: New change to compare
1117
-
prevent_delete_change: Whether the change can be deleted when resolving create+delete sequences
1121
+
exclude_delete: If True, a CREATE+DELETE pair is excluded (file was
1122
+
created and deleted within the same range — no net effect).
1123
+
If False, the DELETE is kept (file existed before this range
1124
+
and the client needs to remove it).
1118
1125
1119
1126
Returns:
1120
1127
Merged change or None if file should be excluded
1121
1128
"""
1122
1129
1123
1130
# Map change type pairs to actions
1124
1131
action_map= {
1125
-
# create + delete = file is transparent for current changes -> delete it
1132
+
# CREATE + DELETE: if file didn't exist before (exclude_delete=True),
1133
+
# the pair cancels out (EXCLUDE). If it did exist, keep the DELETE
1134
+
# so the client removes its local copy.
1126
1135
(
1127
1136
PushChangeType.CREATE,
1128
1137
PushChangeType.DELETE,
1129
-
): ChangeComparisonAction.DELETE,
1138
+
): (
1139
+
ChangeComparisonAction.EXCLUDE
1140
+
ifexclude_delete
1141
+
elseChangeComparisonAction.REPLACE
1142
+
),
1130
1143
# create + update = create with updated info
1131
1144
(
1132
1145
PushChangeType.CREATE,
1133
1146
PushChangeType.UPDATE,
1134
-
): ChangeComparisonAction.UPDATE,
1147
+
): ChangeComparisonAction.UPDATE_METADATA,
1135
1148
(
1136
1149
PushChangeType.CREATE,
1137
1150
PushChangeType.UPDATE_DIFF,
1138
-
): ChangeComparisonAction.UPDATE,
1151
+
): ChangeComparisonAction.UPDATE_METADATA,
1139
1152
(
1140
1153
PushChangeType.CREATE,
1141
1154
PushChangeType.CREATE,
1142
-
): ChangeComparisonAction.EXCLUDE,
1155
+
): ChangeComparisonAction.REPLACE,
1143
1156
# update + update_diff = update with latest info
1144
1157
(
1145
1158
PushChangeType.UPDATE,
1146
1159
PushChangeType.UPDATE_DIFF,
1147
-
): ChangeComparisonAction.UPDATE,
1160
+
): ChangeComparisonAction.UPDATE_METADATA,
1148
1161
(
1149
1162
PushChangeType.UPDATE,
1150
1163
PushChangeType.UPDATE,
@@ -1161,7 +1174,7 @@ def _compare_changes(
1161
1174
(
1162
1175
PushChangeType.UPDATE_DIFF,
1163
1176
PushChangeType.UPDATE_DIFF,
1164
-
): ChangeComparisonAction.UPDATE_DIFF,
1177
+
): ChangeComparisonAction.REPLACE_DIFFS,
1165
1178
(
1166
1179
PushChangeType.UPDATE_DIFF,
1167
1180
PushChangeType.UPDATE,
@@ -1173,44 +1186,45 @@ def _compare_changes(
1173
1186
(
1174
1187
PushChangeType.UPDATE_DIFF,
1175
1188
PushChangeType.CREATE,
1176
-
): ChangeComparisonAction.EXCLUDE,
1189
+
): ChangeComparisonAction.REPLACE,
1177
1190
(
1178
1191
PushChangeType.DELETE,
1179
1192
PushChangeType.CREATE,
1180
-
): ChangeComparisonAction.REPLACE,
1181
-
# delete + update = invalid sequence
1193
+
): ChangeComparisonAction.FORCE_UPDATE,
1194
+
# delete + update = replace it (used for multicheckpoint ranges when we want to keep file in history even if it was deleted in the middle, so we keep delete but update metadata and diffs)
0 commit comments