use bstr::BString;
use crate::helper;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Outcome {
pub identity: git_sec::identity::Account,
pub next: helper::NextAction,
}
pub type Result = std::result::Result<Option<Outcome>, Error>;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
UrlParse(#[from] git_url::parse::Error),
#[error("The 'url' field must be set when performing a 'get/fill' action")]
UrlMissing,
#[error(transparent)]
ContextDecode(#[from] context::decode::Error),
#[error(transparent)]
InvokeHelper(#[from] helper::Error),
#[error("Could not obtain identity for context: {}", { let mut buf = Vec::<u8>::new(); context.write_to(&mut buf).ok(); String::from_utf8_lossy(&buf).into_owned() })]
IdentityMissing { context: Context },
#[error("The handler asked to stop trying to obtain credentials")]
Quit,
#[error("Couldn't obtain {prompt}")]
Prompt { prompt: String, source: git_prompt::Error },
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Context {
pub protocol: Option<String>,
pub host: Option<String>,
pub path: Option<BString>,
pub username: Option<String>,
pub password: Option<String>,
pub url: Option<BString>,
pub quit: Option<bool>,
}
#[allow(clippy::result_large_err)]
pub fn helper_outcome_to_result(outcome: Option<helper::Outcome>, action: helper::Action) -> Result {
fn redact(mut ctx: Context) -> Context {
if let Some(pw) = ctx.password.as_mut() {
*pw = "<redacted>".into()
}
ctx
}
match (action, outcome) {
(helper::Action::Get(ctx), None) => Err(Error::IdentityMissing { context: redact(ctx) }),
(helper::Action::Get(ctx), Some(mut outcome)) => match outcome.consume_identity() {
Some(identity) => Ok(Some(Outcome {
identity,
next: outcome.next,
})),
None => Err(if outcome.quit {
Error::Quit
} else {
Error::IdentityMissing { context: redact(ctx) }
}),
},
(helper::Action::Store(_) | helper::Action::Erase(_), _ignore) => Ok(None),
}
}
pub mod context;