/******************************************************************************* * Copyright (C) 2008, 2016 Roger C. Soares <rogersoares@intelinet.com.br> 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: * Thomas Wolf <thomas.wolf@paranor.ch> - rewrite as Job *******************************************************************************/ package org.eclipse.egit.ui.internal.history; import java.io.IOException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.egit.ui.Activator; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; /** * This class executes the search function for the find toolbar. To avoid * consuming all the memory in the system, this class limits the maximum results * it stores. * * @see FindToolbar * @see FindResults */ public class FindToolbarJob extends Job { private static final int MAX_RESULTS = 20000; private static final ISchedulingRule SINGLE_JOB_RULE = new ISchedulingRule() { @Override public boolean contains(ISchedulingRule rule) { return this == rule; } @Override public boolean isConflicting(ISchedulingRule rule) { return this == rule; } }; String pattern; SWTCommit[] fileRevisions; boolean ignoreCase; boolean findInCommitId; boolean findInComments; boolean findInAuthor; boolean findInCommitter; boolean findInReference; private final FindResults findResults; /** * Creates a new history search job. * * @param name * of the job * @param findResults * to fill */ public FindToolbarJob(String name, FindResults findResults) { super(name); this.findResults = findResults; setRule(SINGLE_JOB_RULE); } private boolean find(String needle, String text) { if (text == null) { return false; } if (ignoreCase) { return text.toLowerCase().indexOf(needle) >= 0; } return text.indexOf(needle) >= 0; } @Override protected IStatus run(IProgressMonitor monitor) { findResults.clear(); if (pattern == null || pattern.isEmpty() || fileRevisions == null || fileRevisions.length == 0) { return Status.OK_STATUS; } String findPattern = pattern; if (ignoreCase) { findPattern = pattern.toLowerCase(); } int totalRevisions = fileRevisions.length; SubMonitor progress = SubMonitor.convert(monitor, totalRevisions); for (int i = 0; i < totalRevisions; i++) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } if (findResults.size() >= MAX_RESULTS) { findResults.setOverflow(); break; } // Finds for the pattern in the revision history. SWTCommit revision = fileRevisions[i]; try { revision.parseBody(); } catch (IOException e) { Activator.logError("Error parsing body", e); //$NON-NLS-1$ continue; } if (findInCommitId && find(findPattern, revision.getId().name())) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } findResults.add(i, revision); continue; } if (findInComments && find(findPattern, revision.getFullMessage())) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } findResults.add(i, revision); continue; } if (findInAuthor && (find(findPattern, revision.getAuthorIdent().getName()) || find(findPattern, revision.getAuthorIdent().getEmailAddress()))) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } findResults.add(i, revision); continue; } if (findInCommitter && (find(findPattern, revision.getCommitterIdent().getName()) || find(findPattern, revision.getCommitterIdent().getEmailAddress()))) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } findResults.add(i, revision); continue; } if (findInReference) { for (int j = 0; j < revision.getRefCount(); j++) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } Ref ref = revision.getRef(j); String refName = ref.getName(); refName = Repository.shortenRefName(refName); if (find(findPattern, refName)) { if (progress.isCanceled()) { return Status.CANCEL_STATUS; } findResults.add(i, revision); break; } } } progress.worked(1); } return progress.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; } }