Skip to main content

ephemeris_forge/
state.rs

1//! Evaluated repository-settings input consumed by the forge adapters.
2
3use ephemeris_token::Token;
4use facet::Facet;
5use facet_value::Value;
6
7/// A forge-tagged repository configuration.
8///
9/// The configuration stays undecoded until the forge is known. Decode it
10/// into the adapter's `Backend::Config` with [`crate::redecode`].
11#[derive(Clone, Debug, Eq, Facet, PartialEq)]
12#[facet(deny_unknown_fields)]
13pub struct RemoteState {
14    /// The forge the configuration targets.
15    pub forge: Forge,
16    /// The desired repository state in the forge's own vocabulary.
17    pub config: Value,
18}
19
20/// Supported forges.
21#[derive(Clone, Copy, Debug, Eq, Facet, PartialEq)]
22#[repr(u8)]
23pub enum Forge {
24    /// Self-hosted Forgejo.
25    #[facet(rename = "forgejo")]
26    Forgejo,
27    /// GitHub, hosted or Enterprise Server.
28    #[facet(rename = "github")]
29    GitHub,
30}
31
32impl Forge {
33    /// Default API base used when a caller does not provide an override.
34    ///
35    /// Forgejo has no single default host, unlike GitHub's one API, so a
36    /// Forgejo caller without an explicit forge URL gets `None` rather than a
37    /// guess.
38    #[must_use]
39    pub const fn default_url(self) -> Option<&'static str> {
40        match self {
41            Self::Forgejo => None,
42            Self::GitHub => Some("https://api.github.com"),
43        }
44    }
45
46    /// The username that pairs with a token for HTTP Git access.
47    #[must_use]
48    pub const fn git_username(self) -> &'static str {
49        match self {
50            Self::Forgejo => "oauth2",
51            Self::GitHub => "x-access-token",
52        }
53    }
54
55    /// The `Authorization` header value of the forge's Cargo registry.
56    ///
57    /// Forgejo wants a `Bearer` scheme and GitHub takes the raw token.
58    #[must_use]
59    pub fn cargo_authorization(self, token: &Token) -> Token {
60        match self {
61            Self::Forgejo => Token::new(format!("Bearer {}", token.expose())),
62            Self::GitHub => token.clone(),
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use ephemeris_token::Token;
70
71    use super::Forge;
72
73    #[test]
74    fn forgejo_cargo_authorization_uses_the_bearer_scheme() {
75        let token = Token::new("secret");
76        assert_eq!(
77            Forge::Forgejo.cargo_authorization(&token).expose(),
78            "Bearer secret"
79        );
80        assert_eq!(Forge::GitHub.cargo_authorization(&token).expose(), "secret");
81    }
82
83    #[test]
84    fn github_defaults_to_its_own_api_host() {
85        assert_eq!(Forge::GitHub.default_url(), Some("https://api.github.com"));
86    }
87
88    #[test]
89    fn forgejo_has_no_default_host() {
90        assert_eq!(Forge::Forgejo.default_url(), None);
91    }
92}