Skip to content

Commit 9d2755a

Browse files
authored
Merge pull request #584 from MerginMaps/change-path-to-query-file
Fix subfolders geopackages diffs
2 parents 4360184 + 5b1733d commit 9d2755a

File tree

4 files changed

+63
-11
lines changed

4 files changed

+63
-11
lines changed

server/mergin/sync/models.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ def get_delta_changes(
411411
result.extend(DeltaChangeSchema(many=True).load(existing_delta.changes))
412412
continue
413413

414+
if checkpoint.rank == 0:
415+
raise ValueError(
416+
f"Missing expected checkpoint of rank 0 for version {checkpoint.end}"
417+
)
418+
414419
# If higher rank delta checkopoint does not exists we need to create it
415420
if checkpoint.rank > 0:
416421
new_checkpoint = ProjectVersionDelta.create_checkpoint(
@@ -918,6 +923,11 @@ def construct_checkpoint(self) -> bool:
918923
if os.path.exists(self.abs_path):
919924
return True
920925

926+
if self.rank == 0:
927+
raise ValueError(
928+
"Checkpoint of rank 0 should be created by user upload, cannot be constructed"
929+
)
930+
921931
# merged diffs can only be created for certain versions
922932
if self.version % LOG_BASE:
923933
return False
@@ -1245,6 +1255,11 @@ def create_checkpoint(
12451255
"""
12461256
Creates and caches new checkpoint and any required FileDiff checkpoints recursively if needed.
12471257
"""
1258+
if checkpoint.rank == 0:
1259+
raise ValueError(
1260+
f"Missing expected checkpoint of rank 0 for version {checkpoint.end}"
1261+
)
1262+
12481263
delta_range = []
12491264
# our new checkpoint will be created by adding last individual delta to previous checkpoints
12501265
expected_checkpoints = Checkpoint.get_checkpoints(
@@ -1267,7 +1282,7 @@ def create_checkpoint(
12671282
# make sure we have all components, if not, created them (recursively)
12681283
for item in expected_checkpoints:
12691284
existing_delta = existing_delta_map.get((item.rank, item.end))
1270-
if not existing_delta:
1285+
if not existing_delta and item.rank > 0:
12711286
existing_delta = cls.create_checkpoint(project_id, item)
12721287

12731288
if existing_delta:

server/mergin/sync/public_api_v2.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ paths:
280280
"404":
281281
$ref: "#/components/responses/NotFound"
282282
x-openapi-router-controller: mergin.sync.public_api_v2_controller
283-
/projects/{id}/raw/diff/{file}:
283+
/projects/{id}/raw/diff:
284284
get:
285285
tags:
286286
- project
@@ -290,7 +290,7 @@ paths:
290290
- $ref: "#/components/parameters/ProjectId"
291291
- name: file
292292
required: true
293-
in: path
293+
in: query
294294
description: File id of the diff file to download
295295
schema:
296296
type: string
@@ -443,7 +443,7 @@ paths:
443443
summary: List projects in the workspace
444444
operationId: list_workspace_projects
445445
parameters:
446-
- $ref: '#/components/parameters/WorkspaceId'
446+
- $ref: "#/components/parameters/WorkspaceId"
447447
- name: page
448448
in: query
449449
description: page number

server/mergin/sync/public_api_v2_controller.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,14 @@ def get_project_delta(id: str, since: str, to: Optional[str] = None):
457457
400,
458458
f"""The 'since' parameter must be less than or equal to the {"'to' parameter" if to_provided else 'latest project version'}""",
459459
)
460-
delta_changes = project.get_delta_changes(since_version, to_version) or []
460+
461+
try:
462+
delta_changes = project.get_delta_changes(since_version, to_version) or []
463+
except ValueError:
464+
logging.exception(
465+
f"Failed to get delta changes for project {project.id} between versions {since_version} and {to_version}"
466+
)
467+
abort(422)
461468

462469
return (
463470
DeltaChangeRespSchema().dump(

server/mergin/tests/test_public_api_v2.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ def test_file_diff_download(client, diff_project):
212212
file_path_id=gpkg_file.id, version=4, rank=0
213213
).first()
214214

215-
response = client.get(f"v2/projects/{diff_project.id}/raw/diff/{diff_file.path}")
215+
response = client.get(
216+
f"v2/projects/{diff_project.id}/raw/diff?file={diff_file.path}"
217+
)
216218
assert response.status_code == 200
217219
assert response.content_type == "application/octet-stream"
218220

@@ -231,7 +233,7 @@ def test_file_diff_download(client, diff_project):
231233
assert not os.path.exists(diff.abs_path)
232234

233235
# download merged diff with its reconstuction on the fly
234-
response = client.get(f"v2/projects/{diff_project.id}/raw/diff/{diff.path}")
236+
response = client.get(f"v2/projects/{diff_project.id}/raw/diff?file={diff.path}")
235237
assert response.status_code == 200
236238
assert response.content_type == "application/octet-stream"
237239
assert os.path.exists(diff.abs_path)
@@ -240,13 +242,39 @@ def test_file_diff_download(client, diff_project):
240242
with patch.object(FileDiff, "construct_checkpoint") as construct_checkpoint_mock:
241243
os.remove(diff.abs_path)
242244
construct_checkpoint_mock.return_value = False
243-
response = client.get(f"v2/projects/{diff_project.id}/raw/diff/{diff.path}")
245+
response = client.get(
246+
f"v2/projects/{diff_project.id}/raw/diff?file={diff.path}"
247+
)
244248
assert response.status_code == 422
245249
assert response.json["code"] == DiffDownloadError.code
246250

247-
response = client.get(f"v2/projects/{diff_project.id}/raw/diff/{diff.path}+1")
251+
response = client.get(f"v2/projects/{diff_project.id}/raw/diff?file={diff.path}+1")
248252
assert response.status_code == 404
249253

254+
subfolder_test_gpkg = os.path.join(
255+
diff_project.storage.project_dir, "test_dir", "test.gpkg"
256+
)
257+
os.makedirs(os.path.dirname(subfolder_test_gpkg), exist_ok=True)
258+
shutil.copy(
259+
os.path.join(test_project_dir, "base.gpkg"),
260+
subfolder_test_gpkg,
261+
)
262+
# shutil.copy(
263+
# test_gpkg_file,
264+
# os.path.join(diff_project.storage.project_dir, "v9", "test_dir", "test.gpkg"),
265+
# )
266+
push_change(
267+
diff_project, "added", "test_dir/test.gpkg", diff_project.storage.project_dir
268+
)
269+
sql = f"UPDATE simple SET rating={1000}"
270+
execute_query(subfolder_test_gpkg, sql)
271+
pv = push_change(
272+
diff_project, "updated", "test_dir/test.gpkg", diff_project.storage.project_dir
273+
)
274+
fd = FileDiff.query.filter_by(version=pv.name, rank=0).first()
275+
response = client.get(f"v2/projects/{diff_project.id}/raw/diff?file={fd.path}")
276+
assert response.status_code == 200
277+
250278

251279
def test_create_diff_checkpoint(diff_project):
252280
"""Test creation of diff checkpoints"""
@@ -738,7 +766,7 @@ def test_project_version_delta_changes(client, diff_project: Project):
738766

739767
# check if checkpoint will be there
740768
response = client.get(
741-
f"v2/projects/{diff_project.id}/raw/diff/{delta[0].diffs[0].id}"
769+
f"v2/projects/{diff_project.id}/raw/diff?file={delta[0].diffs[0].id}"
742770
)
743771
assert response.status_code == 200
744772

@@ -1339,7 +1367,9 @@ def test_project_pull_diffs(client, diff_project):
13391367
second_diff = delta[0]["diffs"][1]
13401368
assert first_diff["id"] == current_diffs[0].path
13411369
assert second_diff["id"] == current_diffs[1].path
1342-
response = client.get(f"v2/projects/{diff_project.id}/raw/diff/{first_diff['id']}")
1370+
response = client.get(
1371+
f"v2/projects/{diff_project.id}/raw/diff?file={first_diff['id']}"
1372+
)
13431373
assert response.status_code == 200
13441374

13451375

0 commit comments

Comments
 (0)