com.microsoft.alm.plugin.idea.ui.simplecheckout.SimpleCheckoutModel.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.alm.plugin.idea.ui.simplecheckout.SimpleCheckoutModel.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root.

package com.microsoft.alm.plugin.idea.ui.simplecheckout;

import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
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.util.io.FileUtil;
import com.intellij.openapi.vcs.CheckoutProvider;
import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.microsoft.alm.plugin.context.ServerContext;
import com.microsoft.alm.plugin.context.ServerContextManager;
import com.microsoft.alm.plugin.idea.resources.TfPluginBundle;
import com.microsoft.alm.plugin.idea.ui.common.AbstractModel;
import com.microsoft.alm.plugin.idea.ui.common.ModelValidationInfo;
import com.microsoft.alm.plugin.services.PluginServiceProvider;
import com.microsoft.alm.plugin.services.PropertyService;
import com.microsoft.alm.plugin.telemetry.TfsTelemetryHelper;
import git4idea.GitVcs;
import git4idea.commands.Git;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * The model for the SimpleCheckout dialog UI
 */
public class SimpleCheckoutModel extends AbstractModel {
    public final static String DEFAULT_SOURCE_PATH = System.getProperty("user.home");
    public final static String PROP_DIRECTORY_NAME = "directoryName";
    public final static String PROP_PARENT_DIR = "parentDirectory";
    public final static String COMMANDLINE_CLONE_ACTION = "commandline-clone";
    public final static Pattern GIT_URL_PATTERN = Pattern.compile("/_git/(.*)");

    private final Project project;
    private final CheckoutProvider.Listener listener;
    private final String gitUrl;
    private String parentDirectory;
    private String directoryName;

    protected SimpleCheckoutModel(final Project project, final CheckoutProvider.Listener listener,
            final String gitUrl) {
        super();
        this.project = project;
        this.listener = listener;
        this.gitUrl = gitUrl;

        this.parentDirectory = PluginServiceProvider.getInstance().getPropertyService()
                .getProperty(PropertyService.PROP_REPO_ROOT);
        // use default root if no repo root is found
        if (StringUtils.isEmpty(this.parentDirectory)) {
            this.parentDirectory = DEFAULT_SOURCE_PATH;
        }

        // try and parse for the repo name to use as the directory name
        final Matcher matcher = GIT_URL_PATTERN.matcher(gitUrl);
        if (matcher.find() && matcher.groupCount() == 1) {
            this.directoryName = matcher.group(1);
        } else {
            this.directoryName = StringUtils.EMPTY;
        }
    }

    public Project getProject() {
        return project;
    }

    public String getParentDirectory() {
        return parentDirectory;
    }

    public void setParentDirectory(final String parentDirectory) {
        if (!StringUtils.equals(this.parentDirectory, parentDirectory)) {
            this.parentDirectory = parentDirectory;
            setChangedAndNotify(PROP_PARENT_DIR);
        }
    }

    public String getDirectoryName() {
        return directoryName;
    }

    public void setDirectoryName(final String directoryName) {
        if (!StringUtils.equals(this.directoryName, directoryName)) {
            this.directoryName = directoryName;
            setChangedAndNotify(PROP_DIRECTORY_NAME);
        }
    }

    public String getRepoUrl() {
        return gitUrl;
    }

    public ModelValidationInfo validate() {
        final String parentDirectory = getParentDirectory();
        if (parentDirectory == null || parentDirectory.isEmpty()) {
            return ModelValidationInfo.createWithResource(PROP_PARENT_DIR,
                    TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_PARENT_DIR_EMPTY);
        }

        final File parentDirectoryOnDisk = new File(parentDirectory);
        if (!parentDirectoryOnDisk.exists()) {
            return ModelValidationInfo.createWithResource(PROP_PARENT_DIR,
                    TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_PARENT_DIR_NOT_FOUND);
        }

        // We test this method and so we need to check to see if we are in IntelliJ before using VirtualFileManager
        // ApplicationManager is null if we are not in IntelliJ
        if (ApplicationManager.getApplication() != null) {
            final VirtualFile destinationParent = LocalFileSystem.getInstance().findFileByPath(parentDirectory);
            if (destinationParent == null) {
                return ModelValidationInfo.createWithResource(PROP_PARENT_DIR,
                        TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_PARENT_DIR_NOT_FOUND);
            }
        }

        final String directoryName = getDirectoryName();
        if (directoryName == null || directoryName.isEmpty()) {
            return ModelValidationInfo.createWithResource(PROP_DIRECTORY_NAME,
                    TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_DIR_NAME_EMPTY);
        }

        final File destDirectoryOnDisk = new File(parentDirectory, directoryName);
        //verify the destination directory does not exist
        if (destDirectoryOnDisk.exists() && destDirectoryOnDisk.isDirectory()) {
            return ModelValidationInfo.createWithResource(PROP_DIRECTORY_NAME,
                    TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_DESTINATION_EXISTS, directoryName);
        }
        //verify destination directory parent exists, we can reach this condition if user specifies a path for directory name
        if (destDirectoryOnDisk.getParentFile() == null || !destDirectoryOnDisk.getParentFile().exists()) {
            return ModelValidationInfo.createWithResource(PROP_DIRECTORY_NAME,
                    TfPluginBundle.KEY_CHECKOUT_DIALOG_ERRORS_DIR_NAME_INVALID, directoryName,
                    destDirectoryOnDisk.getParent());
        }

        return ModelValidationInfo.NO_ERRORS;
    }

    public void cloneRepo() {
        final ModelValidationInfo validationInfo = validate();
        if (validationInfo == null) {
            final Task.Backgroundable createCloneTask = new Task.Backgroundable(project,
                    TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_DIALOG_TITLE), true,
                    PerformInBackgroundOption.DEAF) {
                final AtomicBoolean cloneResult = new AtomicBoolean();

                @Override
                public void run(@NotNull final ProgressIndicator progressIndicator) {
                    progressIndicator.setText(TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_DIALOG_TITLE));
                    // get context from manager, and store in active context
                    final ServerContext context = ServerContextManager.getInstance().getAuthenticatedContext(gitUrl,
                            true);

                    if (context == null) {
                        VcsNotifier.getInstance(project).notifyError(
                                TfPluginBundle
                                        .message(TfPluginBundle.KEY_CHECKOUT_ERRORS_AUTHENTICATION_FAILED_TITLE),
                                TfPluginBundle.message(TfPluginBundle.KEY_ERRORS_AUTH_NOT_SUCCESSFUL, gitUrl));
                        return;
                    }

                    final String gitRepositoryStr = context.getUsableGitUrl();
                    final Git git = ServiceManager.getService(Git.class);
                    cloneResult.set(git4idea.checkout.GitCheckoutProvider.doClone(project, git, getDirectoryName(),
                            getParentDirectory(), gitRepositoryStr));

                    // Add Telemetry for the clone call along with it's success/failure
                    TfsTelemetryHelper.getInstance().sendEvent(COMMANDLINE_CLONE_ACTION,
                            new TfsTelemetryHelper.PropertyMapBuilder().currentOrActiveContext(context)
                                    .actionName(COMMANDLINE_CLONE_ACTION).success(cloneResult.get()).build());
                }

                @Override
                public void onSuccess() {
                    // if clone was successful then complete the checkout process which gives the option to open the project
                    if (cloneResult.get()) {
                        DvcsUtil.addMappingIfSubRoot(project,
                                FileUtil.join(new String[] { parentDirectory, directoryName }), "Git");
                        listener.directoryCheckedOut(new File(parentDirectory, directoryName), GitVcs.getKey());
                        listener.checkoutCompleted();
                    }
                }
            };
            createCloneTask.queue();
        }
    }
}