Skip to main content

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}