Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance normalize uri #14

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit.feature/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<parent>
<groupId>org.sonatype.m2e.egit</groupId>
<artifactId>org.sonatype.m2e.egit.parent</artifactId>
<version>0.14.0-SNAPSHOT</version>
<version>0.15.0-SNAPSHOT</version>
</parent>

<artifactId>org.sonatype.m2e.egit.feature</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit.repository/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.sonatype.m2e.egit</groupId>
<artifactId>org.sonatype.m2e.egit.parent</artifactId>
<version>0.14.0-SNAPSHOT</version>
<version>0.15.0-SNAPSHOT</version>
</parent>

<artifactId>org.sonatype.m2e.egit.repository</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit.tests/.classpath
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/"/>
<classpathentry kind="output" path="target/classes"/>
Expand Down
5 changes: 3 additions & 2 deletions org.sonatype.m2e.egit.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Maven SCM Handler for EGit Tests
Bundle-SymbolicName: org.sonatype.m2e.egit.tests;singleton:=true
Bundle-Version: 0.14.0.qualifier
Bundle-Version: 0.15.0.qualifier
Bundle-Vendor: Sonatype
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.eclipse.m2e.core,
org.eclipse.m2e.scm,
org.eclipse.m2e.tests.common,
org.eclipse.m2e.maven.runtime,
org.eclipse.jgit;bundle-version="[3.0.0,5.0.0)",
org.sonatype.m2e.egit,
org.eclipse.core.runtime,
org.eclipse.core.resources,
Expand Down
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit.tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<parent>
<groupId>org.sonatype.m2e.egit</groupId>
<artifactId>org.sonatype.m2e.egit.parent</artifactId>
<version>0.14.0-SNAPSHOT</version>
<version>0.15.0-SNAPSHOT</version>
</parent>

<artifactId>org.sonatype.m2e.egit.tests</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@
package org.sonatype.m2e.egit.tests;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.m2e.scm.MavenProjectScmInfo;
import org.eclipse.ui.PlatformUI;
import org.sonatype.m2e.egit.internal.EgitScmHandler;

Expand Down Expand Up @@ -42,4 +51,118 @@ public void testCheckoutNoMaster() throws Exception {

assertWorkspaceProject("git-test");
}

public void testNormalizeURI() throws Exception {
EgitScmHandlerExt handler = new EgitScmHandlerExt();

String uri = EgitScmHandler.GIT_SCM_ID + "[email protected]:errai/errai.git/errai-common";

assertEquals("ssh://[email protected]/errai/errai.git", handler.normalizeUri(uri, false));
assertEquals("git://github.com/errai/errai.git", handler.normalizeUri(uri, true));
}

/**
* Authentication success is mocked.
* Expected:
* - no exception,
* - EgitScmHandler.runCloneOperation() is called,
* - EgitScmHandler.onAuthFailed() is not called.
*/
public void testAuthFailed1() throws Exception {
EgitScmHandlerExt handler = new EgitScmHandlerExt();
String url = EgitScmHandlerExt.GIT_SCM_ID + "[email protected]:errai/errai.git/errai-common";
MavenProjectScmInfo scmInfo = new MavenProjectScmInfo(url, null, null, "HEAD", url, url);
CoreException exc = null;
try {
handler.checkoutProject(scmInfo, null, new NullProgressMonitor());
} catch (CoreException e) {
exc = e;
}
assertNull(exc);
assertEquals(1, handler.callsOfrunCloneOperation);
assertEquals(0, handler.callsOfonAuthFailed);
}

/**
* Authentication failure is mocked, user selects cancel to connect anonymously.
* Expected:
* - no exception,
* - EgitScmHandler.runCloneOperation() is called,
* - EgitScmHandler.onAuthFailed() is called.
*/
public void testAuthFailed2() throws Exception {
EgitScmHandlerExt handler = new EgitScmHandlerExt(true, false);
String url = EgitScmHandlerExt.GIT_SCM_ID + "[email protected]:errai/errai.git/errai-common";
MavenProjectScmInfo scmInfo = new MavenProjectScmInfo(url, null, null, "HEAD", url, url);
CoreException exc = null;
try {
handler.checkoutProject(scmInfo, null, new NullProgressMonitor());
} catch (CoreException e) {
exc = e;
}
assertNull(exc);
assertEquals(1, handler.callsOfrunCloneOperation);
assertEquals(1, handler.callsOfonAuthFailed);
}

/**
* Authentication failure is mocked, user selects ok to connect anonymously.
* Expected:
* - no exception,
* - EgitScmHandler.runCloneOperation() is called twice,
* - EgitScmHandler.onAuthFailed() is called.
*/
public void testAuthFailed3() throws Exception {
EgitScmHandlerExt handler = new EgitScmHandlerExt(true, true);
String url = EgitScmHandlerExt.GIT_SCM_ID + "[email protected]:errai/errai.git/errai-common";
MavenProjectScmInfo scmInfo = new MavenProjectScmInfo(url, null, null, "HEAD", url, url);
CoreException exc = null;
try {
handler.checkoutProject(scmInfo, null, new NullProgressMonitor());
} catch (CoreException e) {
exc = e;
}
assertNull(exc);
assertEquals(2, handler.callsOfrunCloneOperation);
assertEquals(1, handler.callsOfonAuthFailed);
}

class EgitScmHandlerExt extends EgitScmHandler {
boolean throwAuthFailed = false;
boolean accessAnonymously = false;

int callsOfonAuthFailed = 0;
int callsOfrunCloneOperation = 0;

EgitScmHandlerExt() {}

EgitScmHandlerExt(boolean throwAuthFailed, boolean accessAnonymously) {
this.throwAuthFailed = throwAuthFailed;
this.accessAnonymously = accessAnonymously;
}

//Make normalizeUri(String, boolean) accessible.
@Override
public String normalizeUri(String uri, boolean avoidSSH) throws URISyntaxException {
return super.normalizeUri(uri, avoidSSH);
}

//Mock super
@Override
protected void runCloneOperation(URIish uri, File location, String refName, SubMonitor pm)
throws InvocationTargetException, IOException, InterruptedException {
callsOfrunCloneOperation++;
if(throwAuthFailed) {
throwAuthFailed = false; //next time run smoothly.
throw new InvocationTargetException(new TransportException("Auth failed"));
}
}

//Mock super
@Override
protected boolean onAuthFailed() {
callsOfonAuthFailed++;
return accessAnonymously;
}
}
}
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit/.classpath
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/"/>
<classpathentry kind="output" path="target/classes"/>
Expand Down
4 changes: 2 additions & 2 deletions org.sonatype.m2e.egit/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.sonatype.m2e.egit;singleton:=true
Bundle-Version: 0.14.0.qualifier
Bundle-Version: 0.15.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.eclipse.m2e.core;bundle-version="[1.0.0,2.0.0)",
org.eclipse.m2e.scm;bundle-version="[1.0.0,2.0.0)",
org.eclipse.m2e.core.ui;bundle-version="[1.0.0,2.0.0)",
Expand Down
2 changes: 1 addition & 1 deletion org.sonatype.m2e.egit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<parent>
<groupId>org.sonatype.m2e.egit</groupId>
<artifactId>org.sonatype.m2e.egit.parent</artifactId>
<version>0.14.0-SNAPSHOT</version>
<version>0.15.0-SNAPSHOT</version>
</parent>

<artifactId>org.sonatype.m2e.egit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.egit.core.op.CloneOperation;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.m2e.scm.MavenProjectScmInfo;
import org.eclipse.m2e.scm.spi.ScmHandler;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -48,25 +53,41 @@ public void checkoutProject(MavenProjectScmInfo info, File location, IProgressMo
log.debug("Checking out project from {} to {}", info, location);

SubMonitor pm = SubMonitor.convert(monitor, 100);
try {
URIish uri = getUri(info);

String refName = getRefName(info);

CloneOperation clone = new CloneOperation(uri, true /* allSelected */, new ArrayList<Ref>(), location, refName,
"origin", getTimeout());
clone.run(pm.newChild(99));

fixAutoCRLF(clone.getGitDir());
} catch(InvocationTargetException e) {
Throwable cause = e.getTargetException();
throw new CoreException(new Status(IStatus.ERROR, getClass().getName(), cause.getMessage(), cause));
} catch(IOException e) {
throw new CoreException(new Status(IStatus.ERROR, getClass().getName(), e.getMessage(), e));
} catch(URISyntaxException e) {
throw new CoreException(new Status(IStatus.ERROR, getClass().getName(), e.getMessage(), e));
} catch(InterruptedException e) {
// The monitor was canceled
try {
boolean avoidSSH = false;
URIish uri = null;
boolean repeat = true;
//The cycle will run maximum twice, first time with avoidSSH = false,
//second, if user chooses it, with avoidSSH = true.
while(repeat) {
repeat = false;
try {
uri = getUri(info, avoidSSH);
String refName = getRefName(info);
runCloneOperation(uri, location, refName, pm);
//
break;
} catch(InvocationTargetException e) {
Throwable cause = e.getTargetException();
if(!avoidSSH && uri != null && "ssh".equals(uri.getScheme()) && cause instanceof TransportException) {
boolean accessGitAnonimously = onAuthFailed();
if(accessGitAnonimously) {
avoidSSH = true;
repeat = true;
continue;
} else {
pm.setCanceled(true);
break;
}
}
throw new CoreException(new Status(IStatus.ERROR, getClass().getName(), cause.getMessage(), cause));
} catch(IOException | URISyntaxException e) {
throw new CoreException(new Status(IStatus.ERROR, getClass().getName(), e.getMessage(), e));
} catch(InterruptedException e) {
// The monitor was canceled
}
}
} finally {
pm.done();
}
Expand All @@ -76,9 +97,32 @@ protected int getTimeout() {
return 30;
}

protected URIish getUri(MavenProjectScmInfo info) throws URISyntaxException {
protected void runCloneOperation(URIish uri, File location, String refName, SubMonitor pm)
throws InvocationTargetException, IOException, InterruptedException {
CloneOperation clone = new CloneOperation(uri, true /* allSelected */, new ArrayList<Ref>(), location, refName,
"origin", getTimeout());
clone.run(pm.newChild(99));

fixAutoCRLF(clone.getGitDir());
}

protected boolean onAuthFailed() {
final boolean[] result = new boolean[]{false};
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method run() of type new Runnable(){} must override a superclass method.

This error shows up because the project BREE is J2SE-1.5 and I happen to have a Java 5 JDK, exhibiting the issue.

We should bump the BREE to 1.7, as well as the project version to 0.15.0-SNAPSHOT

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
String title = "Authentication failed";
String message = "The clone URL uses the SSH protocol. It seems you do not have a valid SSH key. Do you want to continue with the GIT protocol anonymously?";
result[0] = MessageDialog.openConfirm(shell, title, message);
}
});
return result[0];
}

protected URIish getUri(MavenProjectScmInfo info, boolean avoidSSH) throws URISyntaxException {
String url = info.getRepositoryUrl();
url = normalizeUri(url);
url = normalizeUri(url, avoidSSH);

URIish uri = new URIish(url);

Expand All @@ -91,7 +135,7 @@ protected URIish getUri(MavenProjectScmInfo info) throws URISyntaxException {
return uri;
}

protected String normalizeUri(String uri) throws URISyntaxException {
protected String normalizeUri(String uri, boolean avoidSSH) throws URISyntaxException {
if(!uri.startsWith(GIT_SCM_ID)) {
return uri;
}
Expand All @@ -101,6 +145,27 @@ protected String normalizeUri(String uri) throws URISyntaxException {
throw new URISyntaxException(uri, "Invalid git URI");
}

if(avoidSSH) {
String gitPrefix = "git://";
//Replace @ with ://
if(uri.startsWith("git@")) {
uri = gitPrefix + uri.substring(4);
}
//Replace ':' after host with '/' for git
if(uri.startsWith(gitPrefix)) {
int slash = uri.indexOf("/", gitPrefix.length());
int colon = uri.indexOf(":", gitPrefix.length());
if(colon > 0 && slash > colon) {
uri = uri.substring(0, colon) + "/" + uri.substring(colon + 1);
}
}
}
//3. Remove tail after .git
int dotGit = uri.indexOf(".git");
if(dotGit >= 0 && uri.length() > dotGit + 4) {
uri = uri.substring(0, dotGit + 4);
}

URIish gitUri = new URIish(uri);
if(gitUri.getScheme() == null) {
if(gitUri.getHost() == null || "file".equals(gitUri.getHost())) {
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<groupId>org.sonatype.m2e.egit</groupId>
<artifactId>org.sonatype.m2e.egit.parent</artifactId>
<version>0.14.0-SNAPSHOT</version>
<version>0.15.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Maven SCM Handler for EGit Parent</name>

Expand Down