diff options
| author | Kevin Sawicki | 2011-04-28 18:05:35 +0000 |
|---|---|---|
| committer | Chris Aniszczyk | 2011-04-28 19:06:09 +0000 |
| commit | 2e4b940d2c6e0bbd7bb2b413aad8f7a82ec93126 (patch) | |
| tree | 3c17d2d3198e69cae6525185f323b52f3322d463 | |
| parent | 849357793250c23b6562189f4ccdc13689d98a54 (diff) | |
| download | egit-2e4b940d2c6e0bbd7bb2b413aad8f7a82ec93126.tar.gz egit-2e4b940d2c6e0bbd7bb2b413aad8f7a82ec93126.tar.xz egit-2e4b940d2c6e0bbd7bb2b413aad8f7a82ec93126.zip | |
Add commit search query class.
This class performs a rev walk for the repositories
added to a search and matches rev commits against
the selected fields in that commit search.
Bug: 341652
Change-Id: I2a66e81424f1698b61a85cefe06f3e837c336fed
Signed-off-by: Kevin Sawicki <kevin@github.com>
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
3 files changed, 245 insertions, 0 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index 37ebc687af..688feb2ce1 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -3446,6 +3446,12 @@ public class UIText extends NLS { public static String CommitFileDiffViewer_OpenWorkingTreeVersionInEditorMenuLabel; /** */ + public static String CommitSearchQuery_Label; + + /** */ + public static String CommitSearchQuery_TaskSearchCommits; + + /** */ public static String CommitSearchResult_LabelPlural; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchQuery.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchQuery.java new file mode 100644 index 0000000000..90b6ff142f --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchQuery.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2011 GitHub Inc. + * 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: + * Kevin Sawicki (GitHub Inc.) - initial API and implementation + *******************************************************************************/ +package org.eclipse.egit.ui.internal.search; + +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.commit.RepositoryCommit; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.search.internal.core.text.PatternConstructor; +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; + +/** + * Commit search query class that runs a {@link RevWalk} for all + * {@link Repository} objects included in the {@link CommitSearchSettings} and + * matches all {@link RevCommit} objects against the search settings. + */ +public class CommitSearchQuery implements ISearchQuery { + + private abstract class SearchMatcher { + + abstract boolean matches(Pattern pattern, RevCommit commit); + + protected boolean matches(Pattern pattern, String input) { + return input != null && input.length() > 0 + && pattern.matcher(input).find(); + } + + } + + private class AuthorMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + PersonIdent author = commit.getAuthorIdent(); + if (author != null) + return matches(pattern, author.getName()) + || matches(pattern, author.getEmailAddress()); + else + return false; + } + } + + private class CommitterMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + PersonIdent committer = commit.getCommitterIdent(); + if (committer != null) + return matches(pattern, committer.getName()) + || matches(pattern, committer.getEmailAddress()); + else + return false; + } + } + + private class MessageMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + return matches(pattern, commit.getFullMessage()); + } + } + + private class CommitNameMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + return matches(pattern, commit.name()); + } + + } + + private class TreeMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + RevTree tree = commit.getTree(); + return tree != null ? matches(pattern, tree.name()) : false; + } + } + + private class ParentMatcher extends SearchMatcher { + + public boolean matches(Pattern pattern, RevCommit commit) { + for (RevCommit parent : commit.getParents()) + if (matches(pattern, parent.name())) + return true; + return false; + } + + } + + private CommitSearchResult result = new CommitSearchResult(this); + + private CommitSearchSettings settings; + + private List<SearchMatcher> matchers = new LinkedList<SearchMatcher>(); + + /** + * Create git search query + * + * @param settings + */ + public CommitSearchQuery(CommitSearchSettings settings) { + this.settings = settings; + + if (this.settings.isMatchAuthor()) + matchers.add(new AuthorMatcher()); + if (this.settings.isMatchCommitter()) + matchers.add(new CommitterMatcher()); + if (this.settings.isMatchMessage()) + matchers.add(new MessageMatcher()); + if (this.settings.isMatchCommit()) + matchers.add(new CommitNameMatcher()); + if (this.settings.isMatchTree()) + matchers.add(new TreeMatcher()); + if (this.settings.isMatchParents()) + matchers.add(new ParentMatcher()); + } + + private Repository getRepository(String name) throws IOException { + Repository repository = null; + File path = new File(name); + if (path.exists()) + repository = Activator.getDefault().getRepositoryCache() + .lookupRepository(path); + return repository; + } + + /** + * @see org.eclipse.search.ui.ISearchQuery#run(org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus run(IProgressMonitor monitor) + throws OperationCanceledException { + this.result.removeAll(); + + Pattern pattern = PatternConstructor.createPattern( + this.settings.getTextPattern(), + this.settings.isCaseSensitive(), this.settings.isRegExSearch()); + List<String> paths = settings.getRepositories(); + try { + for (String path : paths) { + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + Repository repo = getRepository(path); + if (repo == null) + continue; + + monitor.setTaskName(MessageFormat.format( + UIText.CommitSearchQuery_TaskSearchCommits, repo + .getDirectory().getParentFile().getName())); + walkRepository(repo, pattern, monitor); + } + } catch (IOException e) { + org.eclipse.egit.ui.Activator.handleError( + "Error searching commits", e, true); //$NON-NLS-1$ + } + return Status.OK_STATUS; + } + + private void walkRepository(Repository repository, Pattern pattern, + IProgressMonitor monitor) throws IOException { + RevWalk walk = new RevWalk(repository); + try { + walk.setRetainBody(true); + RevCommit commit = walk.parseCommit(repository + .resolve(Constants.HEAD)); + if (commit != null) { + walk.markStart(commit); + commit = walk.next(); + while (commit != null) { + if (monitor.isCanceled()) + throw new OperationCanceledException(); + for (SearchMatcher matcher : this.matchers) + if (matcher.matches(pattern, commit)) { + result.addResult(new RepositoryCommit(repository, + commit)); + break; + } + commit = walk.next(); + } + } + } finally { + walk.dispose(); + } + } + + /** + * @see org.eclipse.search.ui.ISearchQuery#getLabel() + */ + public String getLabel() { + return UIText.CommitSearchQuery_Label; + } + + /** + * @see org.eclipse.search.ui.ISearchQuery#canRerun() + */ + public boolean canRerun() { + return true; + } + + /** + * @see org.eclipse.search.ui.ISearchQuery#canRunInBackground() + */ + public boolean canRunInBackground() { + return true; + } + + /** + * @see org.eclipse.search.ui.ISearchQuery#getSearchResult() + */ + public ISearchResult getSearchResult() { + return this.result; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 77a854315b..b6c40070c0 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -1027,6 +1027,8 @@ CommitFileDiffViewer_SelectOneCommitMessage=Please select exactly one commit CommitGraphTable_CommitId=Id CommitGraphTable_Committer=Committer CommitGraphTable_CompareWithEachOtherInTreeMenuLabel=Compare with each other in &Tree +CommitSearchQuery_Label=Git Commit Search +CommitSearchQuery_TaskSearchCommits=Searching commits in {0} CommitSearchResult_LabelPlural=Git Commit Search - {0} matches CommitSearchResult_LabelSingle=Git Commit Search - 1 match CommitSelectionDialog_BuildingCommitListMessage=Building commit list |
