* stable-3.4: Prepare 3.4.2-SNAPSHOT builds JGit v3.4.1.201406201815-r Allow retrying connecting SshSession in case of an exception Change-Id: I7efb009b9e012637a16c57e2e93e074023b8e46c Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v3.5.0.201409071800-rc1
/* | /* | ||||
* Copyright (C) 2008, Google Inc. | |||||
* Copyright (C) 2008, 2014 Google Inc. | |||||
* and other copyright owners as documented in the project's IP log. | * and other copyright owners as documented in the project's IP log. | ||||
* | * | ||||
* This program and the accompanying materials are made available | * This program and the accompanying materials are made available | ||||
assertEquals("repo.or.cz", h.getHostName()); | assertEquals("repo.or.cz", h.getHostName()); | ||||
assertEquals("jex_junit", h.getUser()); | assertEquals("jex_junit", h.getUser()); | ||||
assertEquals(22, h.getPort()); | assertEquals(22, h.getPort()); | ||||
assertEquals(1, h.getConnectionAttempts()); | |||||
assertNull(h.getIdentityFile()); | assertNull(h.getIdentityFile()); | ||||
} | } | ||||
assertNotNull(h); | assertNotNull(h); | ||||
assertTrue(h.isBatchMode()); | assertTrue(h.isBatchMode()); | ||||
} | } | ||||
@Test | |||||
public void testAlias_ConnectionAttemptsDefault() throws Exception { | |||||
final Host h = osc.lookup("orcz"); | |||||
assertNotNull(h); | |||||
assertEquals(1, h.getConnectionAttempts()); | |||||
} | |||||
@Test | |||||
public void testAlias_ConnectionAttempts() throws Exception { | |||||
config("Host orcz\n" + "\tConnectionAttempts 5\n"); | |||||
final Host h = osc.lookup("orcz"); | |||||
assertNotNull(h); | |||||
assertEquals(5, h.getConnectionAttempts()); | |||||
} | |||||
@Test | |||||
public void testAlias_invalidConnectionAttempts() throws Exception { | |||||
config("Host orcz\n" + "\tConnectionAttempts -1\n"); | |||||
final Host h = osc.lookup("orcz"); | |||||
assertNotNull(h); | |||||
assertEquals(1, h.getConnectionAttempts()); | |||||
} | |||||
@Test | |||||
public void testAlias_badConnectionAttempts() throws Exception { | |||||
config("Host orcz\n" + "\tConnectionAttempts xxx\n"); | |||||
final Host h = osc.lookup("orcz"); | |||||
assertNotNull(h); | |||||
assertEquals(1, h.getConnectionAttempts()); | |||||
} | |||||
} | } |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<component id="org.eclipse.jgit" version="2"> | |||||
<resource path="META-INF/MANIFEST.MF"> | |||||
<filter comment="minor addition" id="924844039"> | |||||
<message_arguments> | |||||
<message_argument value="3.4.0"/> | |||||
<message_argument value="3.4.0"/> | |||||
</message_arguments> | |||||
</filter> | |||||
</resource> | |||||
</component> |
transportProtoLocal=Local Git Repository | transportProtoLocal=Local Git Repository | ||||
transportProtoSFTP=SFTP | transportProtoSFTP=SFTP | ||||
transportProtoSSH=SSH | transportProtoSSH=SSH | ||||
transportSSHRetryInterrupt=Interrupted while waiting for retry | |||||
treeEntryAlreadyExists=Tree entry "{0}" already exists. | treeEntryAlreadyExists=Tree entry "{0}" already exists. | ||||
treeFilterMarkerTooManyFilters=Too many markTreeFilters passed, maximum number is {0} (passed {1}) | treeFilterMarkerTooManyFilters=Too many markTreeFilters passed, maximum number is {0} (passed {1}) | ||||
treeIteratorDoesNotSupportRemove=TreeIterator does not support remove() | treeIteratorDoesNotSupportRemove=TreeIterator does not support remove() |
/***/ public String transportProtoLocal; | /***/ public String transportProtoLocal; | ||||
/***/ public String transportProtoSFTP; | /***/ public String transportProtoSFTP; | ||||
/***/ public String transportProtoSSH; | /***/ public String transportProtoSSH; | ||||
/***/ public String transportSSHRetryInterrupt; | |||||
/***/ public String treeEntryAlreadyExists; | /***/ public String treeEntryAlreadyExists; | ||||
/***/ public String treeFilterMarkerTooManyFilters; | /***/ public String treeFilterMarkerTooManyFilters; | ||||
/***/ public String treeIteratorDoesNotSupportRemove; | /***/ public String treeIteratorDoesNotSupportRemove; |
pass, host, port, hc); | pass, host, port, hc); | ||||
int retries = 0; | int retries = 0; | ||||
while (!session.isConnected() && retries < 3) { | |||||
while (!session.isConnected()) { | |||||
try { | try { | ||||
retries++; | retries++; | ||||
session.connect(tms); | session.connect(tms); | ||||
// Make sure our known_hosts is not outdated | // Make sure our known_hosts is not outdated | ||||
knownHosts(getJSch(hc, fs), fs); | knownHosts(getJSch(hc, fs), fs); | ||||
// if authentication failed maybe credentials changed at the | |||||
// remote end therefore reset credentials and retry | |||||
if (credentialsProvider != null && e.getCause() == null | |||||
&& e.getMessage().equals("Auth fail") //$NON-NLS-1$ | |||||
&& retries < 3) { | |||||
credentialsProvider.reset(uri); | |||||
session = createSession(credentialsProvider, fs, user, | |||||
pass, host, port, hc); | |||||
} else { | |||||
if (isAuthenticationCanceled(e)) { | |||||
throw e; | |||||
} else if (isAuthenticationFailed(e) | |||||
&& credentialsProvider != null) { | |||||
// if authentication failed maybe credentials changed at | |||||
// the remote end therefore reset credentials and retry | |||||
if (retries < 3) { | |||||
credentialsProvider.reset(uri); | |||||
session = createSession(credentialsProvider, fs, | |||||
user, pass, host, port, hc); | |||||
} else | |||||
throw e; | |||||
} else if (retries >= hc.getConnectionAttempts()) { | |||||
throw e; | throw e; | ||||
} else { | |||||
try { | |||||
Thread.sleep(1000); | |||||
session = createSession(credentialsProvider, fs, | |||||
user, pass, host, port, hc); | |||||
} catch (InterruptedException e1) { | |||||
throw new TransportException( | |||||
JGitText.get().transportSSHRetryInterrupt, | |||||
e1); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
private static boolean isAuthenticationFailed(JSchException e) { | |||||
return e.getCause() == null && e.getMessage().equals("Auth fail"); //$NON-NLS-1$ | |||||
} | |||||
private static boolean isAuthenticationCanceled(JSchException e) { | |||||
return e.getCause() == null && e.getMessage().equals("Auth cancel"); //$NON-NLS-1$ | |||||
} | |||||
private Session createSession(CredentialsProvider credentialsProvider, | private Session createSession(CredentialsProvider credentialsProvider, | ||||
FS fs, String user, final String pass, String host, int port, | FS fs, String user, final String pass, String host, int port, | ||||
final OpenSshConfig.Host hc) throws JSchException { | final OpenSshConfig.Host hc) throws JSchException { |
/* | /* | ||||
* Copyright (C) 2008-2009, Google Inc. | |||||
* Copyright (C) 2008, 2014, Google Inc. | |||||
* and other copyright owners as documented in the project's IP log. | * and other copyright owners as documented in the project's IP log. | ||||
* | * | ||||
* This program and the accompanying materials are made available | * This program and the accompanying materials are made available | ||||
h.user = OpenSshConfig.userName(); | h.user = OpenSshConfig.userName(); | ||||
if (h.port == 0) | if (h.port == 0) | ||||
h.port = OpenSshConfig.SSH_PORT; | h.port = OpenSshConfig.SSH_PORT; | ||||
if (h.connectionAttempts == 0) | |||||
h.connectionAttempts = 1; | |||||
h.patternsApplied = true; | h.patternsApplied = true; | ||||
return h; | return h; | ||||
} | } | ||||
for (final Host c : current) | for (final Host c : current) | ||||
if (c.strictHostKeyChecking == null) | if (c.strictHostKeyChecking == null) | ||||
c.strictHostKeyChecking = value; | c.strictHostKeyChecking = value; | ||||
} else if (StringUtils.equalsIgnoreCase( | |||||
"ConnectionAttempts", keyword)) { //$NON-NLS-1$ | |||||
try { | |||||
final int connectionAttempts = Integer.parseInt(dequote(argValue)); | |||||
if (connectionAttempts > 0) { | |||||
for (final Host c : current) | |||||
if (c.connectionAttempts == 0) | |||||
c.connectionAttempts = connectionAttempts; | |||||
} | |||||
} catch (NumberFormatException nfe) { | |||||
// ignore bad values | |||||
} | |||||
} | } | ||||
} | } | ||||
String strictHostKeyChecking; | String strictHostKeyChecking; | ||||
int connectionAttempts; | |||||
void copyFrom(final Host src) { | void copyFrom(final Host src) { | ||||
if (hostName == null) | if (hostName == null) | ||||
hostName = src.hostName; | hostName = src.hostName; | ||||
batchMode = src.batchMode; | batchMode = src.batchMode; | ||||
if (strictHostKeyChecking == null) | if (strictHostKeyChecking == null) | ||||
strictHostKeyChecking = src.strictHostKeyChecking; | strictHostKeyChecking = src.strictHostKeyChecking; | ||||
if (connectionAttempts == 0) | |||||
connectionAttempts = src.connectionAttempts; | |||||
} | } | ||||
/** | /** | ||||
public boolean isBatchMode() { | public boolean isBatchMode() { | ||||
return batchMode != null && batchMode.booleanValue(); | return batchMode != null && batchMode.booleanValue(); | ||||
} | } | ||||
/** | |||||
* @return the number of tries (one per second) to connect before | |||||
* exiting. The argument must be an integer. This may be useful | |||||
* in scripts if the connection sometimes fails. The default is | |||||
* 1. | |||||
* @since 3.4 | |||||
*/ | |||||
public int getConnectionAttempts() { | |||||
return connectionAttempts; | |||||
} | |||||
} | } | ||||
} | } |