use super::client::{extract_list, managed_url};
use super::types::AppTemplate;
use crate::core::{hmac::AuthMode, http_client::get_with_auth};
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ManagedDetection {
MatchedTemplate(String),
ManagedModeAvailableNoMatch,
Inconclusive,
}
fn normalize_repo(repo: &str) -> String {
let trimmed = repo.trim().trim_end_matches('/');
let without_git = trimmed.strip_suffix(".git").unwrap_or(trimmed);
without_git.trim_end_matches('/').to_lowercase()
}
pub(crate) fn detect_managed_template(
auth_mode: &AuthMode,
git_repository: Option<&str>,
) -> ManagedDetection {
let Some(git_repository) = git_repository else {
return ManagedDetection::Inconclusive;
};
let target = normalize_repo(git_repository);
if target.is_empty() {
return ManagedDetection::Inconclusive;
}
let url = managed_url("/templates?includeUnpublished=true");
let response = match get_with_auth(auth_mode, &url) {
Ok(response) => response,
Err(_) => return ManagedDetection::Inconclusive,
};
if !response.status().is_success() {
return ManagedDetection::Inconclusive;
}
let value = match response.json::<serde_json::Value>() {
Ok(value) => value,
Err(_) => return ManagedDetection::Inconclusive,
};
let templates: Vec<AppTemplate> = match extract_list(value, &["templates"]) {
Ok(templates) => templates,
Err(_) => return ManagedDetection::Inconclusive,
};
for template in &templates {
let (Some(source_repo), Some(slug)) =
(template.source_repo.as_deref(), template.slug.as_deref())
else {
continue;
};
if normalize_repo(source_repo) == target {
return ManagedDetection::MatchedTemplate(slug.to_string());
}
}
ManagedDetection::ManagedModeAvailableNoMatch
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn normalize_repo_ignores_trailing_git_slash_and_case() {
assert_eq!(
normalize_repo("https://GitHub.com/Acme/clinic.git"),
normalize_repo("https://github.com/acme/clinic")
);
assert_eq!(
normalize_repo("https://github.com/acme/clinic/"),
"https://github.com/acme/clinic"
);
assert_eq!(
normalize_repo("https://github.com/acme/clinic.git/"),
"https://github.com/acme/clinic"
);
}
#[test]
fn normalize_repo_does_not_conflate_different_repositories() {
assert_ne!(
normalize_repo("https://github.com/acme/clinic"),
normalize_repo("https://github.com/acme/clinic-staging")
);
}
}