Package org.eclipse.egit.ui.internal.search

Source Code of org.eclipse.egit.ui.internal.search.CommitSearchQuery$SearchMatcher

/*******************************************************************************
*  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.internal.UIText;
import org.eclipse.egit.ui.internal.commit.RepositoryCommit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
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.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());
  }

  /**
   * Get text pattern being searched for
   *
   * @return pattern
   */
  public String getPattern() {
    return this.settings.getTextPattern();
  }

  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 = PatternUtils.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);
      List<RevCommit> commits = new LinkedList<RevCommit>();
      if (this.settings.isAllBranches()) {
        for (Ref ref : repository.getRefDatabase()
            .getRefs(Constants.R_HEADS).values())
          if (!ref.isSymbolic())
            commits.add(walk.parseCommit(ref.getObjectId()));
        for (Ref ref : repository.getRefDatabase()
            .getRefs(Constants.R_REMOTES).values())
          if (!ref.isSymbolic())
            commits.add(walk.parseCommit(ref.getObjectId()));
      } else {
        ObjectId headCommit = repository.resolve(Constants.HEAD);
        if (headCommit != null)
          commits.add(walk.parseCommit(headCommit));
      }

      if (!commits.isEmpty()) {
        walk.markStart(commits);
        for (RevCommit commit : walk) {
          if (monitor.isCanceled())
            throw new OperationCanceledException();
          for (SearchMatcher matcher : this.matchers)
            if (matcher.matches(pattern, commit)) {
              result.addResult(new RepositoryCommit(repository,
                  commit));
              break;
            }
        }
      }
    } 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;
  }

}
TOP

Related Classes of org.eclipse.egit.ui.internal.search.CommitSearchQuery$SearchMatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.