Skip to content

Commit 4360184

Browse files
authored
Merge pull request #583 from MerginMaps/fix-one-diff-concat
Fix for concat changes when one diff is there (not possbile to concat)
2 parents 6f81f79 + 8f2684b commit 4360184

3 files changed

Lines changed: 45 additions & 15 deletions

File tree

server/mergin/sync/models.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
PushChangeType,
3838
)
3939
from .interfaces import WorkspaceRole
40-
from .storages.disk import move_to_tmp
40+
from .storages.disk import copy_file, move_to_tmp
4141
from ..app import db
4242
from .storages import DiskStorage
4343
from .utils import (
@@ -1021,8 +1021,14 @@ def construct_checkpoint(self) -> bool:
10211021

10221022
project: Project = basefile.file.project
10231023
os.makedirs(project.storage.diffs_dir, exist_ok=True)
1024+
10241025
try:
1025-
project.storage.geodiff.concat_changes(diffs_paths, self.abs_path)
1026+
if len(diffs_paths) == 1:
1027+
# if there is only one diff, we can just copy it as a checkpoint without merging
1028+
# geodiff.concat_changes is not able to concat one diff
1029+
copy_file(diffs_paths[0], self.abs_path)
1030+
else:
1031+
project.storage.geodiff.concat_changes(diffs_paths, self.abs_path)
10261032
except (GeoDiffLibError, GeoDiffLibConflictError):
10271033
logging.error(
10281034
f"Geodiff: Failed to merge diffs for file {self.file_path_id}"

server/mergin/tests/test_public_api_v2.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def test_create_diff_checkpoint(diff_project):
261261
shutil.copy(
262262
os.path.join(diff_project.storage.project_dir, "v9", "test.gpkg"), base_gpkg
263263
)
264-
for i in range(22):
264+
for i in range(23):
265265
sql = f"UPDATE simple SET rating={i}"
266266
execute_query(base_gpkg, sql)
267267
pv = push_change(
@@ -348,6 +348,24 @@ def test_create_diff_checkpoint(diff_project):
348348
assert mock.called
349349
assert not os.path.exists(diff.abs_path)
350350

351+
# testing checkpoint with one diff only, no merging should happen, just copy the diff file
352+
individual_diffs = (
353+
FileDiff.query.filter_by(file_path_id=file_path_id, rank=0)
354+
.filter(FileDiff.version.between(33, 36))
355+
.all()
356+
)
357+
create_blank_version(diff_project) # v34
358+
create_blank_version(diff_project) # v35
359+
create_blank_version(diff_project) # v36
360+
diff = FileDiff(
361+
basefile=basefile, path=f"test.gpkg-diff-{uuid.uuid4()}", version=36, rank=1
362+
)
363+
db.session.add(diff)
364+
db.session.commit()
365+
diff.construct_checkpoint()
366+
assert os.path.exists(diff.abs_path)
367+
assert diffs_are_equal(diff.abs_path, individual_diffs[0].abs_path)
368+
351369

352370
def test_can_create_checkpoint(diff_project):
353371
"""Test if diff file checkpoint can be created"""

server/migrations/community/bd1ec73db389_create_file_diff_table.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,28 @@ def upgrade():
6262
# migrate data
6363
conn = op.get_bind()
6464
conn.execute(
65-
"""
65+
sa.text(
66+
"""
6667
WITH diffs AS (
67-
SELECT *
68-
FROM file_history
68+
SELECT *
69+
FROM file_history
6970
WHERE diff IS NOT NULL
7071
),
7172
basefiles AS (
72-
SELECT DISTINCT
73-
fh.id AS basefile_id,
73+
SELECT DISTINCT
74+
fh.id AS basefile_id,
7475
fh.file_path_id,
7576
fh.project_version_name AS basefile_version
7677
FROM diffs d
7778
LEFT OUTER JOIN file_history fh ON fh.file_path_id = d.file_path_id
78-
WHERE
79+
WHERE
7980
fh.change = ANY(ARRAY['create'::push_change_type, 'update'::push_change_type])
8081
),
8182
relevant_basefiles AS (
82-
SELECT
83-
d.id,
84-
d.project_version_name,
85-
b.basefile_id,
83+
SELECT
84+
d.id,
85+
d.project_version_name,
86+
b.basefile_id,
8687
b.basefile_version
8788
FROM diffs d
8889
LEFT OUTER JOIN basefiles b ON b.file_path_id = d.file_path_id AND b.basefile_version < d.project_version_name
@@ -104,6 +105,7 @@ def upgrade():
104105
-- it seems that some projects / files might be broken so we need to play it safe here
105106
SELECT * FROM file_diffs WHERE basefile_id IS NOT NULL;
106107
"""
108+
)
107109
)
108110

109111
op.drop_column("file_history", "diff")
@@ -123,7 +125,8 @@ def downgrade():
123125
# migrate data
124126
conn = op.get_bind()
125127
conn.execute(
126-
"""
128+
sa.text(
129+
"""
127130
UPDATE file_history fh
128131
SET diff = jsonb_build_object(
129132
'path', fd.path,
@@ -134,11 +137,13 @@ def downgrade():
134137
FROM file_diff fd
135138
WHERE fh.file_path_id = fd.file_path_id AND fh.project_version_name = fd.version AND fd.rank = 0;
136139
"""
140+
)
137141
)
138142

139143
# if there were any broken gpkg files (ommited in upgrade), let's add there a dummy diff
140144
conn.execute(
141-
"""
145+
sa.text(
146+
"""
142147
UPDATE file_history fh
143148
SET diff = jsonb_build_object(
144149
'path', 'missing-diff',
@@ -148,6 +153,7 @@ def downgrade():
148153
)
149154
WHERE fh.change = 'update_diff' AND fh.diff IS NULL;
150155
"""
156+
)
151157
)
152158

153159
# add back consistency constraint

0 commit comments

Comments
 (0)