@@ -365,25 +365,31 @@ def apply_pull_changes(self, changes, temp_dir):
365
365
# special care is needed for geodiff files
366
366
if self .is_versioned_file (path ) and k == 'updated' :
367
367
if path in modified :
368
+ f_server_backup = self .fpath (f'{ path } -server_backup' , temp_dir )
368
369
server_diff = self .fpath (f'{ path } -server_diff' , temp_dir ) # single origin diff from 'diffs' for use in rebase
369
370
rebased_diff = self .fpath (f'{ path } -rebased' , temp_dir )
370
- patchedfile = self .fpath (f'{ path } -patched' , temp_dir ) # patched server version with local changes
371
- changeset = self .fpath (f'{ path } -local_diff' , temp_dir ) # final changeset to be potentially committed
371
+ shutil .copy (src , f_server_backup ) # temporary backup of file pulled from server for test and recovery
372
372
try :
373
373
self .geodiff .create_changeset (basefile , src , server_diff )
374
374
self .geodiff .create_rebased_changeset (basefile , dest , server_diff , rebased_diff )
375
- self .geodiff .apply_changeset (src , patchedfile , rebased_diff )
376
- self .geodiff .create_changeset (src , patchedfile , changeset )
377
- shutil .copy (src , basefile )
378
- shutil .copy (patchedfile , dest )
375
+ # update file with rebased_diff to contain both server and local changes
376
+ self .geodiff .apply_changeset (src , rebased_diff )
377
+ # try to create final changeset to be potentially committed in push
378
+ changeset = self .fpath (f'{ path } -local_diff' , temp_dir )
379
+ self .geodiff .create_changeset (f_server_backup , src , changeset )
380
+ # we are happy with rebase, prepare 'live' versions of files
381
+ shutil .copy (f_server_backup , basefile )
382
+ shutil .copy (src , dest )
379
383
except (pygeodiff .GeoDiffLibError , pygeodiff .GeoDiffLibConflictError ):
380
- # it would not be possible to commit local changes, create new conflict file instead
384
+ # it would not be possible to commit local changes
385
+ # local changes will end up in new conflict file
386
+ # for original file server wins
381
387
conflict = self .backup_file (path )
382
388
conflicts .append (conflict )
383
- shutil .copy (src , dest )
384
- shutil .copy (src , basefile )
389
+ shutil .copy (f_server_backup , dest )
390
+ shutil .copy (f_server_backup , basefile )
385
391
else :
386
- # just use already updated tmp_basefile to update project file and its basefile
392
+ # just use server version of file to update both project file and its basefile
387
393
shutil .copy (src , dest )
388
394
shutil .copy (src , basefile )
389
395
else :
@@ -432,10 +438,8 @@ def apply_push_changes(self, changes):
432
438
elif k == 'updated' :
433
439
# better to apply diff to previous basefile to avoid issues with geodiff tmp files
434
440
changeset = self .fpath_meta (item ['diff' ]['path' ])
435
- patchedfile = self .apply_diffs (basefile , [changeset ])
436
- if patchedfile :
437
- move_file (patchedfile , basefile )
438
- else :
441
+ patch_error = self .apply_diffs (basefile , [changeset ])
442
+ if patch_error :
439
443
# in case of local sync issues it is safier to remove basefile, next time it will be downloaded from server
440
444
os .remove (basefile )
441
445
else :
@@ -464,29 +468,26 @@ def backup_file(self, file):
464
468
def apply_diffs (self , basefile , diffs ):
465
469
"""
466
470
Helper function to update content of geodiff file using list of diffs.
471
+ Input file will be overwritten (make sure to create backup if needed).
467
472
468
473
:param basefile: abs path to file to be updated
469
474
:type basefile: str
470
475
:param diffs: list of abs paths to geodiff changeset files
471
476
:type diffs: list[str]
472
- :returns: abs path of created patched file
477
+ :returns: error message if diffs were not successfully applied or None
473
478
:rtype: str
474
479
"""
480
+ error = None
475
481
if not self .is_versioned_file (basefile ):
476
- return
482
+ return error
477
483
478
- patchedfile = None
479
484
for index , diff in enumerate (diffs ):
480
- patchedfile = f'{ basefile } -patched-{ index } '
481
485
try :
482
- self .geodiff .apply_changeset (basefile , patchedfile , diff )
483
- except (pygeodiff .GeoDiffLibError , pygeodiff .GeoDiffLibConflictError ):
484
- return
485
- previous = f'{ basefile } -patched-{ index - 1 } '
486
- if os .path .exists (previous ):
487
- os .remove (previous )
488
- basefile = patchedfile
489
- return patchedfile
486
+ self .geodiff .apply_changeset (basefile , diff )
487
+ except (pygeodiff .GeoDiffLibError , pygeodiff .GeoDiffLibConflictError ) as e :
488
+ error = str (e )
489
+ break
490
+ return error
490
491
491
492
492
493
def decode_token_data (token ):
@@ -924,16 +925,17 @@ def pull_project(self, directory, parallel=True):
924
925
continue
925
926
file ['version' ] = server_info ['version' ]
926
927
basefile = mp .fpath_meta (file ['path' ])
927
- if not os .path .exists (basefile ):
928
- self ._download_file (project_path , file , temp_dir , parallel , diff_only = False )
929
-
930
- diffs = [mp .fpath (f , temp_dir ) for f in file ['diffs' ]]
931
- patched_reference = mp .apply_diffs (basefile , diffs )
932
- if not patched_reference :
928
+ server_file = mp .fpath (file ["path" ], temp_dir )
929
+ if os .path .exists (basefile ):
930
+ shutil .copy (basefile , server_file )
931
+ diffs = [mp .fpath (f , temp_dir ) for f in file ['diffs' ]]
932
+ patch_error = mp .apply_diffs (server_file , diffs )
933
+ if patch_error :
934
+ # we can't use diffs, overwrite with full version of file fetched from server
935
+ self ._download_file (project_path , file , temp_dir , parallel , diff_only = False )
936
+ else :
933
937
self ._download_file (project_path , file , temp_dir , parallel , diff_only = False )
934
938
935
- move_file (patched_reference , mp .fpath (file ["path" ], temp_dir ))
936
-
937
939
conflicts = mp .apply_pull_changes (pull_changes , temp_dir )
938
940
mp .metadata = {
939
941
'name' : project_path ,
0 commit comments