Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

git: only try to use ssh-agent once per connection (#1970) #2008

Merged
merged 1 commit into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed bugs

* SSH authentication could hang when ssh-agent couldn't be reached
[#1970](https://github.com/martinvonz/jj/issues/1970)

## [0.8.0] - 2023-07-09

### Breaking changes
Expand Down
32 changes: 10 additions & 22 deletions lib/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ impl<'a> RemoteCallbacks<'a> {
}
// TODO: We should expose the callbacks to the caller instead -- the library
// crate shouldn't read environment variables.
let mut tried_ssh_agent = false;
callbacks.credentials(move |url, username_from_url, allowed_types| {
let span = tracing::debug_span!("RemoteCallbacks.credentials");
let _ = span.enter();
Expand All @@ -890,28 +891,15 @@ impl<'a> RemoteCallbacks<'a> {
return Ok(creds);
} else if let Some(username) = username_from_url {
if allowed_types.contains(git2::CredentialType::SSH_KEY) {
// Try to get the SSH key from the agent by default, and report an error
// only if it _seems_ like that's what the user wanted.
//
// Note that the env variables read below are **not** the only way to
// communicate with the agent, which is why we request a key from it no
// matter what.
match git2::Cred::ssh_key_from_agent(username) {
Ok(key) => {
tracing::info!(username, "using ssh_key_from_agent");
return Ok(key);
}
Err(err) => {
if std::env::var("SSH_AUTH_SOCK").is_ok()
|| std::env::var("SSH_AGENT_PID").is_ok()
{
tracing::error!(err = %err);
return Err(err);
}
// There is no agent-related env variable so we
// consider that the user doesn't care about using
// the agent and proceed.
}
// Try to get the SSH key from the agent once. We don't even check if
// $SSH_AUTH_SOCK is set because Windows uses another mechanism.
if !tried_ssh_agent {
tracing::info!(username, "using ssh_key_from_agent");
tried_ssh_agent = true;
return git2::Cred::ssh_key_from_agent(username).map_err(|err| {
tracing::error!(err = %err);
err
});
}

if let Some(ref mut cb) = self.get_ssh_key {
Expand Down