summaryrefslogtreecommitdiff
path: root/lib/ansible/collections/list.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/collections/list.py')
-rw-r--r--lib/ansible/collections/list.py124
1 files changed, 36 insertions, 88 deletions
diff --git a/lib/ansible/collections/list.py b/lib/ansible/collections/list.py
index af3c1cae..ef858ae9 100644
--- a/lib/ansible/collections/list.py
+++ b/lib/ansible/collections/list.py
@@ -1,65 +1,28 @@
# (c) 2019 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import os
-
-from collections import defaultdict
-
from ansible.errors import AnsibleError
-from ansible.collections import is_collection_path
-from ansible.module_utils._text import to_bytes
-from ansible.utils.collection_loader import AnsibleCollectionConfig
+from ansible.cli.galaxy import with_collection_artifacts_manager
+from ansible.galaxy.collection import find_existing_collections
+from ansible.module_utils.common.text.converters import to_bytes
from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path
from ansible.utils.display import Display
display = Display()
-def list_collections(coll_filter=None, search_paths=None, dedupe=False):
+@with_collection_artifacts_manager
+def list_collections(coll_filter=None, search_paths=None, dedupe=True, artifacts_manager=None):
collections = {}
- for candidate in list_collection_dirs(search_paths=search_paths, coll_filter=coll_filter):
- if os.path.exists(candidate):
- collection = _get_collection_name_from_path(candidate)
- if collection not in collections or not dedupe:
- collections[collection] = candidate
+ for candidate in list_collection_dirs(search_paths=search_paths, coll_filter=coll_filter, artifacts_manager=artifacts_manager, dedupe=dedupe):
+ collection = _get_collection_name_from_path(candidate)
+ collections[collection] = candidate
return collections
-def list_valid_collection_paths(search_paths=None, warn=False):
- """
- Filter out non existing or invalid search_paths for collections
- :param search_paths: list of text-string paths, if none load default config
- :param warn: display warning if search_path does not exist
- :return: subset of original list
- """
-
- if search_paths is None:
- search_paths = []
-
- search_paths.extend(AnsibleCollectionConfig.collection_paths)
-
- for path in search_paths:
-
- b_path = to_bytes(path)
- if not os.path.exists(b_path):
- # warn for missing, but not if default
- if warn:
- display.warning("The configured collection path {0} does not exist.".format(path))
- continue
-
- if not os.path.isdir(b_path):
- if warn:
- display.warning("The configured collection path {0}, exists, but it is not a directory.".format(path))
- continue
-
- yield path
-
-
-def list_collection_dirs(search_paths=None, coll_filter=None):
+@with_collection_artifacts_manager
+def list_collection_dirs(search_paths=None, coll_filter=None, artifacts_manager=None, dedupe=True):
"""
Return paths for the specific collections found in passed or configured search paths
:param search_paths: list of text-string paths, if none load default config
@@ -67,48 +30,33 @@ def list_collection_dirs(search_paths=None, coll_filter=None):
:return: list of collection directory paths
"""
- collection = None
- namespace = None
+ namespace_filter = None
+ collection_filter = None
+ has_pure_namespace_filter = False # whether at least one coll_filter is a namespace-only filter
if coll_filter is not None:
- if '.' in coll_filter:
- try:
- (namespace, collection) = coll_filter.split('.')
- except ValueError:
- raise AnsibleError("Invalid collection pattern supplied: %s" % coll_filter)
- else:
- namespace = coll_filter
-
- collections = defaultdict(dict)
- for path in list_valid_collection_paths(search_paths):
-
- if os.path.basename(path) != 'ansible_collections':
- path = os.path.join(path, 'ansible_collections')
-
- b_coll_root = to_bytes(path, errors='surrogate_or_strict')
-
- if os.path.exists(b_coll_root) and os.path.isdir(b_coll_root):
-
- if namespace is None:
- namespaces = os.listdir(b_coll_root)
+ if isinstance(coll_filter, str):
+ coll_filter = [coll_filter]
+ namespace_filter = set()
+ for coll_name in coll_filter:
+ if '.' in coll_name:
+ try:
+ namespace, collection = coll_name.split('.')
+ except ValueError:
+ raise AnsibleError("Invalid collection pattern supplied: %s" % coll_name)
+ namespace_filter.add(namespace)
+ if not has_pure_namespace_filter:
+ if collection_filter is None:
+ collection_filter = []
+ collection_filter.append(collection)
else:
- namespaces = [namespace]
-
- for ns in namespaces:
- b_namespace_dir = os.path.join(b_coll_root, to_bytes(ns))
+ namespace_filter.add(coll_name)
+ has_pure_namespace_filter = True
+ collection_filter = None
+ namespace_filter = sorted(namespace_filter)
- if os.path.isdir(b_namespace_dir):
+ for req in find_existing_collections(search_paths, artifacts_manager, namespace_filter=namespace_filter,
+ collection_filter=collection_filter, dedupe=dedupe):
- if collection is None:
- colls = os.listdir(b_namespace_dir)
- else:
- colls = [collection]
-
- for mycoll in colls:
-
- # skip dupe collections as they will be masked in execution
- if mycoll not in collections[ns]:
- b_coll = to_bytes(mycoll)
- b_coll_dir = os.path.join(b_namespace_dir, b_coll)
- if is_collection_path(b_coll_dir):
- collections[ns][mycoll] = b_coll_dir
- yield b_coll_dir
+ if not has_pure_namespace_filter and coll_filter is not None and req.fqcn not in coll_filter:
+ continue
+ yield to_bytes(req.src)