Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"""

import os
import sys
import traceback
import click

from mergin import (
Expand Down Expand Up @@ -63,6 +65,13 @@ def _init_client():
return MerginClient(url, auth_token='Bearer {}'.format(auth_token))


def _print_unhandled_exception():
""" Outputs details of an unhandled exception that is being handled right now """
click.secho("Unhandled exception!", fg='red')
for line in traceback.format_exception(*sys.exc_info()):
click.echo(line)


@click.group()
def cli():
pass
Expand Down Expand Up @@ -99,7 +108,7 @@ def init(project, directory, public):
c.create_project(project, directory, is_public=public)
click.echo('Done')
except Exception as e:
click.secho(str(e), fg='red')
_print_unhandled_exception()


@cli.command()
Expand Down Expand Up @@ -145,7 +154,7 @@ def download(project, directory):
print("Cancelling...")
download_project_cancel(job)
except Exception as e:
click.secho(str(e), fg='red')
_print_unhandled_exception()


def num_version(name):
Expand Down Expand Up @@ -201,7 +210,7 @@ def push():
print("Cancelling...")
push_project_cancel(job)
except Exception as e:
click.secho(str(e), fg='red')
_print_unhandled_exception()


@cli.command()
Expand Down Expand Up @@ -236,7 +245,7 @@ def pull():
print("Cancelling...")
pull_project_cancel(job)
except Exception as e:
click.secho(str(e), fg='red')
_print_unhandled_exception()


@cli.command()
Expand Down Expand Up @@ -281,7 +290,7 @@ def remove(project):
shutil.rmtree(os.path.join(os.getcwd()))
click.echo('Done')
except Exception as e:
click.secho(str(e), fg='red')
_print_unhandled_exception()


if __name__ == '__main__':
Expand Down
3 changes: 3 additions & 0 deletions mergin/client_pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ def pull_project_async(mc, directory):
# The basefile does not exist for some reason. This should not happen normally (maybe user removed the file
# or we removed it within previous pull because we failed to apply patch the older version for some reason).
# But it's not a problem - we will download the newest version and we're sorted.
file_path = file['path']
mp.log.info(f"missing base file for {file_path} -> going to download it (version {server_version})")
file['version'] = server_version
items = _download_items(file, temp_dir, diff_only=False)
dest_file_path = mp.fpath(file["path"], temp_dir)
#dest_file_path = os.path.join(os.path.dirname(os.path.normpath(os.path.join(temp_dir, file['path']))), os.path.basename(file['path']))
Expand Down
33 changes: 33 additions & 0 deletions mergin/test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,36 @@ def test_new_project_sync(mc):
mp = MerginProject(project_dir)
local_changes = mp.get_push_changes()
assert not local_changes["added"] and not local_changes["removed"] and not local_changes["updated"]


def test_missing_basefile_pull(mc):
""" Test pull of a project where basefile of a .gpkg is missing for some reason
(it should gracefully handle it by downloading the missing basefile)
"""

test_project = 'test_missing_basefile_pull'
project = API_USER + '/' + test_project
project_dir = os.path.join(TMP_DIR, test_project) # primary project dir for updates
project_dir_2 = os.path.join(TMP_DIR, test_project + '_2') # concurrent project dir
test_data_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), test_project)

cleanup(mc, project, [project_dir, project_dir_2])
# create remote project
shutil.copytree(test_data_dir, project_dir)
mc.create_project_and_push(test_project, project_dir)

# update our gpkg in a different directory
mc.download_project(project, project_dir_2)
shutil.copy(os.path.join(TEST_DATA_DIR, "inserted_1_A.gpkg"), os.path.join(project_dir_2, "base.gpkg"))
mc.pull_project(project_dir_2)
mc.push_project(project_dir_2)

# make some other local change
shutil.copy(os.path.join(TEST_DATA_DIR, "inserted_1_B.gpkg"), os.path.join(project_dir, "base.gpkg"))

# remove the basefile to simulate the issue
os.remove(os.path.join(project_dir, '.mergin', 'base.gpkg'))

# try to sync again -- it should not crash
mc.pull_project(project_dir)
mc.push_project(project_dir)
Binary file not shown.
Empty file.