Skip to content

Commit

Permalink
Fix Git/SSH on Windows
Browse files Browse the repository at this point in the history
There were two issues on my end:
1. `known_hosts` doesn't seem to be recognized
2. SSH Agent is ignored despite running

A workaround for 1. is to set the HOME environment variable on Windows, so I added a hint to suggest this. Ideally we would add a `certificate_check` callback to the remote callbacks, but the git2 crate doesn't expose whether the certificate check already succeeded, which makes it useless for this purpose (as we'd be prompting users to accept a certificate even though that certificate is already known to be valid).

As for 2., I changed the behavior from "check SSH Agent if some env variables exist" to "check SSH Agent and only fail if some env variables exist". On Windows SSH Agent doesn't use these env variables (but trying to communicate with it will still work), so now Windows properly works with SSH Agent.
  • Loading branch information
71 committed May 4, 2023
1 parent cd0023e commit 104f8e1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
31 changes: 23 additions & 8 deletions lib/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,30 @@ impl<'a> RemoteCallbacks<'a> {
return Ok(creds);
} else if let Some(username) = username_from_url {
if allowed_types.contains(git2::CredentialType::SSH_KEY) {
if std::env::var("SSH_AUTH_SOCK").is_ok()
|| std::env::var("SSH_AGENT_PID").is_ok()
{
tracing::info!(username, "using ssh_key_from_agent");
return git2::Cred::ssh_key_from_agent(username).map_err(|err| {
tracing::error!(err = %err);
err
});
// 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.
}
}

if let Some(ref mut cb) = self.get_ssh_key {
if let Some(path) = cb(username) {
tracing::info!(username, path = ?path, "using ssh_key");
Expand Down
16 changes: 11 additions & 5 deletions src/commands/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,17 @@ fn get_git_repo(store: &Store) -> Result<git2::Repository, CommandError> {

fn map_git_error(err: git2::Error) -> CommandError {
if err.class() == git2::ErrorClass::Ssh {
user_error_with_hint(
err.to_string(),
"Jujutsu uses libssh2, which doesn't respect ~/.ssh/config. Does `ssh -F /dev/null` \
to the host work?",
)
let hint =
if err.code() == git2::ErrorCode::Certificate && std::env::var_os("HOME").is_none() {
"The HOME environment variable is not set, and might be required for Git to \
successfully load certificates. Try setting it to the path of a directory that \
contains a `.ssh` directory."
} else {
"Jujutsu uses libssh2, which doesn't respect ~/.ssh/config. Does `ssh -F \
/dev/null` to the host work?"
};

user_error_with_hint(err.to_string(), hint)
} else {
user_error(err.to_string())
}
Expand Down

0 comments on commit 104f8e1

Please sign in to comment.