diff --git a/org.eclipse.jgit.ssh.apache.agent/resources/org/eclipse/jgit/internal/transport/sshd/agent/connector/Texts.properties b/org.eclipse.jgit.ssh.apache.agent/resources/org/eclipse/jgit/internal/transport/sshd/agent/connector/Texts.properties index f884adc08..6fce08366 100644 --- a/org.eclipse.jgit.ssh.apache.agent/resources/org/eclipse/jgit/internal/transport/sshd/agent/connector/Texts.properties +++ b/org.eclipse.jgit.ssh.apache.agent/resources/org/eclipse/jgit/internal/transport/sshd/agent/connector/Texts.properties @@ -13,4 +13,5 @@ msgSendFailed=Sending {0} bytes to SSH agent failed; {0} bytes not written msgSendFailed2=Sending {0} bytes to SSH agent failed: {1} - {2} msgSharedMemoryFailed=Could not set up shared memory for communicating with Pageant msgShortRead=Short read from SSH agent, expected {0} bytes, got {1} bytes; last read() returned {2} - +pageant=Pageant +unixDefaultAgent=ssh-agent diff --git a/org.eclipse.jgit.ssh.apache.agent/src/org/eclipse/jgit/internal/transport/sshd/agent/connector/Factory.java b/org.eclipse.jgit.ssh.apache.agent/src/org/eclipse/jgit/internal/transport/sshd/agent/connector/Factory.java index 1cbf0e41b..d7409b0c3 100644 --- a/org.eclipse.jgit.ssh.apache.agent/src/org/eclipse/jgit/internal/transport/sshd/agent/connector/Factory.java +++ b/org.eclipse.jgit.ssh.apache.agent/src/org/eclipse/jgit/internal/transport/sshd/agent/connector/Factory.java @@ -11,6 +11,8 @@ import java.io.File; import java.io.IOException; +import java.util.Collection; +import java.util.Collections; import org.eclipse.jgit.transport.sshd.agent.Connector; import org.eclipse.jgit.transport.sshd.agent.ConnectorFactory; @@ -41,4 +43,26 @@ public boolean isSupported() { public String getName() { return NAME; } + + /** + * {@inheritDoc} + *
+ * This factory returns on Windows a + * {@link org.eclipse.jgit.transport.sshd.agent.ConnectorFactory.ConnectorDescriptor + * ConnectorDescriptor} for the internal name "pageant"; on Unix one for + * "SSH_AUTH_SOCK". + *
+ */ + @Override + public Collection+ * The default implementation uses {@link ConnectorFactory#getDefault()} + *
* * @return the factory, or {@code null}Â if no SSH agent support is desired * @since 6.0 */ protected ConnectorFactory getConnectorFactory() { - return ConnectorFactoryProvider.getDefaultFactory(); + return ConnectorFactory.getDefault(); } /** diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java index b351d89ef..da98ea7fe 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java @@ -11,8 +11,10 @@ import java.io.File; import java.io.IOException; +import java.util.Collection; import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.internal.transport.sshd.agent.ConnectorFactoryProvider; /** * A factory for creating {@link Connector}s. This is a service provider @@ -24,14 +26,45 @@ */ public interface ConnectorFactory { + /** + * Retrieves the currently set default {@link ConnectorFactory}. This is the + * factory that is used unless overridden by the + * {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory}. + * + * @return the current default factory; may be {@code null} if none is set + * and the {@link java.util.ServiceLoader} cannot find any suitable + * implementation + */ + static ConnectorFactory getDefault() { + return ConnectorFactoryProvider.getDefaultFactory(); + } + + /** + * Sets a default {@link ConnectorFactory}. This is the factory that is used + * unless overridden by the + * {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory}. + *+ * If no default factory is set programmatically, an implementation is + * discovered via the {@link java.util.ServiceLoader}. + *
+ * + * @param factory + * {@link ConnectorFactory} to set, or {@code null}Â to revert to + * the default behavior of using the + * {@link java.util.ServiceLoader}. + */ + static void setDefault(ConnectorFactory factory) { + ConnectorFactoryProvider.setDefaultFactory(factory); + } + /** * Creates a new {@link Connector}. * * @param identityAgent * identifies the wanted agent connection; if {@code null}, the * factory is free to provide a {@link Connector} to a default - * agent. The value will typically come from the IdentityAgent - * setting in ~/.ssh/config. + * agent. The value will typically come from the + * {@code IdentityAgent} setting in {@code ~/.ssh/config}. * @param homeDir * the current local user's home directory as configured in the * {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory} @@ -58,4 +91,83 @@ Connector create(String identityAgent, File homeDir) */ String getName(); + /** + * {@link ConnectorDescriptor}s describe available {@link Connector}s a + * {@link ConnectorFactory} may provide. + *+ * A {@link ConnectorFactory} may support connecting to different SSH + * agents. Agents are identified by name; a user can choose a specific agent + * for instance via the {@code IdentityAgent} setting in + * {@code ~/.ssh/config}. + *
+ *+ * OpenSSH knows two built-in names: "none" for not using any agent, and + * "SSH_AUTH_SOCK" for using an agent that communicates over a Unix domain + * socket given by the value of environment variable {@code SSH_AUTH_SOCK}. + * Other agents can be specified in OpenSSH by specifying the socket file + * directly. (The "standard" OpenBSD OpenSSH knows only this communication + * mechanism.) "SSH_AUTH_SOCK" is also the default in OpenBSD OpenSSH if + * nothing is configured. + *
+ *+ * A particular {@link ConnectorFactory} may support more communication + * mechanisms or different agents. For instance, a factory on Windows might + * support Pageant, Win32-OpenSSH, or even git bash ssh-agent, and might + * accept internal names like "pageant", "openssh", "SSH_AUTH_SOCK" in + * {@link ConnectorFactory#create(String, File)} to choose among them. + *
+ * The {@link ConnectorDescriptor} interface and the + * {@link ConnectorFactory#getSupportedConnectors()} and + * {@link ConnectorFactory#getDefaultConnector()} methods provide a way for + * code using a {@link ConnectorFactory} to learn what the factory supports + * and thus implement some way by which a user can influence the default + * behavior if {@code IdentityAgent} is not set or + * {@link ConnectorFactory#create(String, File)} is called with + * {@code identityAgent == null}. + */ + interface ConnectorDescriptor { + + /** + * Retrieves the internal name of a supported {@link Connector}. The + * internal name is the one a user can specify for instance in the + * {@code IdentityAgent} setting in {@code ~/.ssh/config} to select the + * connector. + * + * @return the internal name; not empty + */ + @NonNull + String getIdentityAgent(); + + /** + * Retrieves a display name for a {@link Connector}, suitable for + * showing in a UI. + * + * @return the display name; properly localized and not empty + */ + @NonNull + String getDisplayName(); + } + + /** + * Tells which kinds of SSH agents this {@link ConnectorFactory} supports. + *+ * An implementation of this method should document the possible values it + * returns. + *
+ * + * @return an immutable collection of {@link ConnectorDescriptor}s, + * including {@link #getDefaultConnector()} and not including a + * descriptor for internal name "none" + */ + @NonNull + Collection