@@ -134,6 +134,22 @@ def is_versioned_file(self, file):
134134 f_extension = os .path .splitext (file )[1 ]
135135 return f_extension in diff_extensions
136136
137+ def is_gpkg_open (self , path ):
138+ """
139+ Check whether geopackage file is open (and wal file exists)
140+
141+ :param path: absolute path of file on disk
142+ :type path: str
143+ :returns: whether file is open
144+ :rtype: bool
145+ """
146+ f_extension = os .path .splitext (path )[1 ]
147+ if f_extension != '.gpkg' :
148+ return False
149+ if os .path .exists (f'{ path } -wal' ) and os .path .exists (f'{ path } -shm' ):
150+ return True
151+ return False
152+
137153 def ignore_file (self , file ):
138154 """
139155 Helper function for blacklisting certain types of files.
@@ -165,8 +181,6 @@ def inspect_files(self):
165181 for file in files :
166182 if self .ignore_file (file ):
167183 continue
168- if "gpkg" in file :
169- do_sqlite_checkpoint (os .path .join (root , file ))
170184
171185 abs_path = os .path .abspath (os .path .join (root , file ))
172186 rel_path = os .path .relpath (abs_path , start = self .dir )
@@ -225,7 +239,8 @@ def compare_file_sets(self, origin, current):
225239 path = f ["path" ]
226240 if path not in origin_map :
227241 continue
228- if f ["checksum" ] == origin_map [path ]["checksum" ]:
242+ # with open WAL files we don't know yet, better to mark file as updated
243+ if not self .is_gpkg_open (self .fpath (path )) and f ["checksum" ] == origin_map [path ]["checksum" ]:
229244 continue
230245 f ["origin_checksum" ] = origin_map [path ]["checksum" ]
231246 updated .append (f )
@@ -301,13 +316,12 @@ def get_push_changes(self):
301316 :rtype: dict
302317 """
303318 changes = self .compare_file_sets (self .metadata ['files' ], self .inspect_files ())
304- # do checkpoint to push changes from wal file to gpkg if new file
305- for file in changes ['added' ]:
306- if ".gpkg" in file ["path" ]:
307- do_sqlite_checkpoint (self .fpath (file ["path" ]))
308- file ["checksum" ] = generate_checksum (self .fpath (file ["path" ]))
309-
319+ # do checkpoint to push changes from wal file to gpkg
310320 for file in changes ['added' ] + changes ['updated' ]:
321+ size , checksum = do_sqlite_checkpoint (self .fpath (file ["path" ]))
322+ if size and checksum :
323+ file ["size" ] = size
324+ file ["checksum" ] = checksum
311325 file ['chunks' ] = [str (uuid .uuid4 ()) for i in range (math .ceil (file ["size" ] / UPLOAD_CHUNK_SIZE ))]
312326
313327 if not self .geodiff :
@@ -320,8 +334,9 @@ def get_push_changes(self):
320334 if not self .is_versioned_file (path ):
321335 continue
322336
337+ # we use geodiff to check if we can push only diff files
323338 current_file = self .fpath (path )
324- origin_file = self .fpath (path , self . meta_dir )
339+ origin_file = self .fpath_meta (path )
325340 diff_id = str (uuid .uuid4 ())
326341 diff_name = path + '-diff-' + diff_id
327342 diff_file = self .fpath_meta (diff_name )
@@ -341,11 +356,8 @@ def get_push_changes(self):
341356 else :
342357 not_updated .append (file )
343358 except (pygeodiff .GeoDiffLibError , pygeodiff .GeoDiffLibConflictError ) as e :
344- # do checkpoint to push changes from wal file to gpkg if create changeset failed
345- do_sqlite_checkpoint (self .fpath (file ["path" ]))
346- file ["checksum" ] = generate_checksum (self .fpath (file ["path" ]))
347- file ["size" ] = os .path .getsize (self .fpath (file ["path" ]))
348- file ['chunks' ] = [str (uuid .uuid4 ()) for i in range (math .ceil (file ["size" ] / UPLOAD_CHUNK_SIZE ))]
359+ # changes from wal file already committed
360+ pass
349361
350362 changes ['updated' ] = [f for f in changes ['updated' ] if f not in not_updated ]
351363 return changes
@@ -490,15 +502,16 @@ def apply_push_changes(self, changes):
490502 elif k == 'added' :
491503 shutil .copy (self .fpath (path ), basefile )
492504 elif k == 'updated' :
493- # in case for geopackage cannot be created diff
505+ # in case for geopackage cannot be created diff (e.g. forced update with committed changes from wal file)
494506 if "diff" not in item :
495- continue
496- # better to apply diff to previous basefile to avoid issues with geodiff tmp files
497- changeset = self .fpath_meta (item ['diff' ]['path' ])
498- patch_error = self .apply_diffs (basefile , [changeset ])
499- if patch_error :
500- # in case of local sync issues it is safier to remove basefile, next time it will be downloaded from server
501- os .remove (basefile )
507+ shutil .copy (self .fpath (path ), basefile )
508+ else :
509+ # better to apply diff to previous basefile to avoid issues with geodiff tmp files
510+ changeset = self .fpath_meta (item ['diff' ]['path' ])
511+ patch_error = self .apply_diffs (basefile , [changeset ])
512+ if patch_error :
513+ # in case of local sync issues it is safier to remove basefile, next time it will be downloaded from server
514+ os .remove (basefile )
502515 else :
503516 pass
504517
@@ -1090,6 +1103,7 @@ def _download_file(self, project_path, file, directory, parallel=True, diff_only
10901103 }
10911104 file_dir = os .path .dirname (os .path .normpath (os .path .join (directory , file ['path' ])))
10921105 basename = os .path .basename (file ['diff' ]['path' ]) if diff_only else os .path .basename (file ['path' ])
1106+ expected_size = file ['diff' ]['size' ] if diff_only else file ['size' ]
10931107
10941108 if file ['size' ] == 0 :
10951109 os .makedirs (file_dir , exist_ok = True )
@@ -1130,7 +1144,7 @@ def download_file_part(part):
11301144 shutil .copyfileobj (chunk , final )
11311145 os .remove (file_part )
11321146
1133- if os .path .getsize (os .path .join (file_dir , basename )) != file [ 'size' ] :
1147+ if os .path .getsize (os .path .join (file_dir , basename )) != expected_size :
11341148 os .remove (os .path .join (file_dir , basename ))
11351149 raise ClientError (f'Download of file { basename } failed. Please try it again.' )
11361150
0 commit comments