Skip to content

Commit 53694c0

Browse files
Merge from aws/aws-sam-cli/develop
2 parents f37cf2b + 43ead54 commit 53694c0

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

samcli/lib/utils/tar.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def create_tarball(
6262
tarballfile.close()
6363

6464

65-
def _validate_destinations_exists(tar_paths: List[Union[str, Path]]) -> bool:
65+
def _validate_destinations_exists(tar_paths: Union[List[Union[str, Path]], List[Path]]) -> bool:
6666
"""
6767
Validates whether the destination of a symlink exists by resolving the link
6868
and checking the resolved path.
@@ -79,9 +79,22 @@ def _validate_destinations_exists(tar_paths: List[Union[str, Path]]) -> bool:
7979
"""
8080
for file in tar_paths:
8181
file_path_obj = Path(file)
82-
resolved_path = file_path_obj.resolve()
8382

84-
if file_path_obj.is_symlink() and not resolved_path.exists():
83+
try:
84+
resolved_path = file_path_obj.resolve()
85+
except OSError:
86+
# this exception will occur on Windows and will return
87+
# a WinError 123
88+
LOG.warning(f"Failed to resolve file {file_path_obj} on the host machine")
89+
return False
90+
91+
if file_path_obj.is_dir():
92+
# recursively call this method to validate the children are not symlinks to empty locations
93+
children = list(file_path_obj.iterdir())
94+
if not _validate_destinations_exists(children):
95+
# exits early
96+
return False
97+
elif file_path_obj.is_symlink() and not resolved_path.exists():
8598
LOG.warning(f"Symlinked file {file_path_obj} -> {resolved_path} does not exist!")
8699
return False
87100

tests/unit/lib/utils/test_tar.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,38 @@ def test_validating_symlinked_tar_path(self, does_resolved_exist, path_mock):
196196
mock_path_object.resolve.return_value = mock_resolved_object
197197
mock_path_object.is_symlink = Mock()
198198
mock_path_object.is_symlink.return_value = True
199+
mock_path_object.is_dir.return_value = False
199200

200201
path_mock.return_value = mock_path_object
201202

202203
result = _validate_destinations_exists(["mock_path"])
203204

204205
self.assertEqual(result, does_resolved_exist)
206+
207+
@parameterized.expand(
208+
[
209+
(True,),
210+
(False,),
211+
]
212+
)
213+
@patch("samcli.lib.utils.tar.Path")
214+
def test_validating_symlinked_tar_path_directory(self, file_exists, path_mock):
215+
mock_child_resolve = Mock()
216+
mock_child_resolve.exists.return_value = file_exists
217+
218+
mock_child = Mock()
219+
mock_child.is_symlink.return_value = True
220+
mock_child.is_dir.return_value = False
221+
mock_child.resolve.return_value = mock_child_resolve
222+
223+
mock_dir_object = Mock()
224+
mock_dir_object.is_symlink.return_value = False
225+
mock_dir_object.is_dir.return_value = True
226+
mock_dir_object.iterdir.return_value = ["mock_child"]
227+
mock_dir_object.resolve = Mock()
228+
229+
path_mock.side_effect = [mock_dir_object, mock_child]
230+
231+
result = _validate_destinations_exists(["mock_folder"])
232+
233+
self.assertEqual(result, file_exists)

0 commit comments

Comments
 (0)