/******************************************************************************* * Copyright (C) 2017 Obeo 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 *******************************************************************************/ package org.eclipse.egit.core.synchronize; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.internal.CoreText; import org.eclipse.egit.core.internal.util.ProjectUtil; import org.eclipse.egit.core.internal.util.ResourceUtil; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.lib.Repository; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.variants.IResourceVariant; /** * Extension of {@link GitResourceVariantTreeSubscriber} that is able to lazily * load data from resources that were out of the initial scope defined by the * provided {@link GitSynchronizeDataSet}. This is supposed to be used by * logical model aware {@link RemoteResourceMappingContext}s to allow loading * the variants of resources included in logical models. */ public class GitLazyResourceVariantTreeSubscriber extends GitResourceVariantTreeSubscriber { private boolean isLoaded; private boolean isValid; /** * @param gsds */ public GitLazyResourceVariantTreeSubscriber(GitSynchronizeDataSet gsds) { super(gsds); } @Override public boolean isSupervised(IResource res) throws TeamException { return true; } @Override protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { if (getDataSet().shouldBeIncluded(local)) { return super.getSyncInfo(local, base, remote); } // Otherwise, the given resource was not in the original scope this // subscriber was built. However, we want to access it anyway. IProject project = local.getProject(); Repository repo = ResourceUtil.getRepository(local); if (repo == null) { return null; } GitSynchronizeData data = getDataSet().getData(project); if (data == null) { for (GitSynchronizeData sd : getDataSet()) { if (repo.equals(sd.getRepository())) { data = sd; break; } } } if (data == null) { return null; } return getSyncInfo(local, base, remote, data); } /** * Provide a {@link SyncInfo} for the given resource that is not part of the * resources with which the given {@link GitSynchronizeData} was created * (which implies that the synchronization data for this resource is not yet * cached). * * @param local * @param base * @param remote * @param gsd * Data that describe the synchronization to perform * @return a new and initialized instance of {@link GitSyncInfo} for the * given resource that was not part of the resources to synchronize. * Returns <code>null</code> if anything goes wrong (corrupted repo, * IO problem, ...) */ private SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote, @NonNull GitSynchronizeData gsd) { GitSyncObjectCache repoCache = getCache().get(gsd.getRepository()); if (repoCache == null) { return null; } if (!isLoaded) { isLoaded = true; isValid = GitSyncCache.loadDataFromGit(gsd, null, repoCache); } if (isValid) { try { return getSyncInfo(local, base, remote, gsd.getRepository()); } catch (TeamException e) { Activator.logError(e.getMessage(), e); } } return null; } @Override public String getName() { return CoreText.GitLazyResourceVariantTreeSubscriber_name; } @Override public IResource[] roots() { List<IResource> projects = new ArrayList<>(); try { for (GitSynchronizeData data : getDataSet()) { projects.addAll(Arrays.asList(ProjectUtil .getValidOpenProjects(data.getRepository()))); } } catch (CoreException e) { Activator.logError(e.getMessage(), e); } return projects.toArray(new IResource[projects.size()]); } }