@@ -195,9 +195,17 @@ def _upload_folder(
195195 # be populated
196196 all_folder_parts = sorted (all_folder_parts , key = lambda x : len (x .split ("/" )))
197197 for folder in all_folder_parts :
198- print ("{}Creating folder {}" .format (
199- "[Dry Run] " if dry_run else "" , folder ))
200- Object .create_folder (vault , folder )
198+ if dry_run :
199+ try :
200+ f = Object .get_by_full_path (folder )
201+ if not f .is_folder :
202+ print ("[Dry Run] {} is not a folder - this will cause an error on upload." .format (folder ))
203+ else :
204+ print ("[Dry Run] Folder {} already exists - skipping creation" .format (folder ))
205+ except NotFoundError :
206+ print ("[Dry Run] Creating folder {}" .format (folder ))
207+ else :
208+ Object .create_folder (vault , folder )
201209
202210 # Create files in parallel
203211 # Signal handling allows for graceful exit upon KeyboardInterrupt
@@ -234,18 +242,32 @@ def _create_file_job(args):
234242 try :
235243 local_file_path , remote_folder_full_path , vault_path , dry_run , archive_folder , client_auth , follow_shortcuts \
236244 = args
237- if dry_run :
238- print ("[Dry Run] Uploading {} to {}" .format (
239- local_file_path , remote_folder_full_path ))
240- return
245+
241246 # Provides the global host, token, token_type
242247 client = SolveClient (* client_auth )
243- remote_parent = Object .get_by_full_path (
244- remote_folder_full_path ,
245- assert_type = "folder" ,
246- follow_shortcuts = follow_shortcuts ,
247- client = client
248- )
248+
249+ remote_parent = None
250+ try :
251+ remote_parent = Object .get_by_full_path (
252+ remote_folder_full_path ,
253+ assert_type = "folder" ,
254+ follow_shortcuts = follow_shortcuts ,
255+ client = client
256+ )
257+ except NotFoundError as e :
258+ if not dry_run :
259+ raise e
260+
261+ if dry_run :
262+ if not _object_exists (remote_parent , local_file_path , client ):
263+ print ("[Dry Run] Uploading {} to {}" .format (
264+ local_file_path , remote_folder_full_path ))
265+ return
266+ else :
267+ print ("[Dry Run] File {} already exists at {} - skipping upload" .format (
268+ local_file_path , remote_folder_full_path ))
269+ return
270+
249271 Object .upload_file (
250272 local_file_path ,
251273 remote_parent .path ,
@@ -260,6 +282,26 @@ def _create_file_job(args):
260282 except Exception as e :
261283 return e
262284
285+ def _object_exists (remote_parent , local_path , _client ):
286+ if remote_parent is None :
287+ return False
288+ full_path , path_dict = Object .validate_full_path (
289+ os .path .join ('{}:{}' .format (remote_parent .vault .full_path , remote_parent .path ),
290+ os .path .basename (local_path )), client = _client )
291+ try :
292+ obj = Object .get_by_full_path (full_path , client = _client )
293+ if not obj .is_file :
294+ return False
295+ else :
296+ # Check if the md5sum matches
297+ local_md5 = md5sum (local_path )[0 ]
298+ remote_md5 = obj .get ("md5" )
299+ if remote_md5 and remote_md5 == local_md5 :
300+ return True
301+ else :
302+ return False
303+ except NotFoundError :
304+ return False
263305
264306def _create_template_from_file (template_file , dry_run = False ):
265307 mode = "r"
@@ -752,9 +794,11 @@ def _download_recursive(
752794
753795 min_depth = min ([x .depth for x in remote_objects ])
754796 num_at_min_depth = len ([x for x in remote_objects if x .depth == min_depth ])
755- if num_at_min_depth == 1 :
797+ if num_at_min_depth == 1 and not _is_single_file (remote_objects ):
798+ # when downloading from folder
756799 base_folder_depth = min_depth
757800 else :
801+ # when downloading from vault root or singular file
758802 base_folder_depth = min_depth - 1
759803
760804 downloaded_files = set ()
@@ -995,6 +1039,10 @@ def _ls(full_path, recursive=False, follow_shortcuts=False):
9951039 return files
9961040
9971041
1042+ def _is_single_file (objects ):
1043+ return len (objects ) == 1 and objects [0 ].get ("object_type" ) == "file"
1044+
1045+
9981046def should_tag_by_object_type (args , object_ ):
9991047 """Returns True if object matches object type requirements"""
10001048 valid = True
0 commit comments