in source/com.microsoft.tfs.core/src/com/microsoft/tfs/core/clients/versioncontrol/VersionControlClient.java [1540:1871]
private void setWorkspaceLocation(final Workspace workspace, final WorkspaceLocation newLocation)
throws CoreCancelException {
Check.notNull(workspace, "workspace"); //$NON-NLS-1$
Check.notNull(newLocation, "newLocation"); //$NON-NLS-1$
if (newLocation == workspace.getLocation()) {
// No work to do.
return;
}
// Using UpdateWorkspace to set the location of a workspace was not
// supported prior to revision Tfs2012_2.
if (getWebServiceLayer().getServiceLevel().getValue() < WebServiceLevel.TFS_2012_2.getValue()) {
throw new FeatureNotSupportedException(Messages.getString("Workspace.LocalWorkspacesNotSupported")); //$NON-NLS-1$
}
final TaskMonitor taskMonitor = TaskMonitorService.getTaskMonitor();
try {
// 100 total work units, make sure they all add up below
taskMonitor.begin(Messages.getString("VersionControlClient.ChangingWorkspaceLocation"), 100); //$NON-NLS-1$
if (WorkspaceLocation.SERVER == newLocation) {
// Local -> server
final WorkspaceLock wLock = workspace.lock();
try {
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 1. Reconcile
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.ReconcilingLocalWorkspaceToServer")); //$NON-NLS-1$
final AtomicBoolean pendingChangesUpdatedByServer = new AtomicBoolean();
workspace.reconcile(false, pendingChangesUpdatedByServer);
taskMonitor.worked(20);
// Last cancellation point
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 2. Mark all items without a pending edit as read-only on
// disk, since
// this is now a server workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.MarkingUneditedReadOnly")); //$NON-NLS-1$
LocalDataAccessLayer.markReadOnlyBit(workspace, true, taskMonitor.newSubTaskMonitor(30));
// 3. Ask the server to make this a server workspace. Before
// we do,
// grab a couple of pieces of information we won't be able
// to get afterward.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.ChangingWorkspaceLocationOnServer")); //$NON-NLS-1$
final String localMetadataDirectory = workspace.getLocalMetadataDirectory();
final String[] baselineFolders = LocalDataAccessLayer.getBaselineFolders(workspace);
getWebServiceLayer().updateWorkspace(
workspace.getName(),
workspace.getOwnerName(),
new Workspace(
this,
workspace.getName(),
workspace.getOwnerName(),
workspace.getOwnerDisplayName(),
workspace.getOwnerAliases(),
workspace.getComment(),
workspace.getSecurityToken(),
workspace.getFolders(),
workspace.getComputer(),
WorkspaceLocation.SERVER,
workspace.getPermissions(),
null,
workspace.getOptions()),
SupportedFeatures.ALL);
taskMonitor.worked(10);
// 4. Refresh the Workspace object in this instance of the
// client object model.
// This has the additional effect of updating the local
// workspace cache (VersionControl.config).
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.RefreshingWorkspace")); //$NON-NLS-1$
workspace.refresh();
taskMonitor.worked(10);
// 5. Get rid of the baseline folders and local metadata
// directory for this workspace.
// (Past the point of cancellation)
taskMonitor.setCurrentWorkDescription(
MessageFormat.format(
Messages.getString("VersionControlClient.DeletingUnusedBaselineFormat"), //$NON-NLS-1$
localMetadataDirectory));
FileHelpers.deleteDirectory(localMetadataDirectory);
taskMonitor.worked(10);
final TaskMonitor deleteBaselineMonitor = taskMonitor.newSubTaskMonitor(20);
deleteBaselineMonitor.begin("", baselineFolders.length); //$NON-NLS-1$
for (final String baselineFolder : baselineFolders) {
taskMonitor.setCurrentWorkDescription(
MessageFormat.format(
Messages.getString("VersionControlClient.DeletingUnusedBaselineFormat"), //$NON-NLS-1$
baselineFolder));
FileHelpers.deleteDirectory(baselineFolder);
deleteBaselineMonitor.worked(1);
}
deleteBaselineMonitor.done();
} finally {
if (wLock != null) {
wLock.close();
}
}
// 6. Fire a cross-process notification indicating that the
// workspace object changed.
Workstation.getCurrent(getConnection().getPersistenceStoreProvider()).notifyForWorkspace(
workspace,
Notification.VERSION_CONTROL_WORKSPACE_CHANGED);
} else if (WorkspaceLocation.LOCAL == newLocation) {
// Server -> local
/*
* Create a clone of the workspace object which is marked as a
* local workspace. We'll use this object for local work before
* we convert the workspace on the server. This Workspace object
* must not escape this method.
*/
final Workspace localWorkspace = new Workspace(
this,
workspace.getName(),
workspace.getOwnerName(),
workspace.getOwnerDisplayName(),
workspace.getOwnerAliases(),
workspace.getComment(),
workspace.getSecurityToken(),
workspace.getFolders(),
workspace.getComputer(),
WorkspaceLocation.LOCAL,
workspace.getPermissions(),
null,
workspace.getOptions());
final WorkspaceLock wLock = workspace.lock();
try {
boolean workspacePropertiesCreated = false;
try {
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// Delete any existing local metadata for this
// workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.RemovingMetadataForLocalWorkspace")); //$NON-NLS-1$
FileHelpers.deleteDirectory(localWorkspace.getLocalMetadataDirectory());
taskMonitor.worked(10);
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 1. Set up the workspace properties table for this
// workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.CreatingPropertiesTable")); //$NON-NLS-1$
final LocalWorkspaceTransaction propsTransaction =
new LocalWorkspaceTransaction(localWorkspace);
// We're explicitly creating a new workspace properties
// table here. We don't
// want autorecovery to ever run in this scenario.
propsTransaction.setAutoRecover(false);
try {
propsTransaction.execute(new WorkspacePropertiesTransaction() {
@Override
public void invoke(final LocalWorkspaceProperties wp) {
// Set the working folders for the workspace
// (initial population).
wp.setWorkingFolders(workspace.getFolders());
wp.doBaselineFolderMaintenance();
}
});
} finally {
try {
propsTransaction.close();
} catch (final IOException e) {
throw new VersionControlException(e);
}
}
workspacePropertiesCreated = true;
taskMonitor.worked(10);
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 2. Set the pending changes for the local workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.CreatingPendingChangesTable")); //$NON-NLS-1$
final LocalWorkspaceTransaction pcTransaction = new LocalWorkspaceTransaction(localWorkspace);
try {
pcTransaction.execute(new LocalVersionPendingChangesTransaction() {
@Override
public void invoke(final WorkspaceVersionTable lv, final LocalPendingChangesTable pc) {
final PendingSet set = workspace.getPendingChanges();
if (set != null && set.getPendingChanges() != null) {
pc.replacePendingChanges(set.getPendingChanges());
}
}
});
} finally {
try {
pcTransaction.close();
} catch (final IOException e) {
throw new VersionControlException(e);
}
}
taskMonitor.worked(10);
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 3. Get the data we need to populate the local version
// table for the workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.CreatingLocalVersionTable")); //$NON-NLS-1$
final WorkspaceItemSet[] workspaceItemSets = workspace.getItems(new ItemSpec[] {
new ItemSpec(ServerPath.ROOT, RecursionType.FULL)
}, DeletedState.ANY, ItemType.ANY, true, GetItemsOptions.INCLUDE_RECURSIVE_DELETES);
if (null != workspaceItemSets && 1 == workspaceItemSets.length) {
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 4. Populate the local version table for the
// workspace.
final BaselineRequest[] baselineRequests = LocalDataAccessLayer.populateLocalVersionTable(
localWorkspace,
workspaceItemSets[0].getItems(),
taskMonitor.newSubTaskMonitor(10));
if (null != baselineRequests) {
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
// 5. Put the baselines in place (either by
// gzip+hash of existing local content,
// or by downloading content from the server).
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.CompressingAndDownloadingBaselines")); //$NON-NLS-1$
LocalDataAccessLayer.processConversionBaselineRequests(
localWorkspace,
Arrays.asList(baselineRequests));
}
taskMonitor.worked(20);
} else {
taskMonitor.worked(30);
}
// Last cancellation point
if (taskMonitor.isCanceled()) {
throw new CoreCancelException();
}
} catch (final CoreCancelException e) {
// If we were canceled and we have a workspace
// properties table in place, go ahead and take the time
// to clean up the $tf folders we created.
if (workspacePropertiesCreated) {
final String[] baselineFolders = LocalDataAccessLayer.getBaselineFolders(localWorkspace);
for (final String baselineFolder : baselineFolders) {
FileHelpers.deleteDirectory(baselineFolder);
}
}
throw e;
}
// 5. Mark all items in the workspace as writable.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.RemovingReadOnlyFromUneditedItems")); //$NON-NLS-1$
LocalDataAccessLayer.markReadOnlyBit(localWorkspace, false, taskMonitor.newSubTaskMonitor(20));
// 6. Mark this workspace as a local workspace.
taskMonitor.setCurrentWorkDescription(
Messages.getString("VersionControlClient.ChangingWorkspaceLocationOnServer")); //$NON-NLS-1$
getWebServiceLayer().updateWorkspace(
workspace.getName(),
workspace.getOwnerName(),
localWorkspace,
SupportedFeatures.ALL);
taskMonitor.worked(10);
} finally {
if (wLock != null) {
wLock.close();
}
}
// 7. Refresh this Workspace instance in the client object
// model. This has the additional effect of updating the local
// workspace cache (VersionControl.config).
taskMonitor.setCurrentWorkDescription(Messages.getString("VersionControlClient.RefreshingWorkspace")); //$NON-NLS-1$
workspace.refresh();
workspace.getWorkspaceWatcher().workingFoldersChanged(workspace.getFolders());
taskMonitor.worked(10);
// 8. Fire a cross-process notification indicating that the
// workspace object changed.
Workstation.getCurrent(getConnection().getPersistenceStoreProvider()).notifyForWorkspace(
workspace,
Notification.VERSION_CONTROL_WORKSPACE_CHANGED);
}
} finally {
taskMonitor.done();
}
}