from pathlib import Path from ..models import ( CommandSpec, HarnessConfig, ProjectKind, ProjectSelection, Toolchain, ValidationPlan, ValidationStep, ) from .base import AdapterError def _test_argv(root: Path, command: tuple[str, ...]) -> tuple[str, ...]: if "/" not in command[0] and "\\" not in command[0]: return command first = Path(command[0].replace("\\", "/")) executable = first if first.is_absolute() else (root / first).resolve() try: executable.relative_to(root) except ValueError as exc: raise AdapterError( "msbuild.testCommand resolves outside the repository" ) from exc return (str(executable), *command[1:]) class MSBuildAdapter: def create_plan( self, root: Path, selection: ProjectSelection, config: HarnessConfig, tools: Toolchain, ) -> ValidationPlan: if selection.kind is not ProjectKind.MSBUILD: raise AdapterError("MSBuildAdapter received a non-MSBuild project") if not config.msbuild.test_command: raise AdapterError( "msbuild.testCommand is required for .sln/.vcxproj validation" ) build = ValidationStep( CommandSpec( ( str(tools.msbuild), str(selection.project_file), "/m", "/nologo", f"/p:Configuration={config.msbuild.configuration}", f"/p:Platform={config.msbuild.platform}", ), root, "build", ) ) test = ValidationStep( CommandSpec(_test_argv(root, config.msbuild.test_command), root, "test") ) return ValidationPlan(ProjectKind.MSBUILD, (build, test))