summaryrefslogtreecommitdiffstats
path: root/src/ansiblelint/file_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ansiblelint/file_utils.py')
-rw-r--r--src/ansiblelint/file_utils.py54
1 files changed, 46 insertions, 8 deletions
diff --git a/src/ansiblelint/file_utils.py b/src/ansiblelint/file_utils.py
index 15c92d2..04ce3cd 100644
--- a/src/ansiblelint/file_utils.py
+++ b/src/ansiblelint/file_utils.py
@@ -1,4 +1,5 @@
"""Utility functions related to file operations."""
+
from __future__ import annotations
import copy
@@ -16,12 +17,15 @@ import wcmatch.pathlib
import wcmatch.wcmatch
from yaml.error import YAMLError
-from ansiblelint.config import BASE_KINDS, Options, options
+from ansiblelint.app import get_app
+from ansiblelint.config import ANSIBLE_OWNED_KINDS, BASE_KINDS, Options, options
from ansiblelint.constants import CONFIG_FILENAMES, FileType, States
if TYPE_CHECKING:
from collections.abc import Iterator, Sequence
+ from ansiblelint.errors import MatchError
+
_logger = logging.getLogger(__package__)
@@ -69,9 +73,9 @@ def is_relative_to(path: Path, *other: Any) -> bool:
"""Return True if the path is relative to another path or False."""
try:
path.resolve().absolute().relative_to(*other)
- return True
except ValueError:
return False
+ return True
def normpath_path(path: str | Path) -> Path:
@@ -197,6 +201,10 @@ class Lintable:
self.exc: Exception | None = None # Stores data loading exceptions
self.parent = parent
self.explicit = False # Indicates if the file was explicitly provided or was indirectly included.
+ self.line_offset = (
+ 0 # Amount to offset line numbers by to get accurate position
+ )
+ self.matches: list[MatchError] = []
if isinstance(name, str):
name = Path(name)
@@ -219,7 +227,12 @@ class Lintable:
parts = self.path.parent.parts
if "roles" in parts:
role = self.path
- while role.parent.name != "roles" and role.name:
+ roles_path = get_app(cached=True).runtime.config.default_roles_path
+ while (
+ str(role.parent.absolute()) not in roles_path
+ and role.parent.name != "roles"
+ and role.name
+ ):
role = role.parent
if role.exists():
self.role = role.name
@@ -252,7 +265,12 @@ class Lintable:
self.parent = _guess_parent(self)
if self.kind == "yaml":
- _ = self.data # pylint: disable=pointless-statement
+ _ = self.data
+
+ def __del__(self) -> None:
+ """Clean up temporary files when the instance is cleaned up."""
+ if hasattr(self, "file"):
+ self.file.close()
def _guess_kind(self) -> None:
if self.kind == "yaml":
@@ -350,10 +368,16 @@ class Lintable:
lintable.write(force=True)
"""
- if not force and not self.updated:
+ dump_filename = self.path.expanduser().resolve()
+ if os.environ.get("ANSIBLE_LINT_WRITE_TMP", "0") == "1":
+ dump_filename = dump_filename.with_suffix(
+ f".tmp{dump_filename.suffix}",
+ )
+ elif not force and not self.updated:
# No changes to write.
return
- self.path.expanduser().resolve().write_text(
+
+ dump_filename.write_text(
self._content or "",
encoding="utf-8",
)
@@ -372,6 +396,16 @@ class Lintable:
"""Return user friendly representation of a lintable."""
return f"{self.name} ({self.kind})"
+ def is_owned_by_ansible(self) -> bool:
+ """Return true for YAML files that are managed by Ansible."""
+ return self.kind in ANSIBLE_OWNED_KINDS
+
+ def failed(self) -> bool:
+ """Return true if we already found syntax-check errors on this file."""
+ return any(
+ match.rule.id in ("syntax-check", "load-failure") for match in self.matches
+ )
+
@property
def data(self) -> Any:
"""Return loaded data representation for current file, if possible."""
@@ -396,7 +430,11 @@ class Lintable:
# pylint: disable=import-outside-toplevel
from ansiblelint.skip_utils import append_skipped_rules
- self.state = append_skipped_rules(self.state, self)
+ # pylint: disable=possibly-used-before-assignment
+ self.state = append_skipped_rules(
+ self.state,
+ self,
+ )
else:
logging.debug(
"data set to None for %s due to being '%s' (%s) kind.",
@@ -513,7 +551,7 @@ def expand_dirs_in_lintables(lintables: set[Lintable]) -> None:
for item in copy.copy(lintables):
if item.path.is_dir():
for filename in all_files:
- if filename.startswith(str(item.path)):
+ if filename.startswith((str(item.path), str(item.path.absolute()))):
lintables.add(Lintable(filename))