gix_credentials/protocol/
mod.rs1use bstr::BString;
2
3use crate::helper;
4
5#[derive(Debug, Clone, Eq, PartialEq)]
7pub struct Outcome {
8 pub identity: gix_sec::identity::Account,
10 pub next: helper::NextAction,
12}
13
14pub type Result = std::result::Result<Option<Outcome>, Error>;
16
17#[derive(Debug, thiserror::Error)]
19#[expect(missing_docs)]
20pub enum Error {
21 #[error(transparent)]
22 UrlParse(#[from] gix_url::parse::Error),
23 #[error("Either 'url' field or both 'protocol' and 'host' fields must be provided")]
24 UrlMissing,
25 #[error(transparent)]
26 ContextDecode(#[from] context::decode::Error),
27 #[error(transparent)]
28 InvokeHelper(#[from] helper::Error),
29 #[error("Could not configure credential helpers")]
30 ConfigureCredentialHelpers {
31 #[source]
32 source: Box<dyn std::error::Error + Send + Sync + 'static>,
33 },
34 #[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() })]
35 IdentityMissing { context: Context },
36 #[error("The handler asked to stop trying to obtain credentials")]
37 Quit,
38 #[error("Couldn't obtain {prompt}")]
39 Prompt { prompt: String, source: gix_prompt::Error },
40}
41
42#[derive(Debug, Default, Clone, Eq, PartialEq)]
44pub struct Context {
45 pub options: ContextOptions,
47 pub protocol: Option<String>,
49 pub host: Option<String>,
51 pub path: Option<BString>,
54 pub username: Option<String>,
56 pub password: Option<String>,
58 pub oauth_refresh_token: Option<String>,
60 pub password_expiry_utc: Option<gix_date::SecondsSinceUnixEpoch>,
62 pub url: Option<BString>,
66 pub quit: Option<bool>,
68}
69
70#[derive(Debug, Clone, Copy, Eq, PartialEq)]
72pub struct ContextOptions {
73 pub protect_protocol: bool,
77}
78
79impl Default for ContextOptions {
80 fn default() -> Self {
81 ContextOptions { protect_protocol: true }
82 }
83}
84
85#[expect(
87 clippy::result_large_err,
88 reason = "will be removed once `gix-error` is used consistently"
89)]
90pub fn helper_outcome_to_result(outcome: Option<helper::Outcome>, action: helper::Action) -> Result {
91 match (action, outcome) {
92 (helper::Action::Get(ctx), None) => Err(Error::IdentityMissing {
93 context: ctx.redacted(),
94 }),
95 (helper::Action::Get(ctx), Some(mut outcome)) => match outcome.consume_identity() {
96 Some(identity) => Ok(Some(Outcome {
97 identity,
98 next: outcome.next,
99 })),
100 None => Err(if outcome.quit {
101 Error::Quit
102 } else {
103 Error::IdentityMissing {
104 context: ctx.redacted(),
105 }
106 }),
107 },
108 (helper::Action::Store(_) | helper::Action::Erase(_), _ignore) => Ok(None),
109 }
110}
111
112pub mod context;