88import os
99import logging
1010from dataclasses import asdict
11+ from enum import Enum
1112from typing import Dict
1213from datetime import datetime
1314
8081 generate_location ,
8182 is_valid_uuid ,
8283 get_device_id ,
84+ is_versioned_file ,
8385 prepare_download_response ,
8486 get_device_id ,
8587 wkb2wkt ,
@@ -287,6 +289,12 @@ def delete_project(namespace, project_name): # noqa: E501
287289 return NoContent , 200
288290
289291
292+ class DowloadFileAction (Enum ):
293+ FULL = "full"
294+ FULL_GPKG = "full_gpkg"
295+ DIFF = "diff"
296+
297+
290298def download_project_file (
291299 project_name , namespace , file , version = None , diff = None
292300): # noqa: E501
@@ -307,10 +315,20 @@ def download_project_file(
307315
308316 :rtype: file
309317 """
310- project = require_project (namespace , project_name , ProjectPermissions .Read )
311- if diff and not version :
318+ if not is_versioned_file (file ):
319+ action = DowloadFileAction .FULL
320+ elif diff :
321+ action = DowloadFileAction .DIFF
322+ else :
323+ action = DowloadFileAction .FULL_GPKG
324+
325+ if action is DowloadFileAction .DIFF and not version :
312326 abort (400 , f"Changeset must be requested for particular file version" )
313327
328+ if action is DowloadFileAction .FULL and diff is True :
329+ abort (404 , f"No diff in particular file { file } )" )
330+
331+ project = require_project (namespace , project_name , ProjectPermissions .Read )
314332 lookup_version = (
315333 ProjectVersion .from_v_name (version ) if version else project .latest_version
316334 )
@@ -329,24 +347,30 @@ def download_project_file(
329347 if not fh or fh .change == PushChangeType .DELETE .value :
330348 abort (404 , f"File { file } not found" )
331349
332- if diff and version :
333- # get specific version of geodiff file modified in requested version
334- if not fh .diff :
335- abort (404 , f"No diff in particular file { file } version" )
336- file_path = fh .diff_file .location
337- else :
338- file_path = fh .location
339-
340- if version and not diff :
341- project .storage .restore_versioned_file (
342- file , ProjectVersion .from_v_name (version )
343- )
350+ # user asked for diff, but there is no diff at that version
351+ if action is DowloadFileAction .DIFF and not fh .diff :
352+ abort (404 , f"No diff in particular file { file } version" )
344353
354+ file_path = (
355+ fh .diff_file .location if action is DowloadFileAction .DIFF else fh .location
356+ )
345357 abs_path = os .path .join (project .storage .project_dir , file_path )
346- # check file exists (e.g. there might have been issue with restore)
358+
347359 if not os .path .exists (abs_path ):
348- logging .error (f"Missing file { namespace } /{ project_name } /{ file_path } " )
349- abort (404 )
360+ if action is DowloadFileAction .FULL_GPKG :
361+ project .storage .restore_versioned_file (
362+ file , ProjectVersion .from_v_name (version )
363+ )
364+
365+ # check again after restore
366+ if not os .path .exists (abs_path ):
367+ logging .error (
368+ f"Failed to restore { namespace } /{ project_name } /{ file_path } "
369+ )
370+ abort (404 )
371+ else :
372+ logging .error (f"Missing file { namespace } /{ project_name } /{ file_path } " )
373+ abort (404 )
350374
351375 response = prepare_download_response (project .storage .project_dir , file_path )
352376 return response
0 commit comments