78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
from pathlib import Path
|
|
|
|
from .models import DiscoveryResult, HarnessConfig, ProjectKind, ProjectSelection
|
|
from .tdd_policy import find_cpp_files
|
|
|
|
|
|
class DiscoveryError(RuntimeError):
|
|
pass
|
|
|
|
|
|
def _cmake_entry(source: Path) -> Path | None:
|
|
for name in ("CMakePresets.json", "CMakeUserPresets.json", "CMakeLists.txt"):
|
|
candidate = source / name
|
|
if candidate.is_file():
|
|
return candidate
|
|
return None
|
|
|
|
|
|
def _single_msbuild(root: Path, explicit: Path | None) -> Path:
|
|
if explicit is not None:
|
|
if explicit.is_file() and explicit.suffix.lower() in {".sln", ".vcxproj"}:
|
|
return explicit
|
|
raise DiscoveryError(f"configured MSBuild project is invalid: {explicit}")
|
|
solutions = sorted(root.glob("*.sln"))
|
|
if len(solutions) > 1:
|
|
raise DiscoveryError("multiple .sln files found; set msbuild.solution")
|
|
if solutions:
|
|
return solutions[0]
|
|
projects = sorted(root.glob("*.vcxproj"))
|
|
if len(projects) > 1:
|
|
raise DiscoveryError("multiple .vcxproj files found; set msbuild.solution")
|
|
if projects:
|
|
return projects[0]
|
|
raise DiscoveryError("no root .sln or .vcxproj was found")
|
|
|
|
|
|
def discover_project(root: Path, config: HarnessConfig) -> DiscoveryResult:
|
|
root = root.resolve()
|
|
if config.project_type == "cmake":
|
|
entry = _cmake_entry(config.cmake.source_dir)
|
|
if entry is None:
|
|
raise DiscoveryError(
|
|
f"no CMake project found in {config.cmake.source_dir}"
|
|
)
|
|
return DiscoveryResult(ProjectSelection(ProjectKind.CMAKE, entry))
|
|
|
|
if config.project_type == "msbuild":
|
|
project = _single_msbuild(root, config.msbuild.solution)
|
|
return DiscoveryResult(ProjectSelection(ProjectKind.MSBUILD, project))
|
|
|
|
entry = _cmake_entry(root)
|
|
if entry is not None:
|
|
return DiscoveryResult(ProjectSelection(ProjectKind.CMAKE, entry))
|
|
|
|
solutions = sorted(root.glob("*.sln"))
|
|
if len(solutions) > 1:
|
|
raise DiscoveryError("multiple .sln files found; set msbuild.solution")
|
|
if solutions:
|
|
return DiscoveryResult(
|
|
ProjectSelection(ProjectKind.MSBUILD, solutions[0])
|
|
)
|
|
|
|
projects = sorted(root.glob("*.vcxproj"))
|
|
if len(projects) > 1:
|
|
raise DiscoveryError("multiple .vcxproj files found; set msbuild.solution")
|
|
if projects:
|
|
return DiscoveryResult(
|
|
ProjectSelection(ProjectKind.MSBUILD, projects[0])
|
|
)
|
|
|
|
cpp_files = find_cpp_files(root)
|
|
if cpp_files:
|
|
raise DiscoveryError(
|
|
"C/C++ files exist but no CMakeLists.txt, preset, .sln, or .vcxproj "
|
|
"was found; configure projectType and project path"
|
|
)
|
|
return DiscoveryResult(None, ())
|