Skip to content

Commit bed3c5d

Browse files
authored
Merge pull request #29 from opengisch/skip_existing
Add option to skip downloading locally existing files
2 parents a351abe + fc5ce35 commit bed3c5d

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

src/bin/qfieldcloud-cli

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,18 @@ def upload_files(ctx, project_id, project_path, filter_glob, throw_on_error):
293293
"--throw-on-error/--no-throw-on-error",
294294
help="If any project file downloads fails stop downloading the rest. Default: False",
295295
)
296+
@click.option(
297+
"--force-download/--no-force-download",
298+
help="Download file even if it already exists locally. Default: False",
299+
)
296300
@click.pass_context
297-
def download_files(ctx, project_id, local_dir, filter_glob, throw_on_error):
301+
def download_files(ctx, project_id, local_dir, filter_glob, throw_on_error, force_download):
298302
"""Download QFieldCloud project files."""
299303

300304
log(f'Downloading project "{project_id}" files to {local_dir}…')
301305

302306
files = ctx.obj["client"].download_project(
303-
project_id, local_dir, filter_glob, throw_on_error, show_progress=True
307+
project_id, local_dir, filter_glob, throw_on_error, show_progress=True, force_download=force_download,
304308
)
305309

306310
if ctx.obj["format_json"]:
@@ -441,14 +445,18 @@ def package_latest(ctx, project_id):
441445
"--throw-on-error/--no-throw-on-error",
442446
help="If any packaged file downloads fails stop downloading the rest. Default: False",
443447
)
448+
@click.option(
449+
"--force-download/--no-force-download",
450+
help="Download file even if it already exists locally. Default: False",
451+
)
444452
@click.pass_context
445-
def package_download(ctx, project_id, local_dir, filter_glob, throw_on_error):
453+
def package_download(ctx, project_id, local_dir, filter_glob, throw_on_error, force_download):
446454
"""Download packaged QFieldCloud project files."""
447455

448456
log(f'Downloading the latest project "{project_id}" package files to {local_dir}…')
449457

450458
files = ctx.obj["client"].package_download(
451-
project_id, local_dir, filter_glob, throw_on_error, show_progress=True
459+
project_id, local_dir, filter_glob, throw_on_error, show_progress=True, force_download=force_download,
452460
)
453461

454462
if ctx.obj["format_json"]:

src/qfieldcloud_sdk/sdk.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,15 @@ def download_project(
279279
filter_glob: str = None,
280280
throw_on_error: bool = False,
281281
show_progress: bool = False,
282+
force_download: bool = False,
282283
) -> List[Dict]:
283284
"""Download the specified project files into the destination dir.
284285
285286
Args:
286287
project_id: id of the project to be downloaded
287288
local_dir: destination directory where the files will be downloaded
288289
filter_glob: if specified, download only the files which match the glob, otherwise download all
290+
force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
289291
"""
290292

291293
files = self.list_remote_files(project_id)
@@ -298,6 +300,7 @@ def download_project(
298300
filter_glob,
299301
throw_on_error,
300302
show_progress,
303+
force_download,
301304
)
302305

303306
def list_jobs(self, project_id: str, job_type: JobTypes = None) -> Dict[str, Any]:
@@ -442,13 +445,15 @@ def package_download(
442445
filter_glob: str = None,
443446
throw_on_error: bool = False,
444447
show_progress: bool = False,
448+
force_download: bool = False,
445449
) -> List[Dict]:
446450
"""Download the specified project packaged files into the destination dir.
447451
448452
Args:
449453
project_id: id of the project to be downloaded
450454
local_dir: destination directory where the files will be downloaded
451455
filter_glob: if specified, download only packaged files which match the glob, otherwise download all
456+
force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
452457
"""
453458
project_status = self.package_latest(project_id)
454459

@@ -467,6 +472,7 @@ def package_download(
467472
filter_glob,
468473
throw_on_error,
469474
show_progress,
475+
force_download,
470476
)
471477

472478
def download_files(
@@ -478,6 +484,7 @@ def download_files(
478484
filter_glob: str = None,
479485
throw_on_error: bool = False,
480486
show_progress: bool = False,
487+
force_download: bool = False,
481488
) -> List[Dict]:
482489
"""Download project files.
483490
@@ -489,7 +496,7 @@ def download_files(
489496
filter_glob (str, optional): Download only files matching the glob pattern. If None download all. Defaults to None.
490497
throw_on_error (bool, optional): Throw if download error occurres. Defaults to False.
491498
show_progress (bool, optional): Show progress bar in the console. Defaults to False.
492-
499+
force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
493500
Raises:
494501
QFieldCloudException: if throw_on_error is True, throw an error if a download request fails.
495502
@@ -508,6 +515,9 @@ def download_files(
508515

509516
for file in files_to_download:
510517
local_filename = Path(f'{local_dir}/{file["name"]}')
518+
md5sum = None
519+
if not force_download:
520+
md5sum = file.get("md5sum", None)
511521

512522
try:
513523
self.download_file(
@@ -516,6 +526,7 @@ def download_files(
516526
local_filename,
517527
file["name"],
518528
show_progress,
529+
md5sum,
519530
)
520531
file["status"] = FileTransferStatus.SUCCESS
521532
except QfcRequestException as err:
@@ -542,6 +553,7 @@ def download_file(
542553
local_filename: Path,
543554
remote_filename: Path,
544555
show_progress: bool,
556+
remote_md5sum: str = None,
545557
) -> requests.Response:
546558
"""Download a single project file.
547559
@@ -551,13 +563,27 @@ def download_file(
551563
local_filename (Path): Local filename
552564
remote_filename (Path): Remote filename
553565
show_progress (bool): Show progressbar in the console
566+
remote_md5sum (str, optional): The md5sum of the remote file. If is None, the download of the file happens even if it already exists locally. Defaults to None.
554567
555568
Raises:
556569
NotImplementedError: Raised if unknown `download_type` is passed
557570
558571
Returns:
559572
requests.Response: the response object
560573
"""
574+
575+
if remote_md5sum and local_filename.exists():
576+
if self._get_md5sum(str(local_filename)) == remote_md5sum:
577+
if show_progress:
578+
print(
579+
f"{remote_filename}: Already present locally. Download skipped."
580+
)
581+
else:
582+
logging.info(
583+
f'Skipping download of "{remote_filename}" because it is already present locally'
584+
)
585+
return
586+
561587
if download_type == FileTransferType.PROJECT:
562588
url = f"files/{project_id}/{remote_filename}"
563589
elif download_type == FileTransferType.PACKAGE:

0 commit comments

Comments
 (0)