mod commands;
pub use commands::{run_config_oci, run_oci};
pub use xbp_oci::{
parse_image_ref, resolve_auth_from_candidates, DefaultOciPromoter, DefaultOciResolver,
OciAuth, OciAuthRequest, OciClient, OciPromoter, OciRef, OciResolver,
};
use crate::config::SshConfig;
use crate::strategies::XbpConfig;
use std::env;
pub fn auth_candidates_for_registry(
registry: &str,
project: &XbpConfig,
) -> Vec<(String, Option<String>, String)> {
let mut out = Vec::new();
if let (Ok(user), Ok(token)) = (env::var("XBP_OCI_USERNAME"), env::var("XBP_OCI_TOKEN")) {
if !token.trim().is_empty() {
out.push(("env:XBP_OCI_*".into(), Some(user), token));
}
}
let registry_cfg = project
.oci
.as_ref()
.and_then(|o| o.registries.get(registry));
let username = registry_cfg.and_then(|r| r.username.clone());
let wants_github = registry.contains("ghcr.io")
|| registry_cfg
.and_then(|r| r.token_source.as_deref())
.map(|s| s.eq_ignore_ascii_case("github"))
.unwrap_or(false);
if wants_github {
for key in ["XBP_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"] {
if let Ok(token) = env::var(key) {
if !token.trim().is_empty() {
out.push((
format!("env:{key}"),
username
.clone()
.or_else(|| Some("x-access-token".into())),
token,
));
}
}
}
if let Ok(cfg) = SshConfig::load() {
if let Some(token) = cfg.github_oauth2_key.filter(|t| !t.trim().is_empty()) {
out.push((
"global:github".into(),
username.clone().or_else(|| Some("x-access-token".into())),
token,
));
}
if let Some(oci) = cfg.oci {
if let Some(cred) = oci.registries.get(registry) {
if let Some(token) = cred.token.clone().filter(|t| !t.trim().is_empty()) {
out.push((
format!("global:oci:{registry}"),
cred.username.clone().or(username.clone()),
token,
));
}
}
}
}
} else if let Ok(cfg) = SshConfig::load() {
if let Some(oci) = cfg.oci {
if let Some(cred) = oci.registries.get(registry) {
if let Some(token) = cred.token.clone().filter(|t| !t.trim().is_empty()) {
out.push((
format!("global:oci:{registry}"),
cred.username.clone().or(username),
token,
));
}
}
}
}
out
}