use serde::Deserialize;
use super::error::AuthError;
use super::oauth::{build_agent, map_response, read_body_capped};
use super::token::Token;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct OrgRepo {
pub name: String,
pub github_repo: String,
}
pub const ORG_REPOS_PATH: &str = "/_org/api/repos";
pub fn fetch_org_repos(base_url: &str, token: &Token) -> Result<Vec<OrgRepo>, AuthError> {
let agent = build_agent();
let result = agent
.get(format!("{base_url}{ORG_REPOS_PATH}"))
.header("Authorization", &format!("Bearer {}", token.as_str()))
.call();
match result {
Ok(resp) => {
let status = resp.status().as_u16();
let body = read_body_capped(resp, 1 << 20);
map_response::<Vec<OrgRepo>>(status, &body).map_err(|e| e.at_server(base_url))
}
Err(e) => Err(AuthError::Unreachable {
server: base_url.to_string(),
reason: e.to_string(),
}),
}
}
pub fn repo_segment_for<'a>(repos: &'a [OrgRepo], github_repo: &str) -> Option<&'a str> {
let wanted = github_repo
.trim()
.trim_end_matches(".git")
.to_ascii_lowercase();
repos
.iter()
.find(|r| r.github_repo.to_ascii_lowercase() == wanted)
.map(|r| r.name.as_str())
}
#[cfg(test)]
mod tests {
use super::*;
fn dir() -> Vec<OrgRepo> {
vec![
OrgRepo {
name: "widgets".into(),
github_repo: "acme/widgets".into(),
},
OrgRepo {
name: "gadgets".into(),
github_repo: "acme/gadgets".into(),
},
]
}
#[test]
fn segment_matches_case_insensitively_and_ignores_dot_git() {
let d = dir();
assert_eq!(repo_segment_for(&d, "acme/widgets"), Some("widgets"));
assert_eq!(repo_segment_for(&d, "Acme/Widgets.git"), Some("widgets"));
assert_eq!(repo_segment_for(&d, "acme/gadgets"), Some("gadgets"));
assert_eq!(repo_segment_for(&d, "acme/nope"), None);
assert_eq!(repo_segment_for(&[], "acme/widgets"), None);
}
#[test]
fn directory_decodes_the_wire_shape() {
let body = r#"[{"name":"widgets","github_repo":"acme/widgets"}]"#;
let d: Vec<OrgRepo> = super::super::oauth::map_response(200, body).unwrap();
assert_eq!(d, vec![dir()[0].clone()]);
}
}