diff --git a/src/ansiblelint/__main__.py b/src/ansiblelint/__main__.py index 931782bec9a..0cfdfd1a7d4 100755 --- a/src/ansiblelint/__main__.py +++ b/src/ansiblelint/__main__.py @@ -21,6 +21,7 @@ """Command line implementation.""" import errno +import hashlib import logging import os import pathlib @@ -107,6 +108,14 @@ def initialize_options(arguments: Optional[List[str]] = None) -> None: options.warn_list = [normalize_tag(tag) for tag in options.warn_list] options.configured = True + # 6 chars of entropy should be enough + cache_key = hashlib.sha256( + os.path.abspath(options.project_dir).encode() + ).hexdigest()[:6] + options.cache_dir = "%s/ansible-lint/%s" % ( + os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache")), + cache_key, + ) def report_outcome( @@ -258,7 +267,7 @@ def main(argv: Optional[List[str]] = None) -> int: @contextmanager def _previous_revision() -> Iterator[None]: """Create or update a temporary workdir containing the previous revision.""" - worktree_dir = ".cache/old-rev" + worktree_dir = f"{options.cache_dir}/old-rev" revision = subprocess.run( ["git", "rev-parse", "HEAD^1"], check=True, diff --git a/src/ansiblelint/config.py b/src/ansiblelint/config.py index 04dfd0d4f0d..be8a8648c1c 100644 --- a/src/ansiblelint/config.py +++ b/src/ansiblelint/config.py @@ -59,6 +59,7 @@ options = Namespace( + cache_dir=".cache", colored=True, configured=False, cwd=".", diff --git a/src/ansiblelint/prerun.py b/src/ansiblelint/prerun.py index 731b561db0a..78a2fe1bca0 100644 --- a/src/ansiblelint/prerun.py +++ b/src/ansiblelint/prerun.py @@ -111,7 +111,7 @@ def install_requirements(requirement: str) -> None: "role", "install", "--roles-path", - f"{options.project_dir}/.cache/roles", + f"{options.cache_dir}/roles", "-vr", f"{requirement}", ] @@ -136,7 +136,7 @@ def install_requirements(requirement: str) -> None: "collection", "install", "-p", - f"{options.project_dir}/.cache/collections", + f"{options.cache_dir}/collections", "-vr", f"{requirement}", ] @@ -245,7 +245,7 @@ def _install_galaxy_role() -> None: fqrn = f"{role_namespace}{role_name}" else: fqrn = pathlib.Path(".").absolute().name - p = pathlib.Path(f"{options.project_dir}/.cache/roles") + p = pathlib.Path(f"{options.cache_dir}/roles") p.mkdir(parents=True, exist_ok=True) link_path = p / fqrn # despite documentation stating that is_file() reports true for symlinks, @@ -265,10 +265,10 @@ def _prepare_ansible_paths() -> None: for path_list, path in ( (library_paths, "plugins/modules"), - (library_paths, f"{options.project_dir}/.cache/modules"), - (collection_list, f"{options.project_dir}/.cache/collections"), + (library_paths, f"{options.cache_dir}/modules"), + (collection_list, f"{options.cache_dir}/collections"), (roles_path, "roles"), - (roles_path, f"{options.project_dir}/.cache/roles"), + (roles_path, f"{options.cache_dir}/roles"), ): if path not in path_list and os.path.exists(path): path_list.append(path) @@ -283,14 +283,14 @@ def _make_module_stub(module_name: str) -> None: if re.match(r"^(\w+|\w+\.\w+\.[\.\w]+)$", module_name): parts = module_name.split(".") if len(parts) < 3: - path = f"{options.project_dir}/.cache/modules" - module_file = f"{options.project_dir}/.cache/modules/{module_name}.py" + path = f"{options.cache_dir}/modules" + module_file = f"{options.cache_dir}/modules/{module_name}.py" namespace = None collection = None else: namespace = parts[0] collection = parts[1] - path = f"{ options.project_dir }/.cache/collections/ansible_collections/{ namespace }/{ collection }/plugins/modules/{ '/'.join(parts[2:-1]) }" + path = f"{ options.cache_dir }/collections/ansible_collections/{ namespace }/{ collection }/plugins/modules/{ '/'.join(parts[2:-1]) }" module_file = f"{path}/{parts[-1]}.py" os.makedirs(path, exist_ok=True) _write_module_stub( @@ -336,9 +336,9 @@ def _perform_mockings() -> None: for role_name in options.mock_roles: if re.match(r"\w+\.\w+\.\w+$", role_name): namespace, collection, role_dir = role_name.split(".") - path = f".cache/collections/ansible_collections/{ namespace }/{ collection }/roles/{ role_dir }/" + path = f"{options.cache_dir}/collections/ansible_collections/{ namespace }/{ collection }/roles/{ role_dir }/" else: - path = f".cache/roles/{role_name}" + path = f"{options.cache_dir}/roles/{role_name}" os.makedirs(path, exist_ok=True) if options.mock_modules: @@ -357,7 +357,7 @@ def _perform_mockings() -> None: if not namespace or not collection: return p = pathlib.Path( - f"{options.project_dir}/.cache/collections/ansible_collections/{ namespace }" + f"{options.cache_dir}/collections/ansible_collections/{ namespace }" ) p.mkdir(parents=True, exist_ok=True) link_path = p / collection