blob: b0ce6e55dc7eed459ac8132d0abc73f53772a763 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ccvs.core.resources;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
import org.eclipse.team.internal.ccvs.core.util.Util;
/**
* This class provides static methods for checking out projects from a repository
* into the local workspace and for converting IResources into CVSRespources
* and sync trees.
* Instances of this class represent a local workspace root (i.e. a project).
*/
public class CVSWorkspaceRoot {
private ICVSFolder localRoot;
public CVSWorkspaceRoot(IContainer resource){
this.localRoot = getCVSFolderFor(resource);
}
/**
* Set the sharing for a project to enable it to be used with the CVSTeamProvider.
* This method ensure that the repository in the FolderSyncInfo is known and that
* the project is mapped to a CVS repository provider. It does not modify the sync
* info associated with the project's resources in any way.
*/
public static void setSharing(IProject project, FolderSyncInfo info, IProgressMonitor monitor) throws TeamException {
// Ensure provided info matches that of the project
ICVSFolder folder = (ICVSFolder)CVSWorkspaceRoot.getCVSResourceFor(project);
FolderSyncInfo folderInfo = folder.getFolderSyncInfo();
if ( ! info.equals(folderInfo)) {
throw new CVSException(new CVSStatus(IStatus.ERROR, NLS.bind(CVSMessages.CVSProvider_infoMismatch, new String[] { project.getName() })));
}
// Ensure that the repository location format is supported
String root = info.getRoot();
// This will try to create a repository location for the root.
// If it fails, an exception is thrown.
KnownRepositories.getInstance().getRepository(root);
// Register the project with Team
RepositoryProvider.map(project, CVSProviderPlugin.getTypeId());
}
public static ICVSFolder getCVSFolderFor(IContainer resource) {
return new EclipseFolder(resource);
}
public static ICVSFile getCVSFileFor(IFile resource) {
return new EclipseFile(resource);
}
public static ICVSResource getCVSResourceFor(IResource resource) {
if (resource.getType() == IResource.FILE)
return getCVSFileFor((IFile) resource);
else
return getCVSFolderFor((IContainer) resource);
}
public static ICVSRemoteResource getRemoteResourceFor(IResource resource) throws CVSException {
ICVSResource managed = getCVSResourceFor(resource);
return getRemoteResourceFor(managed);
}
public static ICVSRemoteResource getRemoteResourceFor(ICVSResource resource) throws CVSException {
if (resource.isFolder()) {
ICVSFolder folder = (ICVSFolder)resource;
FolderSyncInfo syncInfo = folder.getFolderSyncInfo();
if (syncInfo != null) {
return new RemoteFolder(null, KnownRepositories.getInstance().getRepository(syncInfo.getRoot()), syncInfo.getRepository(), syncInfo.getTag());
}
} else {
if (resource.isManaged()) {
RemoteFolder parent = (RemoteFolder)getRemoteResourceFor(resource.getParent());
if (parent == null) {
// This could be caused by another thread changing the state in the
// instant between when we did the managed check and we obtained the
// parent handle. If this is the case, isManaged should return false
// now. If it doesn't, then we should log an error.
if (resource.isManaged()) {
CVSProviderPlugin.log(new CVSStatus(IStatus.ERROR,CVSStatus.ERROR, NLS.bind(CVSMessages.CVSWorkspaceRoot_11, new String[] { Util.getFullestPath(resource) }),resource.getIResource()));
}
} else {
return RemoteFile.getBase(parent, (ICVSFile)resource);
}
}
}
return null;
}
/*
* Helper method that uses the parent of a local resource that has no base to ensure that the resource
* wasn't added remotely by a third party
*/
private static ICVSRemoteResource getRemoteTreeFromParent(IResource resource, ICVSResource managed, CVSTag tag, IProgressMonitor progress) throws TeamException {
// If the parent isn't mapped to CVS, there's nothing we can do
ICVSFolder parent = managed.getParent();
FolderSyncInfo syncInfo = parent.getFolderSyncInfo();
if (syncInfo == null) {
// The parent is managed so just indicate that there is no remote
return null;
}
ICVSRepositoryLocation location = KnownRepositories.getInstance().getRepository(parent.getFolderSyncInfo().getRoot());
RemoteFolder remoteParent = RemoteFolderTreeBuilder.buildRemoteTree((CVSRepositoryLocation)location, parent, tag, progress);
ICVSRemoteResource remote = null;
if (remoteParent != null) {
try {
remote = (ICVSRemoteResource)remoteParent.getChild(resource.getName());
} catch (CVSException e) {
remote = null;
}
// The types need to match or we're in trouble
if (remote != null && !(remote.isContainer() == managed.isFolder()))
throw new CVSException(new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSMessages.CVSTeamProvider_typesDiffer, new String[] { resource.getFullPath().toString() }), resource));
}
return remote;
}
/**
* Return the remote tree that corresponds to the given local resource. Return
* <code>null</code> if the remote tree doesn't exist remotely or if the local
* resource is not mapped to a remote (i.e. is not managed by CVS).
*
* @param resource the local resource
* @param tag the tag to be queried remotely
* @param cacheFileContentsHint hint which indicates whether file contents will be required
* @param depth the depth
* @param progress
* @return the remote tree or <code>null</code>
* @throws TeamException
*/
public static ICVSRemoteResource getRemoteTree(IResource resource, CVSTag tag, boolean cacheFileContentsHint, int depth, IProgressMonitor progress) throws TeamException {
ICVSResource managed = CVSWorkspaceRoot.getCVSResourceFor(resource);
ICVSRemoteResource remote = CVSWorkspaceRoot.getRemoteResourceFor(resource);
if (remote == null) {
progress.beginTask(null, 100);
remote = getRemoteTreeFromParent(resource, managed, tag, Policy.subMonitorFor(progress, 50));
if (cacheFileContentsHint && remote != null && remote instanceof RemoteFile) {
RemoteFile file = (RemoteFile)remote;
// get the storage for the file to ensure that the contents are cached
file.getStorage(Policy.subMonitorFor(progress, 50));
}
progress.done();
} else if(resource.getType() == IResource.FILE) {
ICVSRepositoryLocation location = remote.getRepository();
if (cacheFileContentsHint) {
remote = UpdateContentCachingService.buildRemoteTree((CVSRepositoryLocation)location, (ICVSFile)managed, tag, progress);
} else {
remote = RemoteFolderTreeBuilder.buildRemoteTree((CVSRepositoryLocation)location, (ICVSFile)managed, tag, progress);
}
} else {
ICVSRepositoryLocation location = remote.getRepository();
if (cacheFileContentsHint) {
remote = UpdateContentCachingService.buildRemoteTree((CVSRepositoryLocation)location, (ICVSFolder)managed, tag, depth, progress);
} else {
remote = RemoteFolderTreeBuilder.buildRemoteTree((CVSRepositoryLocation)location, (ICVSFolder)managed, tag, progress);
}
}
return remote;
}
public static boolean hasRemote(IResource resource) {
try {
ICVSResource cvsResource = getCVSResourceFor(resource);
int type = resource.getType();
if(type!=IResource.FILE) {
if(type==IResource.PROJECT) {
return ((ICVSFolder)cvsResource).isCVSFolder();
} else {
return cvsResource.isManaged();
}
} else {
byte[] syncBytes = ((ICVSFile)cvsResource).getSyncBytes();
if(syncBytes!=null) {
return !ResourceSyncInfo.isAddition(syncBytes);
} else {
return false;
}
}
} catch(CVSException e) {
return false;
}
}
public ICVSRepositoryLocation getRemoteLocation() throws CVSException {
FolderSyncInfo info = localRoot.getFolderSyncInfo();
if (info == null) {
IStatus status = new CVSStatus(IStatus.ERROR,CVSStatus.RESOURCE_SYNC_INFO_ERROR,NLS.bind(CVSMessages.CVSWorkspaceRoot_notCVSFolder, new String[] { localRoot.getName() }),localRoot);
throw new CVSException(status);
}
return KnownRepositories.getInstance().getRepository(info.getRoot());
}
public ICVSFolder getLocalRoot() {
return localRoot;
}
/**
* Return true if the resource is part of a link (i.e. a linked resource or
* one of it's children.
*
* @param container
* @return boolean
*/
public static boolean isLinkedResource(IResource resource) {
return resource.isLinked(IResource.CHECK_ANCESTORS);
}
/**
* A resource is considered shared
* @param resource
* @return boolean
*/
public static boolean isSharedWithCVS(IResource resource) throws CVSException {
if (!resource.isAccessible()) return false;
if(isLinkedResource(resource)) return false;
if(RepositoryProvider.getProvider(resource.getProject(), CVSProviderPlugin.getTypeId()) == null) {
return false;
}
ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
if (cvsResource.isManaged()) return true;
if (!cvsResource.exists()) return false;
if (cvsResource.isFolder() && ((ICVSFolder) cvsResource).isCVSFolder()) return true;
if (cvsResource.isIgnored()) return false;
return cvsResource.getParent().isCVSFolder();
}
/**
* Return whether the given container is an orphaned subtree. An orphaned subtree
* is folder (i.e. non-project) that is a CVS folder but is not managed and is not
* a linked resource. To know if the resource is a descendant of an orphaned subtree,
* the client must invoked this method for each ancestor of a resource.
* @param container the container being tested
* @return whether the container is an orphaned CVS folder
* @throws CVSException
*/
public static boolean isOrphanedSubtree(IContainer container) throws CVSException {
ICVSFolder mFolder = CVSWorkspaceRoot.getCVSFolderFor(container);
return (mFolder.isCVSFolder()
&& ! mFolder.isManaged()
&& mFolder.getIResource().getType() == IResource.FOLDER
&& !isLinkedResource(container));
}
}