diff --git a/changelogs/fragments/fix-build-files-manifest-walk.yml b/changelogs/fragments/fix-build-files-manifest-walk.yml new file mode 100644 index 00000000000..3d1000698bf --- /dev/null +++ b/changelogs/fragments/fix-build-files-manifest-walk.yml @@ -0,0 +1,4 @@ +minor_changes: + - >- + ansible-galaxy - Started normalizing build directory with a trailing separator when building collections, internally. + (https://github.com/ansible/ansible/pull/81619). diff --git a/lib/ansible/galaxy/collection/__init__.py b/lib/ansible/galaxy/collection/__init__.py index 60c9c94ba24..9bb9e941a47 100644 --- a/lib/ansible/galaxy/collection/__init__.py +++ b/lib/ansible/galaxy/collection/__init__.py @@ -1203,10 +1203,17 @@ def _build_files_manifest_walk(b_collection_path, namespace, name, ignore_patter manifest = _make_manifest() + def _discover_relative_base_directory(b_path: bytes, b_top_level_dir: bytes) -> bytes: + if b_path == b_top_level_dir: + return b'' + common_prefix = os.path.commonpath((b_top_level_dir, b_path)) + b_rel_base_dir = os.path.relpath(b_path, common_prefix) + return b_rel_base_dir.lstrip(os.path.sep.encode()) + def _walk(b_path, b_top_level_dir): + b_rel_base_dir = _discover_relative_base_directory(b_path, b_top_level_dir) for b_item in os.listdir(b_path): b_abs_path = os.path.join(b_path, b_item) - b_rel_base_dir = b'' if b_path == b_top_level_dir else b_path[len(b_top_level_dir) + 1:] b_rel_path = os.path.join(b_rel_base_dir, b_item) rel_path = to_text(b_rel_path, errors='surrogate_or_strict') diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py index 991184aec1e..e8230d21073 100644 --- a/test/units/galaxy/test_collection.py +++ b/test/units/galaxy/test_collection.py @@ -39,10 +39,17 @@ def reset_cli_args(): co.GlobalCLIArgs._Singleton__instance = None -@pytest.fixture() -def collection_input(tmp_path_factory): - ''' Creates a collection skeleton directory for build tests ''' - test_dir = to_text(tmp_path_factory.mktemp('test-ÅÑŚÌβŁÈ Collections Input')) +@pytest.fixture +def collection_path_suffix(request): + """Return test collection path suffix or the default.""" + return getattr(request, 'param', 'test-ÅÑŚÌβŁÈ Collections Input') + + +@pytest.fixture +def collection_input(tmp_path_factory, collection_path_suffix): + """Create a collection skeleton directory for build tests.""" + test_dir = to_text(tmp_path_factory.mktemp(collection_path_suffix)) + namespace = 'ansible_namespace' collection = 'collection' skeleton = os.path.join(os.path.dirname(os.path.split(__file__)[0]), 'cli', 'test_data', 'collection_skeleton') @@ -467,6 +474,14 @@ def test_build_existing_output_without_force(collection_input): collection.build_collection(to_text(input_dir, errors='surrogate_or_strict'), to_text(output_dir, errors='surrogate_or_strict'), False) +@pytest.mark.parametrize( + 'collection_path_suffix', + ( + 'test-ÅÑŚÌβŁÈ Collections Input 1 with_slash/', + 'test-ÅÑŚÌβŁÈ Collections Input 2 no slash', + ), + indirect=('collection_path_suffix', ), +) def test_build_existing_output_with_force(collection_input): input_dir, output_dir = collection_input