blob: 05640a2e84f220a3961dae73d53371328e7d1258 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
* Copyright (C) 2012, Robin Stocker <robin@nibor.org>
*
* 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
*******************************************************************************/
package org.eclipse.egit.core.internal.job;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceRuleFactory;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.egit.core.internal.util.ResourceUtil;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.lib.Repository;
/**
* Utility class for scheduling rules
*
*/
public class RuleUtil {
/**
* Calculates an {@link ISchedulingRule} for Jobs working on the index of a
* repository. The rule consists of all projects belonging to the
* repository. If you schedule two jobs working on different resources of
* the same repository you have to ensure that these jobs cannot run in
* parallel because the Git index lock fails if another thread is already
* owning the lock. Thus it is a good practice to lock all projects
* belonging to a Git repository when executing a write operation on the
* index of a repository in a Job.
*
* @param repository
* @return scheduling rule
*/
public static ISchedulingRule getRule(Repository repository) {
IProject[] projects = getProjects(repository);
if (projects.length == 0)
return null;
return new MultiRule(projects);
}
/**
* Calculates a {@link ISchedulingRule} for Jobs working on the index of
* multiple repositories, see {@link #getRule(Repository)}.
*
* @param repositories
* @return scheduling rule
*/
public static ISchedulingRule getRuleForRepositories(Collection<Repository> repositories) {
ISchedulingRule result = null;
for (Repository repository : repositories) {
ISchedulingRule rule = getRule(repository);
result = MultiRule.combine(result, rule);
}
return result;
}
/**
* Calculates a {@link ISchedulingRule} for all repositories related to the
* given resources.
*
* @see RuleUtil#getRule(Repository)
* @param resources
* @return scheduling rule
*/
public static ISchedulingRule getRuleForRepositories(IResource[] resources) {
ISchedulingRule result = null;
Set<Repository> repositories = new HashSet<Repository>();
for (IResource resource : resources) {
RepositoryMapping mapping = RepositoryMapping.getMapping(resource);
if (mapping != null)
repositories.add(mapping.getRepository());
}
for (Repository repository : repositories) {
ISchedulingRule rule = getRule(repository);
result = MultiRule.combine(result, rule);
}
return result;
}
/**
* Calculates a {@link ISchedulingRule} for all containers of the paths that
* are in the workspace.
*
* @param paths
* @return scheduling rule
*/
public static ISchedulingRule getRuleForContainers(Collection<IPath> paths) {
List<ISchedulingRule> rules = new ArrayList<ISchedulingRule>();
IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace()
.getRuleFactory();
for (IPath path : paths) {
IResource resource = ResourceUtil.getResourceForLocation(path, false);
if (resource != null) {
IContainer container = resource.getParent();
ISchedulingRule rule = ruleFactory.modifyRule(container);
if (rule != null)
rules.add(rule);
}
}
if (rules.size() == 0)
return null;
else
return new MultiRule(rules.toArray(new ISchedulingRule[rules.size()]));
}
private static IProject[] getProjects(Repository repository) {
final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
List<IProject> result = new ArrayList<IProject>();
final File parentFile = repository.getWorkTree();
for (IProject p : projects) {
IPath projectLocation = p.getLocation();
if (projectLocation == null)
continue;
if (projectLocation.toFile().getAbsolutePath()
.startsWith(parentFile.getAbsolutePath()))
result.add(p);
}
return result.toArray(new IProject[result.size()]);
}
}