Coverage for src / rhiza / models / _git / helpers.py: 100%
24 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-07-16 12:51 +0000
« prev ^ index » next coverage.py v7.14.0, created at 2026-07-16 12:51 +0000
1"""Module-level git and text helpers shared across the git engine."""
3import shutil
4from typing import Any
6from loguru import logger
9def _normalize_to_list(value: Any | list[Any] | None) -> list[Any]:
10 r"""Convert a value to a list of strings.
12 Handles the case where YAML multi-line strings (using |) are parsed as
13 a single string instead of a list. Splits the string by newlines and
14 strips whitespace from each item.
16 Args:
17 value: A string, list of strings, or None.
19 Returns:
20 A list of strings. Empty list if value is None or empty.
22 Examples:
23 >>> _normalize_to_list(None)
24 []
25 >>> _normalize_to_list([])
26 []
27 >>> _normalize_to_list(['a', 'b', 'c'])
28 ['a', 'b', 'c']
29 >>> _normalize_to_list('single line')
30 ['single line']
31 >>> _normalize_to_list('line1\\n' + 'line2\\n' + 'line3')
32 ['line1', 'line2', 'line3']
33 >>> _normalize_to_list(' item1 \\n' + ' item2 ')
34 ['item1', 'item2']
35 """
36 if value is None:
37 return []
38 if isinstance(value, list):
39 return value
40 if isinstance(value, str):
41 # Split by newlines and filter out empty strings
42 # Handle both actual newlines (\n) and literal backslash-n (\\n)
43 items = value.split("\\n") if "\\n" in value and "\n" not in value else value.split("\n")
44 return [item.strip() for item in items if item.strip()]
45 return []
48def get_git_executable() -> str:
49 """Get the absolute path to the git executable.
51 This function ensures we use the full path to git to prevent
52 security issues related to PATH manipulation.
54 Returns:
55 str: Absolute path to the git executable.
57 Raises:
58 RuntimeError: If git executable is not found in PATH.
59 """
60 git_path = shutil.which("git")
61 if git_path is None:
62 msg = "git executable not found in PATH. Please ensure git is installed and available."
63 raise RuntimeError(msg)
64 return git_path
67def _log_git_stderr_errors(stderr: str | None) -> None:
68 """Extract and log only relevant error messages from git stderr.
70 Args:
71 stderr: Git command stderr output.
72 """
73 if stderr:
74 for line in stderr.strip().split("\n"):
75 line = line.strip()
76 if line and (line.startswith(("fatal:", "error:"))):
77 logger.error(line)