backhopper_core/suites/hints.rs
1// Copyright (C) 2026 Michael S. Klishin and Contributors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// See LICENSE-APACHE and LICENSE-MIT for details.
4
5//! Build-system detection: looks at the repo root to figure out
6//! which Erlang build tool is in use, so we can emit a footer hint
7//! after suite-selection output.
8
9use std::fs;
10use std::path::Path;
11
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(rename_all = "snake_case")]
16pub enum BuildSystem {
17 Rebar3,
18 ErlangMk,
19 Unknown,
20}
21
22impl BuildSystem {
23 /// Detects which Erlang build tool the repo uses. The heuristic:
24 /// * `rebar.config` (or `rebar.config.script`) present → rebar3
25 /// * `erlang.mk` present, OR a top-level `Makefile` includes it → erlang.mk
26 /// * otherwise → unknown
27 ///
28 /// rebar3 wins ties because RabbitMQ-style umbrella projects also
29 /// ship an erlang.mk, but per-app `rebar.config` is the more
30 /// authoritative declaration for the suite-running command.
31 pub fn detect(repo_root: &Path) -> Self {
32 if repo_root.join("rebar.config").is_file()
33 || repo_root.join("rebar.config.script").is_file()
34 {
35 return Self::Rebar3;
36 }
37 if repo_root.join("erlang.mk").is_file() {
38 return Self::ErlangMk;
39 }
40 if let Ok(mk) = fs::read_to_string(repo_root.join("Makefile"))
41 && (mk.contains("erlang.mk") || mk.contains("PROJECT ="))
42 {
43 return Self::ErlangMk;
44 }
45 Self::Unknown
46 }
47}