Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Muskalla2011-08-17 12:18:57 +0000
committerMatthias Sohn2011-08-17 12:18:57 +0000
commit4620af17ae771f0fadb9c612466f90f94a520f4c (patch)
tree9892d3f43ea55c179168e2f529f1bd6a8cca489b /org.eclipse.egit.mylyn.ui/src/org
parentf1ad64cb5fa45b4a9769464e165d7cbac9a111c4 (diff)
downloadegit-4620af17ae771f0fadb9c612466f90f94a520f4c.tar.gz
egit-4620af17ae771f0fadb9c612466f90f94a520f4c.tar.xz
egit-4620af17ae771f0fadb9c612466f90f94a520f4c.zip
Support hyperlink detector for Commit ids
In order to have better navigation between code and tasks, this hyperlink detector recognizes commit ids inside the task descriptions and lets the user open the corresponding commit in the Commit editor. Change-Id: Ic60d11a45b8cb8cc9383e4120a84eae2f1859e32 Signed-off-by: Benjamin Muskalla <benjamin.muskalla@tasktop.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.egit.mylyn.ui/src/org')
-rw-r--r--org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/CommitHyperlinkDetector.java224
-rw-r--r--org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/Messages.java35
-rw-r--r--org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/messages.properties2
3 files changed, 261 insertions, 0 deletions
diff --git a/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/CommitHyperlinkDetector.java b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/CommitHyperlinkDetector.java
new file mode 100644
index 0000000000..cacd84882f
--- /dev/null
+++ b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/CommitHyperlinkDetector.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Benjamin Muskalla and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Benjamin Muskalla <benjamin.muskalla@tasktop.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.egit.internal.mylyn.ui;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.RepositoryCache;
+import org.eclipse.egit.core.RepositoryUtil;
+import org.eclipse.egit.ui.internal.commit.CommitEditor;
+import org.eclipse.egit.ui.internal.commit.RepositoryCommit;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Detects Git commit ids in task descriptions and allows users to open them in
+ * the commit editor.
+ */
+public class CommitHyperlinkDetector extends AbstractHyperlinkDetector {
+
+ private static class CommitHyperlink implements IHyperlink {
+
+ private IRegion region;
+
+ private String objectId;
+
+ private final Shell shell;
+
+ public CommitHyperlink(IRegion region, String objectId, Shell shell) {
+ this.shell = shell;
+ Assert.isNotNull(objectId);
+ Assert.isNotNull(region);
+ Assert.isNotNull(shell);
+
+ this.region = region;
+ this.objectId = objectId;
+ }
+
+ public IRegion getHyperlinkRegion() {
+ return region;
+ }
+
+ public String getTypeLabel() {
+ return null;
+ }
+
+ public String getHyperlinkText() {
+ return objectId;
+ }
+
+ public void open() {
+ try {
+ RepositoryCommit commit;
+ commit = searchCommit();
+ if (commit != null)
+ CommitEditor.openQuiet(commit);
+ else
+ informCommitNotFound();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ private void informCommitNotFound() {
+ MessageDialog
+ .openWarning(
+ shell,
+ Messages.CommitHyperlinkDetector_CommitNotFound,
+ NLS.bind(
+ Messages.CommitHyperlinkDetector_CommitNotFoundInRepositories,
+ objectId));
+ }
+
+ private RepositoryCommit searchCommit() throws IOException {
+ RepositoryUtil repositoryUtil = Activator.getDefault()
+ .getRepositoryUtil();
+ List<String> configuredRepositories = repositoryUtil
+ .getConfiguredRepositories();
+ RepositoryCache repositoryCache = Activator.getDefault()
+ .getRepositoryCache();
+ for (String repoDir : configuredRepositories) {
+ Repository repository = repositoryCache
+ .lookupRepository(new File(repoDir));
+ RevCommit commit = getCommit(repository);
+ if (commit != null)
+ return new RepositoryCommit(repository, commit);
+ }
+
+ return null;
+ }
+
+ private RevCommit getCommit(Repository repository) throws IOException {
+ RevWalk revWalk = null;
+ try {
+ revWalk = new RevWalk(repository);
+ return revWalk.parseCommit(ObjectId.fromString(objectId));
+ } catch (MissingObjectException e) {
+ // ignore
+ return null;
+ } catch (IncorrectObjectTypeException e) {
+ // ignore
+ return null;
+ } finally {
+ if (revWalk != null)
+ revWalk.release();
+ }
+
+ }
+
+ }
+
+ /**
+ * Detects and returns all available hyperlinks for the given {@link TextViewer} which link to a Git commit.
+ */
+ public IHyperlink[] detectHyperlinks(ITextViewer textViewer,
+ IRegion region, boolean canShowMultipleHyperlinks) {
+
+ IDocument document = textViewer.getDocument();
+ if (document == null || document.getLength() == 0)
+ return null;
+
+ String content;
+ int offset = region.getOffset();
+ int length = region.getLength();
+ try {
+ if (length == 0) {
+ IRegion lineInformation = document
+ .getLineInformationOfOffset(offset);
+ offset = lineInformation.getOffset();
+ length = lineInformation.getLength();
+ }
+ content = document.get(offset, length);
+ } catch (BadLocationException e) {
+ return null;
+ }
+
+ List<IHyperlink> hyperlinks = new ArrayList<IHyperlink>();
+ String[] words = content.split(" "); //$NON-NLS-1$
+ Shell shell = textViewer.getTextWidget().getShell();
+ for (String potentialId : words) {
+ String foundId = null;
+ int foundOffset = 0;
+ if (ObjectId.isId(potentialId)) {
+ foundId = potentialId;
+ foundOffset = offset;
+ } else if (potentialId.length() > Constants.OBJECT_ID_STRING_LENGTH) {
+ // could be beginning or end of a sentence
+ String potentialIdAtBeginning = potentialId.substring(0,
+ Constants.OBJECT_ID_STRING_LENGTH);
+ if (ObjectId.isId(potentialIdAtBeginning)) {
+ foundId = potentialIdAtBeginning;
+ foundOffset = offset;
+ } else {
+ String potentialIdAtEnd = potentialId.substring(potentialId
+ .length() - Constants.OBJECT_ID_STRING_LENGTH);
+ if (ObjectId.isId(potentialIdAtEnd)) {
+ foundId = potentialIdAtEnd;
+ foundOffset = potentialId.length()
+ - Constants.OBJECT_ID_STRING_LENGTH;
+ }
+
+ }
+ }
+ if (foundId != null) {
+ CommitHyperlink hyperlink = new CommitHyperlink(new Region(
+ foundOffset, Constants.OBJECT_ID_STRING_LENGTH),
+ foundId, shell);
+ hyperlinks.add(hyperlink);
+ }
+ offset += potentialId.length() + 1;
+ }
+
+ // filter hyperlinks that do not match original region
+ if (region.getLength() == 0) {
+ for (Iterator<IHyperlink> it = hyperlinks.iterator(); it.hasNext();) {
+ IHyperlink hyperlink = it.next();
+ IRegion hyperlinkRegion = hyperlink.getHyperlinkRegion();
+ if (!isInRegion(region, hyperlinkRegion))
+ it.remove();
+ }
+ }
+
+ if (hyperlinks.isEmpty())
+ return null;
+
+ return hyperlinks.toArray(new IHyperlink[hyperlinks.size()]);
+ }
+
+ private boolean isInRegion(IRegion detectInRegion, IRegion hyperlinkRegion) {
+ return detectInRegion.getOffset() >= hyperlinkRegion.getOffset()
+ && detectInRegion.getOffset() <= hyperlinkRegion.getOffset()
+ + hyperlinkRegion.getLength();
+ }
+
+}
diff --git a/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/Messages.java b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/Messages.java
new file mode 100644
index 0000000000..dea39824b8
--- /dev/null
+++ b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/Messages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Benjamin Muskalla and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Benjamin Muskalla <benjamin.muskalla@tasktop.com> - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.internal.mylyn.ui;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Text resources for the plugin. Strings here can be i18n-ed simpler and avoid
+ * duplicating strings.
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.egit.internal.mylyn.ui.messages"; //$NON-NLS-1$
+
+ /** */
+ public static String CommitHyperlinkDetector_CommitNotFound;
+
+ /** */
+ public static String CommitHyperlinkDetector_CommitNotFoundInRepositories;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/messages.properties b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/messages.properties
new file mode 100644
index 0000000000..5d79c38014
--- /dev/null
+++ b/org.eclipse.egit.mylyn.ui/src/org/eclipse/egit/internal/mylyn/ui/messages.properties
@@ -0,0 +1,2 @@
+CommitHyperlinkDetector_CommitNotFound=Commit not found
+CommitHyperlinkDetector_CommitNotFoundInRepositories=The commit {0} was not found in any of the configured repositories.

Back to the top