Merge branch 'stable-4.9'

* stable-4.9:
  Work around a Jsch bug: ensure the user name is set from URI
  Reintroduce protected method which removal broke EMF Compare

Change-Id: I335587eee279f91bd36c9ba9fc149b17a6db6110
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 034b20f..20d08c3 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -35,6 +35,18 @@
                 <message_argument value="processEntry(CanonicalTreeParser, CanonicalTreeParser, CanonicalTreeParser, DirCacheBuildIterator, WorkingTreeIterator, boolean)"/>
             </message_arguments>
         </filter>
+        <filter id="1141899266">
+            <message_arguments>
+                <message_argument value="3.5"/>
+                <message_argument value="4.9"/>
+                <message_argument value="processEntry(CanonicalTreeParser, CanonicalTreeParser, CanonicalTreeParser, DirCacheBuildIterator, WorkingTreeIterator, boolean)"/>
+            </message_arguments>
+        </filter>
+        <filter id="1143996420">
+            <message_arguments>
+                <message_argument value="processEntry(CanonicalTreeParser, CanonicalTreeParser, CanonicalTreeParser, DirCacheBuildIterator, WorkingTreeIterator, boolean)"/>
+            </message_arguments>
+        </filter>
     </resource>
     <resource path="src/org/eclipse/jgit/transport/http/HttpConnection.java" type="org.eclipse.jgit.transport.http.HttpConnection">
         <filter id="403767336">
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index d598f79..481cebc 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -611,6 +611,7 @@
 sourceRefDoesntResolveToAnyObject=Source ref {0} doesn''t resolve to any object.
 sourceRefNotSpecifiedForRefspec=Source ref not specified for refspec: {0}
 squashCommitNotUpdatingHEAD=Squash commit -- not updating HEAD
+sshUserNameError=Jsch error: failed to set SSH user name correctly to ''{0}''; using ''{1}'' picked up from SSH config file.
 sslFailureExceptionMessage=Secure connection to {0} could not be stablished because of SSL problems
 sslFailureInfo=A secure connection to {0}\ncould not be established because the server''s certificate could not be validated.
 sslFailureCause=SSL reported: {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index cc685e4..921c2dc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -670,6 +670,7 @@ public static JGitText get() {
 	/***/ public String sourceRefDoesntResolveToAnyObject;
 	/***/ public String sourceRefNotSpecifiedForRefspec;
 	/***/ public String squashCommitNotUpdatingHEAD;
+	/***/ public String sshUserNameError;
 	/***/ public String sslFailureExceptionMessage;
 	/***/ public String sslFailureInfo;
 	/***/ public String sslFailureCause;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index fc2fa0b..83b8363 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -483,6 +483,62 @@ private DirCacheEntry keep(DirCacheEntry e) {
 	 * @param ignoreConflicts
 	 *            see
 	 *            {@link ResolveMerger#mergeTrees(AbstractTreeIterator, RevTree, RevTree, boolean)}
+	 * @return <code>false</code> if the merge will fail because the index entry
+	 *         didn't match ours or the working-dir file was dirty and a
+	 *         conflict occurred
+	 * @throws MissingObjectException
+	 * @throws IncorrectObjectTypeException
+	 * @throws CorruptObjectException
+	 * @throws IOException
+	 * @since 3.5
+	 * @deprecated
+	 */
+	@Deprecated
+	protected boolean processEntry(CanonicalTreeParser base,
+			CanonicalTreeParser ours, CanonicalTreeParser theirs,
+			DirCacheBuildIterator index, WorkingTreeIterator work,
+			boolean ignoreConflicts) throws MissingObjectException,
+			IncorrectObjectTypeException, CorruptObjectException, IOException {
+		return processEntry(base, ours, theirs, index, work, ignoreConflicts,
+				null);
+	}
+
+	/**
+	 * Processes one path and tries to merge taking git attributes in account.
+	 * This method will do all trivial (not content) merges and will also detect
+	 * if a merge will fail. The merge will fail when one of the following is
+	 * true
+	 * <ul>
+	 * <li>the index entry does not match the entry in ours. When merging one
+	 * branch into the current HEAD, ours will point to HEAD and theirs will
+	 * point to the other branch. It is assumed that the index matches the HEAD
+	 * because it will only not match HEAD if it was populated before the merge
+	 * operation. But the merge commit should not accidentally contain
+	 * modifications done before the merge. Check the <a href=
+	 * "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
+	 * >git read-tree</a> documentation for further explanations.</li>
+	 * <li>A conflict was detected and the working-tree file is dirty. When a
+	 * conflict is detected the content-merge algorithm will try to write a
+	 * merged version into the working-tree. If the file is dirty we would
+	 * override unsaved data.</li>
+	 * </ul>
+	 *
+	 * @param base
+	 *            the common base for ours and theirs
+	 * @param ours
+	 *            the ours side of the merge. When merging a branch into the
+	 *            HEAD ours will point to HEAD
+	 * @param theirs
+	 *            the theirs side of the merge. When merging a branch into the
+	 *            current HEAD theirs will point to the branch which is merged
+	 *            into HEAD.
+	 * @param index
+	 *            the index entry
+	 * @param work
+	 *            the file in the working tree
+	 * @param ignoreConflicts
+	 *            see
+	 *            {@link ResolveMerger#mergeTrees(AbstractTreeIterator, RevTree, RevTree, boolean)}
 	 * @param attributes
 	 *            the attributes defined for this entry
 	 * @return <code>false</code> if the merge will fail because the index entry
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
index 7fe9066..eadfd69 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
@@ -53,14 +53,19 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.net.ConnectException;
 import java.net.UnknownHostException;
+import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.jcraft.jsch.JSch;
 import com.jcraft.jsch.JSchException;
@@ -80,6 +85,10 @@
  * to supply appropriate {@link UserInfo} to the session.
  */
 public abstract class JschConfigSessionFactory extends SshSessionFactory {
+
+	private static final Logger LOG = LoggerFactory
+			.getLogger(JschConfigSessionFactory.class);
+
 	private final Map<String, JSch> byIdentityFile = new HashMap<>();
 
 	private JSch defaultJSch;
@@ -177,6 +186,9 @@ private Session createSession(CredentialsProvider credentialsProvider,
 			FS fs, String user, final String pass, String host, int port,
 			final OpenSshConfig.Host hc) throws JSchException {
 		final Session session = createSession(hc, user, host, port, fs);
+		// Jsch will have overridden the explicit user by the one from the SSH
+		// config file...
+		setUserName(session, user);
 		// We retry already in getSession() method. JSch must not retry
 		// on its own.
 		session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -199,6 +211,28 @@ private Session createSession(CredentialsProvider credentialsProvider,
 		return session;
 	}
 
+	private void setUserName(Session session, String userName) {
+		// Jsch 0.1.54 picks up the user name from the ssh config, even if an
+		// explicit user name was given! We must correct that if ~/.ssh/config
+		// has a different user name.
+		if (userName == null || userName.isEmpty()
+				|| userName.equals(session.getUserName())) {
+			return;
+		}
+		try {
+			Class<?>[] parameterTypes = { String.class };
+			Method method = Session.class.getDeclaredMethod("setUserName", //$NON-NLS-1$
+					parameterTypes);
+			method.setAccessible(true);
+			method.invoke(session, userName);
+		} catch (NullPointerException | IllegalAccessException
+				| IllegalArgumentException | InvocationTargetException
+				| NoSuchMethodException | SecurityException e) {
+			LOG.error(MessageFormat.format(JGitText.get().sshUserNameError,
+					userName, session.getUserName()), e);
+		}
+	}
+
 	/**
 	 * Create a new remote session for the requested address.
 	 *