Skip to content

Commit 2c9bdad

Browse files
authored
Merge pull request #520 from MerginMaps/cache-versions
Checkpoints introduction for version changes
2 parents c6b60ce + 3685e43 commit 2c9bdad

File tree

8 files changed

+1111
-9
lines changed

8 files changed

+1111
-9
lines changed

server/mergin/sync/files.py

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
import datetime
55
from enum import Enum
66
import os
7-
from dataclasses import dataclass
7+
from dataclasses import dataclass, field
88
from typing import Optional, List
99
import uuid
1010
from flask import current_app
11-
from marshmallow import ValidationError, fields, EXCLUDE, post_dump, validates_schema
11+
from marshmallow import (
12+
ValidationError,
13+
fields,
14+
EXCLUDE,
15+
post_dump,
16+
validates_schema,
17+
post_load,
18+
)
1219
from pathvalidate import sanitize_filename
1320

1421
from .utils import (
@@ -234,3 +241,113 @@ def patch_field(self, data, **kwargs):
234241
if not data.get("diff"):
235242
data.pop("diff")
236243
return data
244+
245+
246+
@dataclass
247+
class DeltaDiffFile:
248+
"""Diff file path in diffs list"""
249+
250+
path: str
251+
252+
253+
class DeltaChangeDiffFileSchema(ma.Schema):
254+
"""Schema for diff file path in diffs list"""
255+
256+
path = fields.String(required=True)
257+
258+
259+
@dataclass
260+
class DeltaChangeBase(File):
261+
"""Base class for changes stored in json list or returned from delta endpoint"""
262+
263+
change: PushChangeType
264+
version: int
265+
266+
267+
@dataclass
268+
class DeltaChangeMerged(DeltaChangeBase):
269+
"""Delta item with merged diffs to list of multiple diff files"""
270+
271+
diffs: List[DeltaDiffFile] = field(default_factory=list)
272+
273+
def to_data_delta(self):
274+
"""Convert DeltaMerged to DeltaData with single diff"""
275+
result = DeltaChange(
276+
path=self.path,
277+
size=self.size,
278+
checksum=self.checksum,
279+
change=self.change,
280+
version=self.version,
281+
)
282+
if self.diffs:
283+
result.diff = self.diffs[0].path
284+
return result
285+
286+
287+
@dataclass
288+
class DeltaChange(DeltaChangeBase):
289+
"""Change items stored in database as list of this item with single diff file"""
290+
291+
diff: Optional[str] = None
292+
293+
def to_merged(self) -> DeltaChangeMerged:
294+
"""Convert to DeltaMerged with multiple diffs"""
295+
result = DeltaChangeMerged(
296+
path=self.path,
297+
size=self.size,
298+
checksum=self.checksum,
299+
change=self.change,
300+
version=self.version,
301+
)
302+
if self.diff:
303+
result.diffs = [DeltaDiffFile(path=self.diff)]
304+
return result
305+
306+
307+
class DeltaChangeBaseSchema(ma.Schema):
308+
"""Base schema for delta json and response from delta endpoint"""
309+
310+
path = fields.String(required=True)
311+
size = fields.Integer(required=True)
312+
checksum = fields.String(required=True)
313+
version = fields.Integer(required=True)
314+
change = fields.Enum(PushChangeType, by_value=True, required=True)
315+
316+
317+
class DeltaChangeSchema(DeltaChangeBaseSchema):
318+
"""Schema for change data in changes column"""
319+
320+
diff = fields.String(required=False)
321+
322+
@post_load
323+
def make_object(self, data, **kwargs):
324+
return DeltaChange(**data)
325+
326+
@post_dump
327+
def patch_field(self, data, **kwargs):
328+
# drop 'diff' key entirely if empty or None as database would expect
329+
if not data.get("diff"):
330+
data.pop("diff", None)
331+
return data
332+
333+
334+
class DeltaChangeItemSchema(DeltaChangeBaseSchema):
335+
"""Schema for delta changes response"""
336+
337+
diffs = fields.List(fields.Nested(DeltaChangeDiffFileSchema()))
338+
339+
@post_dump
340+
def patch_field(self, data, **kwargs):
341+
# drop 'diffs' key entirely if empty or None as clients would expect
342+
if not data.get("diffs"):
343+
data.pop("diffs", None)
344+
return data
345+
346+
347+
class DeltaChangeRespSchema(ma.Schema):
348+
"""Schema for list of delta changes wrapped in items field"""
349+
350+
items = fields.List(fields.Nested(DeltaChangeItemSchema()))
351+
352+
class Meta:
353+
unknown = EXCLUDE

0 commit comments

Comments
 (0)