Introduce SshSupport to centralize SSH related utility code
As discussed with Thomas here: https://git.eclipse.org/r/#/c/83506/31/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java@349 Move the code from ConfigureGerritAfterCloneTask to SshSupport and eliminate the slightly modified copy of the code from LfsConnectionFactory. Separate EGit commit will eliminate the code from ConfigureGerritAfterCloneTask. Change-Id: Ifb5adb1342e0fc1f2a70cddf693408d4e0ef7906 Signed-off-by: Markus Duft <markus.duft@ssi-schaefer.com>
This commit is contained in:
parent
e00f59b7fe
commit
4ca9bb5ab9
|
@ -47,9 +47,7 @@
|
||||||
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_ENCODING;
|
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_ENCODING;
|
||||||
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.ProxySelector;
|
import java.net.ProxySelector;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -66,20 +64,17 @@
|
||||||
import org.eclipse.jgit.lib.StoredConfig;
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
import org.eclipse.jgit.transport.HttpConfig;
|
import org.eclipse.jgit.transport.HttpConfig;
|
||||||
import org.eclipse.jgit.transport.HttpTransport;
|
import org.eclipse.jgit.transport.HttpTransport;
|
||||||
import org.eclipse.jgit.transport.RemoteSession;
|
|
||||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
|
||||||
import org.eclipse.jgit.transport.URIish;
|
import org.eclipse.jgit.transport.URIish;
|
||||||
import org.eclipse.jgit.transport.http.HttpConnection;
|
import org.eclipse.jgit.transport.http.HttpConnection;
|
||||||
import org.eclipse.jgit.util.FS;
|
|
||||||
import org.eclipse.jgit.util.HttpSupport;
|
import org.eclipse.jgit.util.HttpSupport;
|
||||||
import org.eclipse.jgit.util.io.MessageWriter;
|
import org.eclipse.jgit.util.SshSupport;
|
||||||
import org.eclipse.jgit.util.io.StreamCopyThread;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides means to get a valid LFS connection for a given repository.
|
* Provides means to get a valid LFS connection for a given repository.
|
||||||
*/
|
*/
|
||||||
public class LfsConnectionFactory {
|
public class LfsConnectionFactory {
|
||||||
|
|
||||||
|
private static final int SSH_AUTH_TIMEOUT_SECONDS = 5;
|
||||||
private static final String SCHEME_HTTPS = "https"; //$NON-NLS-1$
|
private static final String SCHEME_HTTPS = "https"; //$NON-NLS-1$
|
||||||
private static final String SCHEME_SSH = "ssh"; //$NON-NLS-1$
|
private static final String SCHEME_SSH = "ssh"; //$NON-NLS-1$
|
||||||
private static final Map<String, AuthCache> sshAuthCache = new TreeMap<>();
|
private static final Map<String, AuthCache> sshAuthCache = new TreeMap<>();
|
||||||
|
@ -193,10 +188,11 @@ private static Protocol.ExpiringAction getSshAuthentication(
|
||||||
// discover and authenticate; git-lfs does "ssh
|
// discover and authenticate; git-lfs does "ssh
|
||||||
// -p <port> -- <host> git-lfs-authenticate
|
// -p <port> -- <host> git-lfs-authenticate
|
||||||
// <project> <upload/download>"
|
// <project> <upload/download>"
|
||||||
String json = runSshCommand(u.setPath(""), //$NON-NLS-1$
|
String json = SshSupport.runSshCommand(u.setPath(""), //$NON-NLS-1$
|
||||||
db.getFS(),
|
null, db.getFS(),
|
||||||
"git-lfs-authenticate " + extractProjectName(u) + " " //$NON-NLS-1$//$NON-NLS-2$
|
"git-lfs-authenticate " + extractProjectName(u) + " " //$NON-NLS-1$//$NON-NLS-2$
|
||||||
+ purpose);
|
+ purpose,
|
||||||
|
SSH_AUTH_TIMEOUT_SECONDS);
|
||||||
|
|
||||||
action = Protocol.gson().fromJson(json,
|
action = Protocol.gson().fromJson(json,
|
||||||
Protocol.ExpiringAction.class);
|
Protocol.ExpiringAction.class);
|
||||||
|
@ -253,42 +249,6 @@ private static String extractProjectName(URIish u) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String runSshCommand(URIish sshUri, FS fs, String command)
|
|
||||||
throws IOException {
|
|
||||||
RemoteSession session = null;
|
|
||||||
Process process = null;
|
|
||||||
StreamCopyThread errorThread = null;
|
|
||||||
try (MessageWriter stderr = new MessageWriter()) {
|
|
||||||
session = SshSessionFactory.getInstance().getSession(sshUri, null,
|
|
||||||
fs, 5_000);
|
|
||||||
process = session.exec(command, 0);
|
|
||||||
errorThread = new StreamCopyThread(process.getErrorStream(),
|
|
||||||
stderr.getRawStream());
|
|
||||||
errorThread.start();
|
|
||||||
try (BufferedReader reader = new BufferedReader(
|
|
||||||
new InputStreamReader(process.getInputStream(),
|
|
||||||
org.eclipse.jgit.lib.Constants.CHARSET))) {
|
|
||||||
return reader.readLine();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (process != null) {
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
if (errorThread != null) {
|
|
||||||
try {
|
|
||||||
errorThread.halt();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Stop waiting and return anyway.
|
|
||||||
} finally {
|
|
||||||
errorThread = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (session != null) {
|
|
||||||
SshSessionFactory.getInstance().releaseSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param operation
|
* @param operation
|
||||||
* the operation to perform, e.g. Protocol.OPERATION_DOWNLOAD
|
* the operation to perform, e.g. Protocol.OPERATION_DOWNLOAD
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Markus Duft <markus.duft@ssi-schaefer.com>
|
||||||
|
* and other copyright owners as documented in the project's IP log.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available
|
||||||
|
* under the terms of the Eclipse Distribution License v1.0 which
|
||||||
|
* accompanies this distribution, is reproduced below, and is
|
||||||
|
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
*
|
||||||
|
* - Neither the name of the Eclipse Foundation, Inc. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.eclipse.jgit.util;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.annotations.Nullable;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||||
|
import org.eclipse.jgit.transport.RemoteSession;
|
||||||
|
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
import org.eclipse.jgit.util.io.MessageWriter;
|
||||||
|
import org.eclipse.jgit.util.io.StreamCopyThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra utilities to support usage of SSH.
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public class SshSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to execute a remote SSH command and read the first line of
|
||||||
|
* output.
|
||||||
|
*
|
||||||
|
* @param sshUri
|
||||||
|
* the SSH remote URI
|
||||||
|
* @param provider
|
||||||
|
* the {@link CredentialsProvider} or <code>null</code>.
|
||||||
|
* @param fs
|
||||||
|
* the {@link FS} implementation passed to
|
||||||
|
* {@link SshSessionFactory}
|
||||||
|
* @param command
|
||||||
|
* the remote command to execute.
|
||||||
|
* @param timeout
|
||||||
|
* a timeout in seconds.
|
||||||
|
* @return The first line of output read from stdout. Stderr is discarded.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static String runSshCommand(URIish sshUri,
|
||||||
|
@Nullable CredentialsProvider provider, FS fs, String command,
|
||||||
|
int timeout) throws IOException {
|
||||||
|
RemoteSession session = null;
|
||||||
|
Process process = null;
|
||||||
|
StreamCopyThread errorThread = null;
|
||||||
|
try (MessageWriter stderr = new MessageWriter()) {
|
||||||
|
session = SshSessionFactory.getInstance().getSession(sshUri,
|
||||||
|
provider, fs, 1000 * timeout);
|
||||||
|
process = session.exec(command, 0);
|
||||||
|
errorThread = new StreamCopyThread(process.getErrorStream(),
|
||||||
|
stderr.getRawStream());
|
||||||
|
errorThread.start();
|
||||||
|
try (BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(process.getInputStream(),
|
||||||
|
Constants.CHARSET))) {
|
||||||
|
return reader.readLine();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (errorThread != null) {
|
||||||
|
try {
|
||||||
|
errorThread.halt();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Stop waiting and return anyway.
|
||||||
|
} finally {
|
||||||
|
errorThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
if (session != null) {
|
||||||
|
SshSessionFactory.getInstance().releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue