grit/
trunk.rs

1use std::fmt;
2
3use crate::git::git;
4
5/// No local branch was found to have any of the supplied names.
6#[derive(Debug)]
7pub struct Error(Vec<String>);
8
9impl fmt::Display for Error {
10    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11        write!(f, "trunk not found: {}", self.0.join(", "))
12    }
13}
14
15/// Default names to consider when searching for local trunk branch, in order of
16/// preference. Overridden by the value of the [`GRIT_TRUNKS`] environment
17/// variable.
18pub const DEFAULT_TRUNKS: [&str; 2] = ["main", "master"];
19
20/// Environment variable to check for comma-separated list of local trunk branch
21/// names.  If the variable is unset, the value defaults to [`DEFAULT_TRUNKS`].
22pub const GRIT_TRUNKS: &str = "GRIT_TRUNKS";
23
24/// Returns the names of potential trunk branches, per [`GRIT_TRUNKS`] (if set)
25/// or [`DEFAULT_TRUNKS`].
26pub fn names() -> Vec<String> {
27    let trunks = std::env::var(GRIT_TRUNKS);
28    match trunks.as_ref() {
29        Ok(trunks) => trunks.split(',').map(str::to_owned).collect(),
30        Err(_) => DEFAULT_TRUNKS.map(str::to_owned).to_vec(),
31    }
32}
33
34/// Returns the name of the local trunk branch, if it can be determined.
35///
36/// # Errors
37///
38/// Will return [`Error`] if no local trunk branch is found.
39pub async fn local() -> Result<String, Error> {
40    let names = names();
41    for name in &names {
42        if git(["show-ref", name]).await.is_ok() {
43            return Ok(name.to_owned());
44        }
45    }
46    Err(Error(names))
47}