Skip to content

Commit a9986b1

Browse files
committed
Add cli command to trigger checkpoints caching
1 parent 2938e21 commit a9986b1

File tree

3 files changed

+128
-4
lines changed

3 files changed

+128
-4
lines changed

server/mergin/sync/commands.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,50 @@ def remove(project_name):
127127
project.removed_by = None
128128
db.session.commit()
129129
click.secho("Project removed", fg="green")
130+
131+
@project.command()
132+
@click.argument("project-name", callback=normalize_input(lowercase=False))
133+
@click.option("--since", type=int, required=False)
134+
@click.option("--to", type=int, required=False)
135+
def create_checkpoint(project_name, since=None, to=None):
136+
"""Create project delta checkpoint, corresponding lower checkpoints and merged diffs for project"""
137+
ws, name = split_project_path(project_name)
138+
workspace = current_app.ws_handler.get_by_name(ws)
139+
if not workspace:
140+
click.secho("ERROR: Workspace does not exist", fg="red", err=True)
141+
sys.exit(1)
142+
project = (
143+
Project.query.filter_by(workspace_id=workspace.id, name=name)
144+
.filter(Project.storage_params.isnot(None))
145+
.first()
146+
)
147+
if not project:
148+
click.secho("ERROR: Project does not exist", fg="red", err=True)
149+
sys.exit(1)
150+
151+
since = since if since is not None else 0
152+
to = to if to is not None else project.latest_version
153+
if since < 0 or to < 1:
154+
click.secho(
155+
"ERROR: Invalid version number, minimum version for 'since' is 0 and minimum version for 'to' is 1",
156+
fg="red",
157+
err=True,
158+
)
159+
sys.exit(1)
160+
161+
if to > project.latest_version:
162+
click.secho(
163+
"ERROR: 'to' version exceeds latest project version", fg="red", err=True
164+
)
165+
sys.exit(1)
166+
167+
if since >= to:
168+
click.secho(
169+
"ERROR: 'since' version must be less than 'to' version",
170+
fg="red",
171+
err=True,
172+
)
173+
sys.exit(1)
174+
175+
project.get_delta_changes(since, to)
176+
click.secho("Project checkpoint(s) created", fg="green")

server/mergin/tests/test_cli.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from mergin.auth.models import User
1414
from mergin.commands import _check_permissions, _check_celery
1515
from mergin.stats.models import MerginInfo
16-
from mergin.sync.models import Project, ProjectVersion
16+
from mergin.sync.models import FileDiff, Project, ProjectVersion, ProjectVersionDelta
1717
from mergin.tests import (
1818
test_project,
1919
test_workspace_id,
@@ -545,3 +545,70 @@ def test_check_celery(mock_ping, ping, result, output, capsys):
545545
out, err = capsys.readouterr() # capture what was echoed to stdout
546546
assert ("Error: " not in out) == result
547547
assert output in out
548+
549+
550+
create_project_checkpoint_data = [
551+
(
552+
f"{test_workspace_name}/non-existing",
553+
0,
554+
1,
555+
"ERROR: Project does not exist",
556+
),
557+
(
558+
f"{test_workspace_name}/{test_project}",
559+
4,
560+
1,
561+
"ERROR: 'since' version must be less than 'to' version",
562+
),
563+
(
564+
f"{test_workspace_name}/{test_project}",
565+
0,
566+
100,
567+
"ERROR: 'to' version exceeds latest project version",
568+
),
569+
(
570+
f"{test_workspace_name}/{test_project}",
571+
0,
572+
0,
573+
"ERROR: Invalid version number, minimum version for 'since' is 0 and minimum version for 'to' is 1",
574+
),
575+
(
576+
f"{test_workspace_name}/{test_project}",
577+
0,
578+
4,
579+
"Project checkpoint(s) created",
580+
),
581+
(
582+
f"{test_workspace_name}/{test_project}",
583+
None,
584+
None,
585+
"Project checkpoint(s) created",
586+
),
587+
]
588+
589+
590+
@pytest.mark.parametrize("project_name,since,to,output", create_project_checkpoint_data)
591+
def test_create_checkpoint(runner, project_name, since, to, output, diff_project):
592+
"""Test 'project remove' command"""
593+
ProjectVersionDelta.query.filter_by(project_id=diff_project.id).filter(
594+
ProjectVersionDelta.rank > 0
595+
).delete()
596+
db.session.commit()
597+
598+
remove = runner.invoke(
599+
args=[
600+
"project",
601+
"create-checkpoint",
602+
project_name,
603+
"--since",
604+
since,
605+
"--to",
606+
to,
607+
]
608+
)
609+
assert output in remove.output
610+
checkpoints = ProjectVersionDelta.query.filter(ProjectVersionDelta.rank > 0).count()
611+
if remove.exit_code == 0:
612+
assert checkpoints > 0
613+
else:
614+
assert checkpoints == 0

server/mergin/tests/test_public_api_v2.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,12 +606,22 @@ def test_project_version_delta_changes(client, diff_project: Project):
606606
assert response.status_code == 200
607607

608608
# remove intermediate deltas and assert they would be recreated if needed for higher ranks
609-
ProjectVersionDelta.query.filter(ProjectVersionDelta.rank > 0).delete()
609+
ProjectVersionDelta.query.filter_by(project_id=diff_project.id).filter(
610+
ProjectVersionDelta.rank > 0
611+
).delete()
610612
db.session.commit()
611613
# v1-v16 would be created from v1-v4, v5-v8 and v9-v12 and 4 individual deltas
612614
delta = diff_project.get_delta_changes(0, diff_project.latest_version)
613-
assert ProjectVersionDelta.query.filter_by(rank=1).count() == 3
614-
assert ProjectVersionDelta.query.filter_by(rank=2, version=16).count() == 1
615+
assert (
616+
ProjectVersionDelta.query.filter_by(project_id=diff_project.id, rank=1).count()
617+
== 3
618+
)
619+
assert (
620+
ProjectVersionDelta.query.filter_by(
621+
project_id=diff_project.id, rank=2, version=16
622+
).count()
623+
== 1
624+
)
615625

616626

617627
push_data = [

0 commit comments

Comments
 (0)