Skip to content

Commit 05ddd16

Browse files
varmar05wonder-sk
authored andcommitted
Add option to download older versions of project (closes #74)
1 parent 9823695 commit 05ddd16

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

mergin/cli.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ def list_projects(flag):
146146
@cli.command()
147147
@click.argument('project')
148148
@click.argument('directory', type=click.Path(), required=False)
149-
def download(project, directory):
149+
@click.option('--version', default=None, help='Version of project to download')
150+
def download(project, directory, version):
150151
"""Download last version of mergin project"""
151152

152153
c = _init_client()
@@ -156,7 +157,7 @@ def download(project, directory):
156157

157158
click.echo('Downloading into {}'.format(directory))
158159
try:
159-
job = download_project_async(c, project, directory)
160+
job = download_project_async(c, project, directory, version)
160161

161162
import time
162163
with click.progressbar(length=job.total_size) as bar:

mergin/client.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,17 +318,22 @@ def projects_list(self, tags=None, user=None, flag=None, q=None):
318318
projects = json.load(resp)
319319
return projects
320320

321-
def project_info(self, project_path, since=None):
321+
def project_info(self, project_path, since=None, version=None):
322322
"""
323323
Fetch info about project.
324324
325325
:param project_path: Project's full name (<namespace>/<name>)
326326
:type project_path: String
327327
:param since: Version to track history of geodiff files from
328328
:type since: String
329+
:param version: Project version to get details for (particularly list of files)
330+
:type version: String
329331
:rtype: Dict
330332
"""
331333
params = {'since': since} if since else {}
334+
# since and version are mutually exclusive
335+
if version:
336+
params = {'version': version}
332337
resp = self.get("/v1/project/{}".format(project_path), params)
333338
return json.load(resp)
334339

@@ -344,17 +349,20 @@ def project_versions(self, project_path):
344349
resp = self.get("/v1/project/version/{}".format(project_path))
345350
return json.load(resp)
346351

347-
def download_project(self, project_path, directory):
352+
def download_project(self, project_path, directory, version=None):
348353
"""
349-
Download latest version of project into given directory.
354+
Download project into given directory. If version is not specified, latest version is downloaded
350355
351356
:param project_path: Project's full name (<namespace>/<name>)
352357
:type project_path: String
353358
359+
:param version: Project version to download
360+
:type version: String
361+
354362
:param directory: Target directory
355363
:type directory: String
356364
"""
357-
job = download_project_async(self, project_path, directory)
365+
job = download_project_async(self, project_path, directory, version)
358366
download_project_wait(job)
359367
download_project_finalize(job)
360368

mergin/client_pull.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def _cleanup_failed_download(directory):
9696
shutil.rmtree(directory)
9797

9898

99-
def download_project_async(mc, project_path, directory):
99+
def download_project_async(mc, project_path, directory, project_version=None):
100100
"""
101101
Starts project download in background and returns handle to the pending project download.
102102
Using that object it is possible to watch progress or cancel the ongoing work.
@@ -114,7 +114,7 @@ def download_project_async(mc, project_path, directory):
114114
mp.log.info(f"--- start download {project_path}")
115115

116116
try:
117-
project_info = mc.project_info(project_path)
117+
project_info = mc.project_info(project_path, version=project_version)
118118
except ClientError:
119119
_cleanup_failed_download(directory)
120120
raise

mergin/test/test_client.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,42 @@ def test_get_projects_by_name(mc):
662662
assert full_name in resp
663663
assert resp[full_name]["name"] == name
664664
assert resp[full_name]["version"] == 'v0'
665+
666+
667+
def test_download_versions(mc):
668+
test_project = 'test_download'
669+
project = API_USER + '/' + test_project
670+
project_dir = os.path.join(TMP_DIR, test_project)
671+
# download dirs
672+
project_dir_v1 = os.path.join(TMP_DIR, test_project + '_v1')
673+
project_dir_v2 = os.path.join(TMP_DIR, test_project + '_v2')
674+
project_dir_v3 = os.path.join(TMP_DIR, test_project + '_v3')
675+
676+
cleanup(mc, project, [project_dir, project_dir_v1, project_dir_v2, project_dir_v3])
677+
# create remote project
678+
shutil.copytree(TEST_DATA_DIR, project_dir)
679+
mc.create_project_and_push(test_project, project_dir)
680+
681+
# create new version - v2
682+
f_added = 'new.txt'
683+
with open(os.path.join(project_dir, f_added), 'w') as f:
684+
f.write('new file')
685+
686+
mc.push_project(project_dir)
687+
project_info = mc.project_info(project)
688+
assert project_info['version'] == 'v2'
689+
690+
info_v1 = mc.project_info(project, version='v1')
691+
mc.download_project(project, project_dir_v1, 'v1')
692+
for f in info_v1["files"]:
693+
assert os.path.exists(os.path.join(project_dir_v1, f["path"]))
694+
695+
mc.download_project(project, project_dir_v2, 'v2')
696+
info_v2 = mc.project_info(project, version='v2')
697+
assert os.path.exists(os.path.join(project_dir_v2, f_added))
698+
for f in info_v2["files"]:
699+
assert os.path.exists(os.path.join(project_dir_v2, f["path"]))
700+
701+
# try to download not-existing version
702+
with pytest.raises(ClientError):
703+
mc.download_project(project, project_dir_v3, 'v3')

0 commit comments

Comments
 (0)