blob: 2a8eac0bba6ae9b51b34a6dee7838add588bcdfc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.operations;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.SyncInfoFilter.ContentComparisonSyncInfoFilter;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.MutableResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
/**
* Reconcile an existing unshared local project with an existing remote folder.
*/
public class ReconcileProjectOperation extends ShareProjectOperation {
private ICVSRemoteFolder folder;
private ContentComparisonSyncInfoFilter contentCompare = new ContentComparisonSyncInfoFilter(false);
public ReconcileProjectOperation(Shell shell, IProject project, ICVSRemoteFolder folder) {
super(shell, folder.getRepository(), project, folder.getRepositoryRelativePath());
this.folder = folder;
}
/* (non-Javadoc)
* @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#getTaskName()
*/
protected String getTaskName() {
return NLS.bind(CVSUIMessages.ReconcileProjectOperation_0, new String[] { getProject().getName(), folder.getRepositoryRelativePath() });
}
/* (non-Javadoc)
* @see org.eclipse.team.internal.ccvs.ui.operations.ShareProjectOperation#createRemoteFolder(org.eclipse.core.runtime.IProgressMonitor)
*/
protected ICVSRemoteFolder createRemoteFolder(IProgressMonitor monitor) throws CVSException {
// The folder already exists so just return the handle
return folder;
}
/* (non-Javadoc)
* @see org.eclipse.team.internal.ccvs.ui.operations.ShareProjectOperation#mapProjectToRemoteFolder(org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder, org.eclipse.core.runtime.IProgressMonitor)
*/
protected void mapProjectToRemoteFolder(ICVSRemoteFolder remote, IProgressMonitor monitor) throws TeamException {
// Map the project
monitor.beginTask(null, 100);
super.mapProjectToRemoteFolder(remote, Policy.subMonitorFor(monitor, 10));
// Reconcile the sync info
reconcileSyncInfo(Policy.subMonitorFor(monitor, 90));
monitor.done();
}
/* (non-Javadoc)
* @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
*/
protected void reconcileSyncInfo(IProgressMonitor monitor) throws CVSException {
try {
monitor.beginTask(null, 100);
// Fetch the entire remote tree
ICVSRemoteFolder remote = CheckoutToRemoteFolderOperation.checkoutRemoteFolder(getPart(), folder, Policy.subMonitorFor(monitor, 80));
// Traverse the tree and populate the workspace base or remote
// with the sync info depending on file contents
populateWorkspace(remote, Policy.subMonitorFor(monitor, 20));
} catch (InvocationTargetException e) {
throw CVSException.wrapException(e);
} catch (TeamException e) {
throw CVSException.wrapException(e);
} catch (InterruptedException e) {
throw new OperationCanceledException();
} finally {
monitor.done();
}
}
private void populateWorkspace(final ICVSRemoteFolder remote, IProgressMonitor monitor) throws CVSException {
CVSWorkspaceRoot.getCVSFolderFor(getProject()).run(new ICVSRunnable() {
public void run(IProgressMonitor monitor) throws CVSException {
populateWorkspace(getProject(), remote, monitor);
}
}, monitor);
}
/* private */ void populateWorkspace(IResource resource, ICVSRemoteResource remote, IProgressMonitor monitor) throws CVSException {
try {
if (resource.getType() == IResource.FILE) {
if (remote.isContainer()) {
CVSUIPlugin.log(IStatus.ERROR, NLS.bind(CVSUIMessages.ReconcileProjectOperation_1, new String[] { resource.getFullPath().toString(), remote.getRepositoryRelativePath() }), null);
} else {
IFile file = (IFile)resource;
IResourceVariant variant = (IResourceVariant)remote;
if (file.exists()
&& variant != null
&& contentCompare.compareContents(file, variant, monitor)) {
// The contents are the same so populate the local workspace
// with the remote sync info and make the file in-sync
makeInSync(file, remote, monitor);
} else {
// Would like to put the bytes in the remote but this
// is complicated due to subscriber events.
// We'll refresh the subcriber at the end.
}
}
} else {
if (!remote.isContainer()) {
CVSUIPlugin.log(IStatus.ERROR, NLS.bind(CVSUIMessages.ReconcileProjectOperation_2, new String[] { resource.getFullPath().toString(), remote.getRepositoryRelativePath() }), null);
} else {
// Map the local folder to the remote folder.
// (Note that this will make phantoms for non-exisiting local folders)
ICVSFolder folder = (ICVSFolder)CVSWorkspaceRoot.getCVSResourceFor(resource);
folder.setFolderSyncInfo(((ICVSFolder)remote).getFolderSyncInfo());
// Traverse the children of the remote
// (The members were prefetched).
ICVSRemoteResource[] members = remote.members(monitor);
for (int i = 0; i < members.length; i++) {
ICVSRemoteResource member = members[i];
populateWorkspace(getLocalChild((IContainer)resource, member), member, monitor);
}
}
}
} catch (TeamException e) {
throw CVSException.wrapException(e);
}
}
/*
* Get the local resource handle for corresponding to the remote resource
*/
private IResource getLocalChild(IContainer parent, ICVSRemoteResource member) {
IResource resource = parent.findMember(member.getName());
if (resource == null) {
if (member.isContainer()) {
resource = parent.getFolder(new Path(null, member.getName()));
} else {
resource = parent.getFile(new Path(null, member.getName()));
}
}
return resource;
}
/*
* Make the file in-sync with its corresponding remote.
*/
private void makeInSync(IFile file, ICVSRemoteResource remote, IProgressMonitor monitor) throws CVSException {
ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file);
ResourceSyncInfo info = remote.getSyncInfo();
Date modTime = info.getTimeStamp();
if (modTime != null) {
cvsFile.setTimeStamp(modTime);
}
modTime = cvsFile.getTimeStamp();
MutableResourceSyncInfo newInfoWithTimestamp = info.cloneMutable();
newInfoWithTimestamp.setTimeStamp(modTime);
cvsFile.setSyncInfo(newInfoWithTimestamp, ICVSFile.CLEAN);
}
}