pub struct ManagedClient<R: ProcessRunner = JobRunner> { /* private fields */ }Expand description
A CliClient wrapper that adds two opt-in concerns the CLI wrappers
(vcs-git, vcs-jj, vcs-github, vcs-gitlab) all share, without touching a
single call site:
- Lock-contention retry (
is_lock_contention) per aRetryPolicy— off by default (RetryPolicy::none); enable withwith_retry. Safe even for mutating commands, since lock contention is a clean pre-execution failure. - Credential injection from an opt-in
CredentialProvider— off by default (no provider); attach one withwith_credentials. When a forge token-env binding is configured (with_token_env), every command run through this client gets the resolved token in that environment variable (e.g.GH_TOKEN). Backends that inject the secret differently (git’scredential.helper) instead callresolve_credentialat the command site. Resolution happens once per call, before the retry loop.
Both default to inert, so a client with neither configured behaves exactly
like a bare CliClient.
Implementations§
Source§impl ManagedClient<JobRunner>
impl ManagedClient<JobRunner>
Sourcepub fn new(program: impl AsRef<OsStr>) -> Self
pub fn new(program: impl AsRef<OsStr>) -> Self
A retrying client driving program on the real job-backed runner (no retry
until with_retry).
Source§impl<R: ProcessRunner> ManagedClient<R>
impl<R: ProcessRunner> ManagedClient<R>
Sourcepub fn with_runner(program: impl AsRef<OsStr>, runner: R) -> Self
pub fn with_runner(program: impl AsRef<OsStr>, runner: R) -> Self
A retrying client driving program on runner — inject a fake in tests.
Sourcepub fn with_retry(self, policy: RetryPolicy) -> Self
pub fn with_retry(self, policy: RetryPolicy) -> Self
Set the lock-contention retry policy (opt-in; default is no retry).
Sourcepub fn retry_policy(&self) -> RetryPolicy
pub fn retry_policy(&self) -> RetryPolicy
The active retry policy.
Sourcepub fn with_credentials(self, provider: Arc<dyn CredentialProvider>) -> Self
pub fn with_credentials(self, provider: Arc<dyn CredentialProvider>) -> Self
Attach a CredentialProvider (opt-in; default is none → ambient auth).
The provider is consulted per operation: automatically when a
with_token_env binding is set, or
on demand via resolve_credential.
Precedence: a resolved token is injected after any
default_env, so the provider wins over a
static default and over the ambient CLI login. Cancellation: a
default_cancel_on token bounds the
spawned process, not provider resolution — if your provider does slow I/O
(a vault lookup), bound it yourself.
Sourcepub fn with_token_env(
self,
service: CredentialService,
var: &'static str,
) -> Self
pub fn with_token_env( self, service: CredentialService, var: &'static str, ) -> Self
Bind the resolved token to an environment variable injected on every
command this client runs (the forge case: GH_TOKEN, GITLAB_TOKEN). The
service tags the CredentialRequest. No effect without a provider.
Sourcepub fn has_credentials(&self) -> bool
pub fn has_credentials(&self) -> bool
Whether a credential provider is configured.
Sourcepub async fn resolve_credential(
&self,
service: CredentialService,
host: Option<&str>,
) -> Result<Option<Credential>>
pub async fn resolve_credential( &self, service: CredentialService, host: Option<&str>, ) -> Result<Option<Credential>>
Resolve a credential for service/host from the configured provider, or
Ok(None) if no provider is set or it defers to ambient auth. Backends
that inject the secret at the command site (git’s credential.helper) call
this directly; the forge token-env path uses it internally.
Sourcepub fn default_timeout(self, timeout: Duration) -> Self
pub fn default_timeout(self, timeout: Duration) -> Self
Apply a default timeout to every command this client builds.
Sourcepub fn default_env(
self,
key: impl AsRef<OsStr>,
value: impl AsRef<OsStr>,
) -> Self
pub fn default_env( self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>, ) -> Self
Set an environment variable on every command this client builds.
Sourcepub fn default_env_remove(self, key: impl AsRef<OsStr>) -> Self
pub fn default_env_remove(self, key: impl AsRef<OsStr>) -> Self
Remove an inherited environment variable on every command this client builds.
Sourcepub fn default_cancel_on(self, token: CancellationToken) -> Self
pub fn default_cancel_on(self, token: CancellationToken) -> Self
Cancel every command this client builds when token fires.
Sourcepub fn command<I, S>(&self, args: I) -> Command
pub fn command<I, S>(&self, args: I) -> Command
Build a Command for this client’s program (passthrough).
Sourcepub fn command_in<I, S>(&self, dir: &Path, args: I) -> Command
pub fn command_in<I, S>(&self, dir: &Path, args: I) -> Command
Build a Command bound to dir (passthrough).
Sourcepub async fn run(&self, call: impl IntoCommand<R>) -> Result<String>
pub async fn run(&self, call: impl IntoCommand<R>) -> Result<String>
Like CliClient::run, with credential injection and lock-retry.
Sourcepub async fn run_unit(&self, call: impl IntoCommand<R>) -> Result<()>
pub async fn run_unit(&self, call: impl IntoCommand<R>) -> Result<()>
Like CliClient::run_unit, with credential injection and lock-retry.
Sourcepub async fn output_string(
&self,
call: impl IntoCommand<R>,
) -> Result<ProcessResult<String>>
pub async fn output_string( &self, call: impl IntoCommand<R>, ) -> Result<ProcessResult<String>>
Like CliClient::output_string, with credential injection. No lock-retry:
output_string returns Ok on a non-zero exit (it captures the result), so a
lock failure surfaces as an Ok here, not an Err the retry predicate could
match — route mutations that need lock-retry through
run/run_unit instead.
Sourcepub async fn run_untrimmed(&self, call: impl IntoCommand<R>) -> Result<String>
pub async fn run_untrimmed(&self, call: impl IntoCommand<R>) -> Result<String>
Like run, but returns stdout verbatim — no trim_end.
For content-returning verbs (a file’s bytes at a rev, a diff, a raw
template render) where the trailing newline(s) are part of the value, not
noise: trimming them corrupts a read-modify-write round-trip and desyncs a
diff’s last hunk from its @@ line count. Exit-checked like run; no
lock-retry (a content read is not a mutation).
Sourcepub async fn probe(&self, call: impl IntoCommand<R>) -> Result<bool>
pub async fn probe(&self, call: impl IntoCommand<R>) -> Result<bool>
Like CliClient::probe (zero-or-nonzero exit → bool), with credential
injection and lock-retry.
Sourcepub async fn exit_code(&self, call: impl IntoCommand<R>) -> Result<i32>
pub async fn exit_code(&self, call: impl IntoCommand<R>) -> Result<i32>
Like CliClient::exit_code (the raw exit code; a spawn failure or timeout
still errors), with credential injection and lock-retry.
Sourcepub async fn parse<T>(
&self,
call: impl IntoCommand<R>,
parser: impl FnOnce(&str) -> T + Send,
) -> Result<T>where
T: Send,
pub async fn parse<T>(
&self,
call: impl IntoCommand<R>,
parser: impl FnOnce(&str) -> T + Send,
) -> Result<T>where
T: Send,
Like CliClient::parse (credential injection applied; the FnOnce parser
can’t be re-run, so lock-retry does not — parsing is a read, where lock
contention is not a concern anyway).
Sourcepub async fn try_parse<T>(
&self,
call: impl IntoCommand<R>,
parser: impl FnOnce(&str) -> Result<T> + Send,
) -> Result<T>where
T: Send,
pub async fn try_parse<T>(
&self,
call: impl IntoCommand<R>,
parser: impl FnOnce(&str) -> Result<T> + Send,
) -> Result<T>where
T: Send,
Like CliClient::try_parse (credential injection applied; FnOnce parser,
and a read, so no lock-retry).