405647: clicking on review file URL should open file editor
Change-Id: I5c32a86e649f9ad7b04de3cfc7976b3cf9749b62
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=405647
Signed-off-by: chris.poon <chris.poon@tasktop.com>
diff --git a/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandlerTest.java b/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandlerTest.java
index 1c202df..7fd15bb 100644
--- a/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandlerTest.java
+++ b/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandlerTest.java
@@ -12,9 +12,31 @@
package org.eclipse.mylyn.internal.gerrit.ui;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import java.util.Arrays;
+
+import org.eclipse.mylyn.commons.workbench.EditorHandle;
import org.eclipse.mylyn.internal.gerrit.core.GerritConnector;
+import org.eclipse.mylyn.internal.gerrit.ui.editor.GerritTaskEditorPage;
+import org.eclipse.mylyn.reviews.core.model.IFileItem;
+import org.eclipse.mylyn.reviews.core.model.IReview;
+import org.eclipse.mylyn.reviews.core.model.IReviewItemSet;
import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.ui.TasksUi;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
import org.junit.Test;
/**
@@ -22,125 +44,243 @@
*/
public class GerritUrlHandlerTest {
+ private final TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND,
+ "http://review.mylyn.org");
+
private final GerritUrlHandler handler = new GerritUrlHandler();
+ private IWorkbenchPage page;
+
+ private String taskId;
+
+ private int patchSetNumber;
+
+ private String path;
+
@Test
public void testGetTaskId() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org");
assertEquals("123", handler.getTaskId(repository, "http://review.mylyn.org/123"));
}
@Test
public void testGetTaskIdTrailingSlashAfterId() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org");
assertEquals("123", handler.getTaskId(repository, "http://review.mylyn.org/123/foo/bar"));
}
@Test
public void testGetTaskIdInvalidId() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://mylyn.org/reviews");
- assertEquals(null, handler.getTaskId(repository, "http://mylyn.org/reviews/ab123"));
+ assertEquals(null, handler.getTaskId(repository, "http://review.mylyn.org/ab123"));
}
@Test
public void testGetTaskIdRepositoryMismatch() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals(null, handler.getTaskId(repository, "http://mylyn.org/reviews/123"));
}
@Test
public void testGetTaskIdSubPath() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://mylyn.org/reviews");
- assertEquals("123", handler.getTaskId(repository, "http://mylyn.org/reviews/123"));
- }
-
- @Test
- public void testGetTaskIdTrailingSlash() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals("123", handler.getTaskId(repository, "http://review.mylyn.org/123"));
}
@Test
+ public void testGetTaskIdTrailingSlash() {
+ TaskRepository trailingSlashRepository = new TaskRepository(GerritConnector.CONNECTOR_KIND,
+ "http://review.mylyn.org/");
+ assertEquals("123", handler.getTaskId(trailingSlashRepository, "http://review.mylyn.org/123"));
+ }
+
+ @Test
public void testGetTaskIdAbsolute() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals("123", handler.getTaskId(repository, "http://review.mylyn.org/#/c/123"));
}
@Test
public void testGetTaskIdLetters() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org");
assertEquals(null, handler.getTaskId(repository, "http://review.mylyn.org/#/c/abc/"));
}
@Test
public void testGetTaskIdEmpty() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org");
assertEquals(null, handler.getTaskId(repository, "http://review.mylyn.org/#/c//"));
}
@Test
public void testGetTaskIdAbsoluteTrailingSlash() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals("123", handler.getTaskId(repository, "http://review.mylyn.org/#/c/123/"));
}
@Test
public void testGetTaskIdPatchSet() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals("4698", handler.getTaskId(repository, "http://review.mylyn.org/#/c/4698/5"));
}
@Test
public void testGetTaskIdFile() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
assertEquals("4698", handler.getTaskId(repository, "http://review.mylyn.org/#/c/4698/5/foo/bar"));
}
@Test
public void testGetPatchSetNumberPatchSet() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/4698/5";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(5, handler.getPatchSetNumber(repository, url, taskId));
}
@Test
public void testGetPatchSetNumberPatchSetTrailingSlash() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/4698/5/";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(5, handler.getPatchSetNumber(repository, url, taskId));
}
@Test
public void testGetPatchSetNumberPatchSetFile() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/4698/5/foo/bar";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(5, handler.getPatchSetNumber(repository, url, taskId));
}
@Test
public void testGetPatchSetNumberNoneSpecified() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/4698";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(-1, handler.getPatchSetNumber(repository, url, taskId));
}
@Test
public void testGetPatchSetNumberNoneSpecifiedTrailingSlash() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/4698/";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(-1, handler.getPatchSetNumber(repository, url, taskId));
}
@Test
public void testGetPatchSetNumberNoneSpecifiedNotAnInteger() {
- TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://review.mylyn.org/");
String url = "http://review.mylyn.org/#/c/A1";
- String taskId = handler.getTaskId(repository, url);
+ taskId = handler.getTaskId(repository, url);
assertEquals(-1, handler.getPatchSetNumber(repository, url, taskId));
}
+
+ @Test
+ public void testGetPathNoneSpecified() {
+ assertPath(null, "http://review.mylyn.org/#/c/4698/5");
+ }
+
+ @Test
+ public void testGetPathNoneSpecifiedTrailingSlash() {
+ assertPath(null, "http://review.mylyn.org/#/c/4698/5/");
+ }
+
+ @Test
+ public void testGetPathNoneSpecifiedInvalidPatchNumber() {
+ assertPath(null, "http://review.mylyn.org/#/c/4698/-1abcd");
+ }
+
+ @Test
+ public void testGetPathNoneSpecifiedInvalidPatchNumberTrailingSlash() {
+ assertPath(null, "http://review.mylyn.org/#/c/4698/-1abcd/");
+ }
+
+ @Test
+ public void testGetPath() {
+ assertPath("foo/bar.java", "http://review.mylyn.org/#/c/4698/5/foo/bar.java");
+ }
+
+ @Test
+ public void testGetPathWithTrailingSlash() {
+ assertPath("foo/bar.java", "http://review.mylyn.org/#/c/4698/5/foo/bar.java/");
+ }
+
+ @Test
+ public void testOpenUrlWithInvalidReview() throws Exception {
+ String url = "http://review.mylyn.org/#/c/4698/1/foo/bar.java";
+ GerritUrlHandler spy = setUpOpenUrlTests(url);
+ doReturn(null).when(spy).revealPatchSet(any(EditorHandle.class), anyInt());
+
+ spy.openUrl(page, url, 0);
+
+ verify(spy, times(1)).revealPatchSet(any(EditorHandle.class), anyInt());
+ verify(spy, never()).getFileItem(any(IReview.class), anyInt(), anyString());
+ verify(spy, never()).openCompareEditor(null);
+ }
+
+ @Test
+ public void testOpenUrlWithValidPathOpenReview() throws Exception {
+ String url = "http://review.mylyn.org/#/c/4698/1/foo/bar.java";
+ GerritUrlHandler spy = setUpOpenUrlTests(url);
+ GerritTaskEditorPage page = mock(GerritTaskEditorPage.class);
+ IReview review = createMockReview();
+ when(page.getReview()).thenReturn(review);
+ doReturn(page).when(spy).revealPatchSet(any(EditorHandle.class), anyInt());
+ openReviewTest(spy, url);
+
+ verify(spy, times(1)).getFileItem(review, 1, "foo/bar.java");
+ assertEquals(path, spy.getFileItem(review, patchSetNumber, path).getName());
+ }
+
+ @Test
+ public void testOpenUrlWithInvalidPatchSetNumberOpenReview() throws Exception {
+ String url = "http://review.mylyn.org/#/c/4698/5/foo/bar.java";
+ GerritUrlHandler spy = setUpOpenUrlTests(url);
+ GerritTaskEditorPage page = mock(GerritTaskEditorPage.class);
+ IReview review = createMockReview();
+ when(page.getReview()).thenReturn(review);
+ doReturn(page).when(spy).revealPatchSet(any(EditorHandle.class), anyInt());
+ openReviewTest(spy, url);
+
+ verify(spy, times(1)).getFileItem(review, 5, "foo/bar.java");
+ assertNull(spy.getFileItem(review, patchSetNumber, path));
+ }
+
+ @Test
+ public void testOpenUrlWithInvalidPathOpenReview() throws Exception {
+ String url = "http://review.mylyn.org/#/c/4698/1/foo/bar.jav";
+ GerritUrlHandler spy = setUpOpenUrlTests(url);
+ GerritTaskEditorPage page = mock(GerritTaskEditorPage.class);
+ IReview review = createMockReview();
+ when(page.getReview()).thenReturn(review);
+ doReturn(page).when(spy).revealPatchSet(any(EditorHandle.class), anyInt());
+ openReviewTest(spy, url);
+
+ verify(spy, times(1)).getFileItem(review, 1, "foo/bar.jav");
+ assertNull(spy.getFileItem(review, patchSetNumber, path));
+ }
+
+ private GerritUrlHandler setUpOpenUrlTests(String url) {
+ page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ GerritUrlHandler spy = spy(handler);
+ TasksUi.getRepositoryManager().addRepository(repository);
+ taskId = spy.getTaskId(repository, url);
+ patchSetNumber = spy.getPatchSetNumber(repository, url, taskId);
+ path = spy.getFilePath(repository, url, taskId, patchSetNumber);
+
+ return spy;
+ }
+
+ private IReview createMockReview() {
+ IReview mockReview = mock(IReview.class);
+ IReviewItemSet mockSet = mock(IReviewItemSet.class);
+ IFileItem mockFile = mock(IFileItem.class);
+
+ when(mockFile.getName()).thenReturn("foo/bar.java");
+ when(mockSet.getId()).thenReturn("1");
+ when(mockSet.getItems()).thenReturn(Arrays.asList(mockFile));
+ when(mockReview.getSets()).thenReturn(Arrays.asList(mockSet));
+
+ return mockReview;
+ }
+
+ private void openReviewTest(GerritUrlHandler spy, String url) {
+ doNothing().when(spy).openCompareEditor(any(IFileItem.class));
+ spy.openUrl(page, url, 0);
+
+ verify(spy, times(1)).revealPatchSet(any(EditorHandle.class), anyInt());
+ verify(spy, times(1)).openCompareEditor(any(IFileItem.class));
+ }
+
+ private void assertPath(String expectedPath, String testUrl) {
+ taskId = handler.getTaskId(repository, testUrl);
+ patchSetNumber = handler.getPatchSetNumber(repository, testUrl, taskId);
+ assertEquals(expectedPath, handler.getFilePath(repository, testUrl, taskId, patchSetNumber));
+ }
}
diff --git a/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandler.java b/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandler.java
index 6d660ef..8bbc2d6 100644
--- a/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandler.java
+++ b/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/GerritUrlHandler.java
@@ -11,14 +11,19 @@
package org.eclipse.mylyn.internal.gerrit.ui;
+import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
+import org.eclipse.compare.CompareConfiguration;
import org.eclipse.mylyn.commons.workbench.EditorHandle;
import org.eclipse.mylyn.commons.workbench.browser.AbstractUrlHandler;
import org.eclipse.mylyn.internal.gerrit.core.GerritConnector;
import org.eclipse.mylyn.internal.gerrit.ui.editor.GerritTaskEditorPage;
+import org.eclipse.mylyn.reviews.core.model.IFileItem;
+import org.eclipse.mylyn.reviews.core.model.IReview;
+import org.eclipse.mylyn.reviews.core.model.IReviewItemSet;
import org.eclipse.mylyn.reviews.ui.spi.editor.ReviewSetSection;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.ui.TasksUi;
@@ -28,6 +33,8 @@
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.forms.editor.IFormPage;
+import com.google.common.base.Joiner;
+
/**
* @author Steffen Pingel
* @author Miles Parker
@@ -46,10 +53,15 @@
for (TaskRepository repository : TasksUi.getRepositoryManager().getRepositories(GerritConnector.CONNECTOR_KIND)) {
String taskId = getTaskId(repository, url);
if (taskId != null) {
- EditorHandle editorHandle = TasksUiUtil.openTaskWithResult(repository, taskId);
int patchSetNumber = getPatchSetNumber(repository, url, taskId);
+ EditorHandle editorHandle = TasksUiUtil.openTaskWithResult(repository, taskId);
if (patchSetNumber > 0) {
- revealPatchSet(editorHandle, patchSetNumber);
+ GerritTaskEditorPage gerritPage = revealPatchSet(editorHandle, patchSetNumber);
+ if (gerritPage != null) {
+ IFileItem file = getFileItem(gerritPage.getReview(), patchSetNumber,
+ getFilePath(repository, url, taskId, patchSetNumber));
+ openCompareEditor(file);
+ }
}
return editorHandle;
}
@@ -57,7 +69,13 @@
return null;
}
- private void revealPatchSet(EditorHandle editorHandle, Integer patchSetNumber) {
+ public void openCompareEditor(IFileItem file) {
+ if (file != null) {
+ GerritCompareUi.openFileComparisonEditor(new CompareConfiguration(), file, new GerritReviewBehavior(null));
+ }
+ }
+
+ protected GerritTaskEditorPage revealPatchSet(EditorHandle editorHandle, Integer patchSetNumber) {
IWorkbenchPart part = editorHandle.getPart();
if (part instanceof TaskEditor) {
TaskEditor taskEditor = (TaskEditor) part;
@@ -68,8 +86,10 @@
if (section != null && !section.getControl().isDisposed()) {
section.revealPatchSet(patchSetNumber);
}
+ return gerritPage;
}
}
+ return null;
}
public String getTaskId(TaskRepository repository, String url) {
@@ -89,10 +109,7 @@
* is not an integer.
*/
int getPatchSetNumber(TaskRepository repository, String url, String taskId) {
- String taskUrl = TasksUi.getRepositoryConnector(GerritConnector.CONNECTOR_KIND).getTaskUrl(repository.getUrl(),
- taskId);
- String urlQualifiers = StringUtils.remove(url, taskUrl);
- String[] fragments = StringUtils.split(urlQualifiers, "/"); //$NON-NLS-1$
+ String[] fragments = StringUtils.split(extractUrlQualifiers(repository, url, taskId), "/"); //$NON-NLS-1$
if (fragments.length > 0) {
String patchSetFragment = fragments[0];
try {
@@ -104,6 +121,37 @@
return -1;
}
+ public String getFilePath(TaskRepository repository, String url, String taskId, int patchSetNumber) {
+ if (patchSetNumber > 0) {
+ String[] fragments = StringUtils.split(extractUrlQualifiers(repository, url, taskId), "/"); //$NON-NLS-1$
+ if (fragments.length > 1) {
+ return Joiner.on("/").join(Arrays.copyOfRange(fragments, 1, fragments.length));
+ }
+ }
+ return null;
+ }
+
+ private String extractUrlQualifiers(TaskRepository repository, String url, String taskId) {
+ String taskUrl = TasksUi.getRepositoryConnector(GerritConnector.CONNECTOR_KIND).getTaskUrl(repository.getUrl(),
+ taskId);
+ return StringUtils.remove(url, taskUrl);
+ }
+
+ public IFileItem getFileItem(IReview review, final int patchSetNumber, final String path) {
+ if (review != null) {
+ for (IReviewItemSet set : review.getSets()) {
+ if (set.getId().equals(Integer.toString(patchSetNumber))) {
+ for (final IFileItem item : set.getItems()) {
+ if (path.equals(item.getName())) {
+ return item;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
@Override
public int getPriority() {
return 200;