Coverage for src/debputy/build_support/buildsystem_detection.py: 12%
52 statements
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
1from typing import (
2 Optional,
3 TYPE_CHECKING,
4)
6from debputy.filesystem_scan import FSROOverlay
7from debputy.manifest_parser.base_types import BuildEnvironmentDefinition
8from debputy.manifest_parser.util import AttributePath
9from debputy.plugin.debputy.to_be_api_types import (
10 BuildSystemRule,
11)
12from debputy.plugin.plugin_state import run_in_context_of_plugin_wrap_errors
13from debputy.util import (
14 _error,
15 _debug_log,
16)
18if TYPE_CHECKING:
19 from debputy.highlevel_manifest import HighLevelManifest
22def default_build_environment_only(
23 manifest: "HighLevelManifest",
24) -> BuildEnvironmentDefinition:
25 build_envs = manifest.build_environments
26 if build_envs.environments:
27 _error(
28 'When automatic build system detection is used, the manifest cannot use "build-environments"'
29 )
30 build_env = build_envs.default_environment
31 assert build_env is not None
32 return build_env
35def auto_detect_buildsystem(
36 manifest: "HighLevelManifest",
37) -> Optional[BuildSystemRule]:
38 auto_detectable_build_systems = (
39 manifest.plugin_provided_feature_set.auto_detectable_build_systems
40 )
41 excludes = set()
42 options = []
43 _debug_log("Auto-detecting build systems.")
44 source_root = FSROOverlay.create_root_dir("", ".")
45 for ppadbs in auto_detectable_build_systems.values():
46 detected = ppadbs.detector(source_root)
47 if not isinstance(detected, bool):
48 _error(
49 f'The auto-detector for the build system {ppadbs.manifest_keyword} returned a "non-bool"'
50 f" ({detected!r}), which could be a bug in the plugin or the plugin relying on a newer"
51 " version of `debputy` that changed the auto-detection protocol."
52 )
53 if not detected:
54 _debug_log(
55 f"Skipping build system {ppadbs.manifest_keyword}: Detector returned False!"
56 )
57 continue
58 _debug_log(
59 f"Considering build system {ppadbs.manifest_keyword} as its Detector returned True!"
60 )
61 if ppadbs.auto_detection_shadow_build_systems:
62 names = ", ".join(
63 sorted(x for x in ppadbs.auto_detection_shadow_build_systems)
64 )
65 _debug_log(f"Build system {ppadbs.manifest_keyword} excludes: {names}!")
66 excludes.update(ppadbs.auto_detection_shadow_build_systems)
67 options.append(ppadbs)
69 if not options:
70 _debug_log("Zero candidates; continuing without a build system")
71 return None
73 if excludes:
74 names = ", ".join(sorted(x for x in excludes))
75 _debug_log(f"The following build systems have been excluded: {names}!")
76 remaining_options = [o for o in options if o.manifest_keyword not in excludes]
77 else:
78 remaining_options = options
80 if len(remaining_options) > 1:
81 names = ", ".join(o.manifest_keyword for o in remaining_options)
82 # TODO: This means adding an auto-detectable build system to an existing plugin causes FTBFS
83 # We need a better way of handling this. Probably the build systems should include
84 # a grace timer based on d/changelog. Anything before the changelog date is in
85 # "grace mode" and will not conflict with a build system that is. If all choices
86 # are in "grace mode", "oldest one" wins.
87 _error(
88 f"Multiple build systems match, please pick one explicitly (under `builds:`): {names}"
89 )
91 if not remaining_options:
92 names = ", ".join(o.build_system_rule_type.__name__ for o in options)
93 # TODO: Detect at registration time
94 _error(
95 f"Multiple build systems matched but they all shadowed each other: {names}."
96 f" There is a bug in at least one of them!"
97 )
99 chosen_build_system = remaining_options[0]
100 environment = default_build_environment_only(manifest)
101 bs = run_in_context_of_plugin_wrap_errors(
102 chosen_build_system.plugin_metadata.plugin_name,
103 chosen_build_system.constructor,
104 {
105 "environment": environment,
106 },
107 AttributePath.builtin_path(),
108 manifest,
109 )
110 bs.auto_generated_stem = ""
111 return bs