[stable-2.14] Resolve issues on python pre-3.10.6 with collection dirs longer than 100 characters (#81061) (#81073)

(cherry picked from commit 56b67cc)
pull/81187/head
Matt Martz 1 year ago committed by GitHub
parent c8fe9a74a1
commit 939370ea32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- ansible-galaxy - Fix issue installing collections containing directories with more than 100 characters on python versions before 3.10.6

@ -1516,6 +1516,13 @@ def install_artifact(b_coll_targz_path, b_collection_path, b_temp_path, signatur
"""
try:
with tarfile.open(b_coll_targz_path, mode='r') as collection_tar:
# Remove this once py3.11 is our controller minimum
# Workaround for https://bugs.python.org/issue47231
# See _extract_tar_dir
collection_tar._ansible_normalized_cache = {
m.name.removesuffix(os.path.sep): m for m in collection_tar.getmembers()
} # deprecated: description='TarFile member index' core_version='2.18' python_version='3.11'
# Verify the signature on the MANIFEST.json before extracting anything else
_extract_tar_file(collection_tar, MANIFEST_FILENAME, b_collection_path, b_temp_path)
@ -1595,22 +1602,12 @@ def install_src(collection, b_collection_path, b_collection_output_path, artifac
def _extract_tar_dir(tar, dirname, b_dest):
""" Extracts a directory from a collection tar. """
member_names = [to_native(dirname, errors='surrogate_or_strict')]
# Create list of members with and without trailing separator
if not member_names[-1].endswith(os.path.sep):
member_names.append(member_names[-1] + os.path.sep)
dirname = to_native(dirname, errors='surrogate_or_strict').removesuffix(os.path.sep)
# Try all of the member names and stop on the first one that are able to successfully get
for member in member_names:
try:
tar_member = tar.getmember(member)
except KeyError:
continue
break
else:
# If we still can't find the member, raise a nice error.
raise AnsibleError("Unable to extract '%s' from collection" % to_native(member, errors='surrogate_or_strict'))
try:
tar_member = tar._ansible_normalized_cache[dirname]
except KeyError:
raise AnsibleError("Unable to extract '%s' from collection" % dirname)
b_dir_path = os.path.join(b_dest, to_bytes(dirname, errors='surrogate_or_strict'))

@ -14,6 +14,7 @@ from ansible.galaxy.collection import _extract_tar_dir
@pytest.fixture
def fake_tar_obj(mocker):
m_tarfile = mocker.Mock()
m_tarfile._ansible_normalized_cache = {'/some/dir': mocker.Mock()}
m_tarfile.type = mocker.Mock(return_value=b'99')
m_tarfile.SYMTYPE = mocker.Mock(return_value=b'22')
@ -22,23 +23,11 @@ def fake_tar_obj(mocker):
def test_extract_tar_member_trailing_sep(mocker):
m_tarfile = mocker.Mock()
m_tarfile.getmember = mocker.Mock(side_effect=KeyError)
m_tarfile._ansible_normalized_cache = {}
with pytest.raises(AnsibleError, match='Unable to extract'):
_extract_tar_dir(m_tarfile, '/some/dir/', b'/some/dest')
assert m_tarfile.getmember.call_count == 1
def test_extract_tar_member_no_trailing_sep(mocker):
m_tarfile = mocker.Mock()
m_tarfile.getmember = mocker.Mock(side_effect=KeyError)
with pytest.raises(AnsibleError, match='Unable to extract'):
_extract_tar_dir(m_tarfile, '/some/dir', b'/some/dest')
assert m_tarfile.getmember.call_count == 2
def test_extract_tar_dir_exists(mocker, fake_tar_obj):
mocker.patch('os.makedirs', return_value=None)

Loading…
Cancel
Save