Java tutorial
// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See License.txt in the project root. package com.microsoft.alm.plugin.idea.tfvc.ui.checkout; import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.CheckoutProvider; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vfs.VirtualFile; import com.microsoft.alm.helpers.Path; import com.microsoft.alm.plugin.context.RepositoryContext; import com.microsoft.alm.plugin.context.ServerContext; import com.microsoft.alm.plugin.external.commands.CreateWorkspaceCommand; import com.microsoft.alm.plugin.external.commands.UpdateWorkspaceMappingCommand; import com.microsoft.alm.plugin.external.exceptions.WorkspaceAlreadyExistsException; import com.microsoft.alm.plugin.external.models.Workspace; import com.microsoft.alm.plugin.external.utils.CommandUtils; import com.microsoft.alm.plugin.idea.common.resources.TfPluginBundle; import com.microsoft.alm.plugin.idea.common.services.LocalizationServiceImpl; import com.microsoft.alm.plugin.idea.common.ui.checkout.VcsSpecificCheckoutModel; import com.microsoft.alm.plugin.idea.common.utils.IdeaHelper; import com.microsoft.alm.plugin.idea.common.utils.VcsHelper; import com.microsoft.alm.plugin.idea.tfvc.core.TFSVcs; import com.microsoft.alm.plugin.idea.tfvc.ui.workspace.WorkspaceController; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; public class TfvcCheckoutModel implements VcsSpecificCheckoutModel { private static final Logger logger = LoggerFactory.getLogger(TfvcCheckoutModel.class); @Override public void doCheckout(final Project project, final CheckoutProvider.Listener listener, final ServerContext context, final VirtualFile destinationParent, final String directoryName, final String parentDirectory, final boolean isAdvancedChecked) { final String workspaceName = directoryName; final String teamProjectName = getRepositoryName(context); final String localPath = Path.combine(parentDirectory, directoryName); final AtomicBoolean checkoutResult = new AtomicBoolean(); (new Task.Backgroundable(project, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_CREATING_WORKSPACE), true, PerformInBackgroundOption.DEAF) { public void run(@NotNull final ProgressIndicator indicator) { IdeaHelper.setProgress(indicator, 0.10, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_PROGRESS_CREATING)); try { // Create the workspace with default values final CreateWorkspaceCommand command = new CreateWorkspaceCommand(context, workspaceName, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_WORKSPACE_COMMENT), null, null); command.runSynchronously(); } catch (final WorkspaceAlreadyExistsException e) { logger.warn("Error creating workspace: " + LocalizationServiceImpl.getInstance().getExceptionMessage(e)); // TODO: allow user to change name in the flow instead of starting over IdeaHelper.runOnUIThread(new Runnable() { @Override public void run() { Messages.showErrorDialog(project, LocalizationServiceImpl.getInstance().getExceptionMessage(e), TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_FAILED_TITLE)); } }); // returning since the workspace failed to create so we can't proceed with the next steps return; } IdeaHelper.setProgress(indicator, 0.20, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_PROGRESS_ADD_ROOT)); // Map the project root to the local folder final String serverPath = VcsHelper.TFVC_ROOT + teamProjectName; final UpdateWorkspaceMappingCommand mappingCommand = new UpdateWorkspaceMappingCommand(context, workspaceName, new Workspace.Mapping(serverPath, localPath, false), false); mappingCommand.runSynchronously(); IdeaHelper.setProgress(indicator, 0.30, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_PROGRESS_CREATE_FOLDER)); // Ensure that the local folder exists final File file = new File(localPath); if (!file.mkdirs()) { //TODO should we throw here? } // if advanced is set, then sync just some of the files (those that we need for IntelliJ) // Otherwise, sync all the files for the team project if (!isAdvancedChecked) { IdeaHelper.setProgress(indicator, 0.50, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_TFVC_PROGRESS_SYNC)); // Sync all files recursively CommandUtils.syncWorkspace(context, localPath); } IdeaHelper.setProgress(indicator, 1.00, "", true); // No exception means that it was successful checkoutResult.set(true); } public void onSuccess() { if (checkoutResult.get()) { // Check the isAdvanced flag if (isAdvancedChecked) { // The user wants to edit the workspace before syncing... final RepositoryContext repositoryContext = RepositoryContext.createTfvcContext(localPath, workspaceName, teamProjectName, context.getServerUri().toString()); final WorkspaceController controller = new WorkspaceController(project, repositoryContext, workspaceName); if (controller.showModalDialog(false)) { // Save and Sync the workspace (this will be backgrounded) controller.saveWorkspace(localPath, true, new Runnable() { @Override public void run() { // Files are all synchronized, so trigger the VCS update UpdateVersionControlSystem(project, parentDirectory, directoryName, destinationParent, listener); } }); } } else { // We don't have to wait for the workspace to be updated, so just trigger the VCS update UpdateVersionControlSystem(project, parentDirectory, directoryName, destinationParent, listener); } } } }).queue(); } private void UpdateVersionControlSystem(final Project project, String parentDirectory, String directoryName, final VirtualFile destinationParent, CheckoutProvider.Listener listener) { // Add our new directory to IntelliJ's project DvcsUtil.addMappingIfSubRoot(project, FileUtil.join(new String[] { parentDirectory, directoryName }), TFSVcs.TFVC_NAME); // Check the folder for any dirty files destinationParent.refresh(true, true, new Runnable() { public void run() { if (project.isOpen() && !project.isDisposed() && !project.isDefault()) { VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project); mgr.fileDirty(destinationParent); } } }); // Trigger our listener events listener.directoryCheckedOut(new File(parentDirectory, directoryName), TFSVcs.getKey()); listener.checkoutCompleted(); } @Override public String getTelemetryAction() { return "create_workspace"; } @Override public String getButtonText() { return TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_DIALOG_CREATE_WORKSPACE_BUTTON); } @Override public String getRepositoryName(final ServerContext context) { return (context != null && context.getTeamProjectReference() != null) ? context.getTeamProjectReference().getName() : StringUtils.EMPTY; } @Override public RepositoryContext.Type getRepositoryType() { return RepositoryContext.Type.TFVC; } }