Skip to content

Commit eabfd5e

Browse files
authored
Added API calls for downloading files at version and getting concatenated file diffs (#101)
Fixes #93
1 parent db78b90 commit eabfd5e

File tree

5 files changed

+474
-16
lines changed

5 files changed

+474
-16
lines changed

mergin/cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
from mergin.client_pull import (
2727
download_project_async,
2828
download_project_cancel,
29+
download_file_async,
30+
download_file_finalize,
2931
download_project_finalize,
3032
download_project_is_running,
3133
)
@@ -260,6 +262,41 @@ def download(ctx, project, directory, version):
260262
_print_unhandled_exception()
261263

262264

265+
@cli.command()
266+
@click.argument("filepath")
267+
@click.argument("output")
268+
@click.option("--version", help="Project version tag, for example 'v3'")
269+
@click.pass_context
270+
def download_file(ctx, filepath, output, version):
271+
"""
272+
Download project file at specified version. `project` needs to be a combination of namespace/project.
273+
If no version is given, the latest will be fetched.
274+
"""
275+
mc = ctx.obj["client"]
276+
if mc is None:
277+
return
278+
mp = MerginProject(os.getcwd())
279+
project_path = mp.metadata["name"]
280+
try:
281+
job = download_file_async(mc, project_path, filepath, output, version)
282+
with click.progressbar(length=job.total_size) as bar:
283+
last_transferred_size = 0
284+
while download_project_is_running(job):
285+
time.sleep(1 / 10) # 100ms
286+
new_transferred_size = job.transferred_size
287+
bar.update(new_transferred_size - last_transferred_size) # the update() needs increment only
288+
last_transferred_size = new_transferred_size
289+
download_file_finalize(job)
290+
click.echo("Done")
291+
except KeyboardInterrupt:
292+
click.secho("Cancelling...")
293+
download_project_cancel(job)
294+
except ClientError as e:
295+
click.secho("Error: " + str(e), fg="red")
296+
except Exception as e:
297+
_print_unhandled_exception()
298+
299+
263300
def num_version(name):
264301
return int(name.lstrip("v"))
265302

mergin/client.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,20 @@
1111
import dateutil.parser
1212
import ssl
1313

14-
from .common import ClientError, LoginError
14+
from .common import ClientError, LoginError, InvalidProject
1515
from .merginproject import MerginProject
16-
from .client_pull import download_project_async, download_project_wait, download_project_finalize
16+
from .client_pull import (
17+
download_file_finalize,
18+
download_project_async,
19+
download_file_async,
20+
download_diffs_async,
21+
download_project_finalize,
22+
download_project_wait,
23+
download_diffs_finalize,
24+
)
1725
from .client_pull import pull_project_async, pull_project_wait, pull_project_finalize
1826
from .client_push import push_project_async, push_project_wait, push_project_finalize
19-
from .utils import DateTimeEncoder
27+
from .utils import DateTimeEncoder, get_versions_with_file_changes
2028
from .version import __version__
2129

2230
this_dir = os.path.dirname(os.path.realpath(__file__))
@@ -618,3 +626,38 @@ def get_projects_by_names(self, projects):
618626

619627
resp = self.post("/v1/project/by_names", {"projects": projects}, {"Content-Type": "application/json"})
620628
return json.load(resp)
629+
630+
def download_file(self, project_dir, file_path, output_filename, version=None):
631+
"""
632+
Download project file at specified version. Get the latest if no version specified.
633+
634+
:param project_dir: project local directory
635+
:type project_dir: String
636+
:param file_path: relative path of file to download in the project directory
637+
:type file_path: String
638+
:param output_filename: full destination path for saving the downloaded file
639+
:type output_filename: String
640+
:param version: optional version tag for downloaded file
641+
:type version: String
642+
"""
643+
job = download_file_async(self, project_dir, file_path, output_filename, version=version)
644+
pull_project_wait(job)
645+
download_file_finalize(job)
646+
647+
def get_file_diff(self, project_dir, file_path, output_diff, version_from, version_to):
648+
""" Create concatenated diff for project file diffs between versions version_from and version_to.
649+
650+
:param project_dir: project local directory
651+
:type project_dir: String
652+
:param file_path: relative path of file to download in the project directory
653+
:type file_path: String
654+
:param output_diff: full destination path for concatenated diff file
655+
:type output_diff: String
656+
:param version_from: starting project version tag for getting diff, for example 'v3'
657+
:type version_from: String
658+
:param version_to: ending project version tag for getting diff
659+
:type version_to: String
660+
"""
661+
job = download_diffs_async(self, project_dir, file_path, version_from, version_to)
662+
pull_project_wait(job)
663+
download_diffs_finalize(job, output_diff)

0 commit comments

Comments
 (0)