@@ -141,6 +141,7 @@ def upload_local_artifacts(
141141 uploader : S3Uploader ,
142142 extension : Optional [str ] = None ,
143143 local_path : Optional [str ] = None ,
144+ previously_uploaded : Optional [Dict ] = None ,
144145) -> str :
145146 """
146147 Upload local artifacts referenced by the property at given resource and
@@ -154,18 +155,20 @@ def upload_local_artifacts(
154155
155156 If path is already a path to S3 object, this method does nothing.
156157
157- :param resource_type: Type of the CloudFormation resource
158- :param resource_id: Id of the CloudFormation resource
159- :param resource_dict: Dictionary containing resource definition
160- :param property_path: Json path to the property of SAM or CloudFormation resource where the
161- local path is present
162- :param parent_dir: Resolve all relative paths with respect to this
163- directory
164- :param uploader: Method to upload files to S3
165- :param extension: Extension of the uploaded artifact
166- :param local_path: Local path for the cases when search return more than single result
167- :return: S3 URL of the uploaded object
168- :raise: ValueError if path is not a S3 URL or a local path
158+ :param resource_type: Type of the CloudFormation resource
159+ :param resource_id: Id of the CloudFormation resource
160+ :param resource_dict: Dictionary containing resource definition
161+ :param property_path: Json path to the property of SAM or CloudFormation resource
162+ where the local path is present
163+ :param parent_dir: Resolve all relative paths with respect to this
164+ directory
165+ :param uploader: Method to upload files to S3
166+ :param extension: Extension of the uploaded artifact
167+ :param local_path: Local path for the cases when search return more than single result
168+ :param previously_uploaded: Cache mapping from (evaluated) local path to previous result of
169+ this function
170+ :return: S3 URL of the uploaded object
171+ :raise: ValueError if path is not a S3 URL or a local path
169172 """
170173
171174 if local_path is None :
@@ -183,18 +186,29 @@ def upload_local_artifacts(
183186
184187 local_path = make_abs_path (parent_dir , local_path )
185188
189+ if previously_uploaded and local_path in previously_uploaded :
190+ result = previously_uploaded [local_path ]
191+ LOG .debug ("Skipping upload of %s since is already uploaded to %s" , local_path , result )
192+ return cast (str , result )
193+
186194 # Or, pointing to a folder. Zip the folder and upload (zip_method is changed based on resource type)
187195 if is_local_folder (local_path ):
188- return zip_and_upload (
196+ result = zip_and_upload (
189197 local_path ,
190198 uploader ,
191199 extension ,
192200 zip_method = make_zip_with_lambda_permissions if resource_type in LAMBDA_LOCAL_RESOURCES else make_zip ,
193201 )
202+ if previously_uploaded is not None :
203+ previously_uploaded [local_path ] = result
204+ return cast (str , result )
194205
195206 # Path could be pointing to a file. Upload the file
196207 if is_local_file (local_path ):
197- return uploader .upload_with_dedup (local_path )
208+ result = uploader .upload_with_dedup (local_path )
209+ if previously_uploaded is not None :
210+ previously_uploaded [local_path ] = result
211+ return cast (str , result )
198212
199213 raise InvalidLocalPathError (resource_id = resource_id , property_name = property_path , local_path = local_path )
200214
0 commit comments