# Buggy code
def _build_collection_tar(
    b_collection_path, b_tar_path, collection_manifest, file_manifest
):
    files_manifest_json = to_bytes(
        json.dumps(file_manifest, indent=True), errors="surrogate_or_strict"
    )
    collection_manifest["file_manifest_file"]["chksum_sha256"] = secure_hash_s(
        files_manifest_json, hash_func=sha256
    )
    collection_manifest_json = to_bytes(
        json.dumps(collection_manifest, indent=True), errors="surrogate_or_strict"
    )

    with _tempdir() as b_temp_path:
        b_tar_filepath = os.path.join(b_temp_path, os.path.basename(b_tar_path))

        with tarfile.open(b_tar_filepath, mode="w:gz") as tar_file:
            # Add the MANIFEST.json and FILES.json file to the archive
            for name, b in [
                ("MANIFEST.json", collection_manifest_json),
                ("FILES.json", files_manifest_json),
            ]:
                b_io = BytesIO(b)
                tar_info = tarfile.TarInfo(name)
                tar_info.size = len(b)
                tar_info.mtime = time.time()
                tar_info.mode = 0o0644
                tar_file.addfile(tarinfo=tar_info, fileobj=b_io)

            for file_info in file_manifest["files"]:
                if file_info["name"] == ".":
                    continue

                # arcname expects a native string, cannot be bytes
                filename = to_native(file_info["name"], errors="surrogate_or_strict")
                b_src_path = os.path.join(
                    b_collection_path, to_bytes(filename, errors="surrogate_or_strict")
                )

                def reset_stat(tarinfo):
                    existing_is_exec = tarinfo.mode & stat.S_IXUSR
                    tarinfo.mode = (
                        0o0755 if existing_is_exec or tarinfo.isdir() else 0o0644
                    )
                    tarinfo.uid = tarinfo.gid = 0
                    tarinfo.uname = tarinfo.gname = ""
                    return tarinfo

                tar_file.add(
                    os.path.realpath(b_src_path),
                    arcname=filename,
                    recursive=False,
                    filter=reset_stat,
                )

        shutil.copy(b_tar_filepath, b_tar_path)
        collection_name = "%s.%s" % (
            collection_manifest["collection_info"]["namespace"],
            collection_manifest["collection_info"]["name"],
        )
        display.display(
            "Created collection for %s at %s" % (collection_name, to_text(b_tar_path))
        )


# Traceback (KeyError)
Exception, this is probably a bug: "filename 'tests/unit/modules/placebo_recordings/aws_direct_connect_link_aggregation_group/nonexistent_lag_status' not found"
the full traceback was:
Traceback (most recent call last):
File "/home/bcoca/work/ansible/bin/ansible-galaxy", line 123, in <module>
exit_code = cli.run()
File "/home/bcoca/work/ansible/lib/ansible/cli/galaxy.py", line 490, in run
context.CLIARGS['func']()
File "/home/bcoca/work/ansible/lib/ansible/cli/galaxy.py", line 1057, in execute_install
self._execute_install_collection(collection_requirements, collection_path)
File "/home/bcoca/work/ansible/lib/ansible/cli/galaxy.py", line 1079, in _execute_install_collection
no_deps, force, force_with_deps, allow_pre_release=allow_pre_release)
File "/home/bcoca/work/ansible/lib/ansible/galaxy/collection.py", line 675, in install_collections
collection.install(output_path, b_temp_path)
File "/home/bcoca/work/ansible/lib/ansible/galaxy/collection.py", line 250, in install
self.install_artifact(b_collection_path, b_temp_path)
File "/home/bcoca/work/ansible/lib/ansible/galaxy/collection.py", line 275, in install_artifact
_extract_tar_dir(collection_tar, file_name, b_collection_path)
File "/home/bcoca/work/ansible/lib/ansible/galaxy/collection.py", line 1387, in _extract_tar_dir
tar_member = tar.getmember(to_native(dirname, errors='surrogate_or_strict'))
File "/usr/lib/python3.7/tarfile.py", line 1752, in getmember
raise KeyError("filename %r not found" % name)
KeyError: "filename 'tests/unit/modules/placebo_recordings/aws_direct_connect_link_aggregation_group/nonexistent_lag_status' not found"

# Fixed code
def _build_collection_tar(
    b_collection_path, b_tar_path, collection_manifest, file_manifest
):
    files_manifest_json = to_bytes(
        json.dumps(file_manifest, indent=True), errors="surrogate_or_strict"
    )
    collection_manifest["file_manifest_file"]["chksum_sha256"] = secure_hash_s(
        files_manifest_json, hash_func=sha256
    )
    collection_manifest_json = to_bytes(
        json.dumps(collection_manifest, indent=True), errors="surrogate_or_strict"
    )

    with _tempdir() as b_temp_path:
        b_tar_filepath = os.path.join(b_temp_path, os.path.basename(b_tar_path))

        with tarfile.open(b_tar_filepath, mode="w:gz") as tar_file:
            # Add the MANIFEST.json and FILES.json file to the archive
            for name, b in [
                ("MANIFEST.json", collection_manifest_json),
                ("FILES.json", files_manifest_json),
            ]:
                b_io = BytesIO(b)
                tar_info = tarfile.TarInfo(name)
                tar_info.size = len(b)
                tar_info.mtime = time.time()
                tar_info.mode = 0o0644
                tar_file.addfile(tarinfo=tar_info, fileobj=b_io)

            for file_info in file_manifest["files"]:
                if file_info["name"] == ".":
                    continue

                # arcname expects a native string, cannot be bytes
                filename = to_native(file_info["name"], errors="surrogate_or_strict")
                b_src_path = os.path.join(
                    b_collection_path, to_bytes(filename, errors="surrogate_or_strict")
                )

                def reset_stat(tarinfo):
                    if tarinfo.type != tarfile.SYMTYPE:
                        existing_is_exec = tarinfo.mode & stat.S_IXUSR
                        tarinfo.mode = (
                            0o0755 if existing_is_exec or tarinfo.isdir() else 0o0644
                        )
                    tarinfo.uid = tarinfo.gid = 0
                    tarinfo.uname = tarinfo.gname = ""

                    return tarinfo

                if os.path.islink(b_src_path):
                    b_link_target = os.path.realpath(b_src_path)
                    if _is_child_path(b_link_target, b_collection_path):
                        b_rel_path = os.path.relpath(
                            b_link_target, start=os.path.dirname(b_src_path)
                        )

                        tar_info = tarfile.TarInfo(filename)
                        tar_info.type = tarfile.SYMTYPE
                        tar_info.linkname = to_native(
                            b_rel_path, errors="surrogate_or_strict"
                        )
                        tar_info = reset_stat(tar_info)
                        tar_file.addfile(tarinfo=tar_info)

                        continue

                # Dealing with a normal file, just add it by name.
                tar_file.add(
                    os.path.realpath(b_src_path),
                    arcname=filename,
                    recursive=False,
                    filter=reset_stat,
                )

        shutil.copy(b_tar_filepath, b_tar_path)
        collection_name = "%s.%s" % (
            collection_manifest["collection_info"]["namespace"],
            collection_manifest["collection_info"]["name"],
        )
        display.display(
            "Created collection for %s at %s" % (collection_name, to_text(b_tar_path))
        )