diff --git a/scripts/run_behave_parallel.py b/scripts/run_behave_parallel.py index b3d6e4d80..0731a103a 100644 --- a/scripts/run_behave_parallel.py +++ b/scripts/run_behave_parallel.py @@ -23,6 +23,7 @@ import argparse import io import multiprocessing import os +import subprocess import sys import time import traceback @@ -32,6 +33,50 @@ from typing import Any DEFAULT_FEATURE_ROOT = "features/" + +def _is_btrfs_or_overlayfs() -> bool: + fs_targets = {"btrfs", "overlay"} + + try: + result = subprocess.run( + ["stat", "-f", "-c", "%T", "."], + check=True, + capture_output=True, + text=True, + ) + except (OSError, subprocess.SubprocessError): + pass + else: + fs_type = result.stdout.strip().lower() + return fs_type in fs_targets + + try: + current_path = os.path.realpath(".") + best_match_len = -1 + best_fs_type: str | None = None + with open("/proc/mounts", encoding="utf-8") as mounts: + for line in mounts: + parts = line.split() + if len(parts) < 3: + continue + mount_point = parts[1].replace("\\040", " ") + mount_real = os.path.realpath(mount_point) + if not mount_real: + continue + if ( + current_path == mount_real + or current_path.startswith(mount_real.rstrip("/") + "/") + ) and len(mount_real) > best_match_len: + best_match_len = len(mount_real) + best_fs_type = parts[2].lower() + if best_fs_type: + return best_fs_type in fs_targets + except OSError: + pass + + return False + + # Type alias for summary dictionaries Summary = dict[str, Any] @@ -321,8 +366,6 @@ def main(argv: list[str] | None = None) -> None: # Pass-through --help / --version to behave if any(flag in remaining for flag in ("-h", "--help", "--version")): - import subprocess - code = subprocess.run( [sys.executable, "-m", "behave", *other_args, *feature_args] ).returncode @@ -348,6 +391,7 @@ def main(argv: list[str] | None = None) -> None: or coverage_mode or len(feature_paths) == 1 or len(feature_paths) <= 2 + or _is_btrfs_or_overlayfs() ): # ---- sequential in-process mode ---- _, total = _run_features_inprocess(feature_paths, other_args)