liveplugin.toolwindow.addplugin.git.GitCloneDialog.java Source code

Java tutorial

Introduction

Here is the source code for liveplugin.toolwindow.addplugin.git.GitCloneDialog.java

Source

/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package liveplugin.toolwindow.addplugin.git;

import com.intellij.dvcs.DvcsRememberedInputs;
import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;
import git4idea.GitUtil;
import git4idea.commands.GitCommand;
import git4idea.commands.GitLineHandler;
import git4idea.commands.GitTask;
import git4idea.commands.GitTaskResult;
import git4idea.remote.GitRememberedInputs;
import liveplugin.LivePluginAppComponent;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Pattern;

/**
 * This is a fork of {@link git4idea.checkout.GitCloneDialog}.
 * The reason for fork is to disable "parent directory" and "directory name" text fields.
 *
 *
 * A dialog for the git clone options
 *
 * @author Constantine.Plotnikov
 */
@SuppressWarnings("UnresolvedPropertyKey")
public class GitCloneDialog extends DialogWrapper {
    /**
     * The pattern for SSH URL-s in form [user@]host:path
     */
    private static final Pattern SSH_URL_PATTERN;

    static {
        // TODO make real URL pattern
        @NonNls
        final String ch = "[\\p{ASCII}&&[\\p{Graph}]&&[^@:/]]";
        @NonNls
        final String host = ch + "+(?:\\." + ch + "+)*";
        @NonNls
        final String path = "/?" + ch + "+(?:/" + ch + "+)*/?";
        @NonNls
        final String all = "(?:" + ch + "+@)?" + host + ":" + path;
        SSH_URL_PATTERN = Pattern.compile(all);
    }

    private JPanel myRootPanel;
    private EditorComboBox myRepositoryURL;
    private TextFieldWithBrowseButton myParentDirectory;
    private JButton myTestButton; // test repository
    private JTextField myDirectoryName;

    private String myTestURL; // the repository URL at the time of the last test
    private Boolean myTestResult; // the test result of the last test or null if not tested
    private String myDefaultDirectoryName = "";
    private final Project myProject;

    public GitCloneDialog(Project project) {
        super(project, true);
        myProject = project;
        init();
        initListeners();
        setTitle(DvcsBundle.getString("clone.title"));
        setOKButtonText(DvcsBundle.getString("clone.button"));
    }

    public String getSourceRepositoryURL() {
        return getCurrentUrlText();
    }

    public String getParentDirectory() {
        return myParentDirectory.getText();
    }

    public String getDirectoryName() {
        return myDirectoryName.getText();
    }

    /**
     * Init components
     */
    private void initListeners() {
        FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor();
        fcd.setShowFileSystemRoots(true);
        fcd.setTitle(DvcsBundle.getString("clone.destination.directory.title"));
        fcd.setDescription(DvcsBundle.getString("clone.destination.directory.description"));
        fcd.setHideIgnored(false);
        myParentDirectory.addActionListener(new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(
                fcd.getTitle(), fcd.getDescription(), myParentDirectory, myProject, fcd,
                TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
            @Override
            protected VirtualFile getInitialFile() {
                // suggest project base directory only if nothing is typed in the component.
                String text = getComponentText();
                if (text.length() == 0) {
                    VirtualFile file = myProject.getBaseDir();
                    if (file != null) {
                        return file;
                    }
                }
                return super.getInitialFile();
            }
        });

        final DocumentListener updateOkButtonListener = new DocumentAdapter() {
            @Override
            protected void textChanged(DocumentEvent e) {
                updateButtons();
            }
        };
        myParentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
        String parentDir = GitRememberedInputs.getInstance().getCloneParentDir();
        //    if (StringUtil.isEmptyOrSpaces(parentDir)) {
        //      parentDir = ProjectUtil.getBaseDir();
        //    }

        //noinspection ConstantIfStatement
        myParentDirectory.setText(LivePluginAppComponent.pluginsRootPath()); // FORK DIFF

        myDirectoryName.getDocument().addDocumentListener(updateOkButtonListener);

        myTestButton.addActionListener(new ActionListener() {
            public void actionPerformed(@NotNull final ActionEvent e) {
                test();
            }
        });

        setOKActionEnabled(false);
        myTestButton.setEnabled(false);
    }

    private void test() {
        myTestURL = getCurrentUrlText();
        boolean testResult = test(myTestURL);

        if (testResult) {
            Messages.showInfoMessage(myTestButton, DvcsBundle.message("clone.test.success.message", myTestURL),
                    DvcsBundle.getString("clone.test.connection.title"));
            myTestResult = Boolean.TRUE;
        } else {
            myTestResult = Boolean.FALSE;
        }
        updateButtons();
    }

    /*
     * JGit doesn't have ls-remote command independent from repository yet.
     * That way, we have a hack here: if http response asked for a password, then the url is at least valid and existant, and we consider
     * that the test passed.
     */
    private boolean test(String url) {
        final GitLineHandler handler = new GitLineHandler(myProject, new File("."), GitCommand.LS_REMOTE);
        handler.setUrl(url);
        handler.addParameters(url, "master");
        GitTask task = new GitTask(myProject, handler, DvcsBundle.message("clone.testing", url));
        GitTaskResult result = task.executeModal();
        return result.isOK();
    }

    /**
     * Check fields and display error in the wrapper if there is a problem
     */
    private void updateButtons() {
        if (!checkRepositoryURL()) {
            return;
        }
        if (!checkDestination()) {
            return;
        }
        setErrorText(null);
        setOKActionEnabled(true);
    }

    /**
     * Check destination directory and set appropriate error text if there are problems
     *
     * @return true if destination components are OK.
     */
    private boolean checkDestination() {
        if (myParentDirectory.getText().length() == 0 || myDirectoryName.getText().length() == 0) {
            setErrorText(null);
            setOKActionEnabled(false);
            return false;
        }
        File file = new File(myParentDirectory.getText(), myDirectoryName.getText());
        if (file.exists()) {
            setErrorText(DvcsBundle.message("clone.destination.exists.error", file));
            setOKActionEnabled(false);
            return false;
        } else if (!file.getParentFile().exists()) {
            setErrorText(DvcsBundle.message("clone.parent.missing.error", file.getParent()));
            setOKActionEnabled(false);
            return false;
        }
        return true;
    }

    /**
     * Check repository URL and set appropriate error text if there are problems
     *
     * @return true if repository URL is OK.
     */
    private boolean checkRepositoryURL() {
        String repository = getCurrentUrlText();
        if (repository.length() == 0) {
            setErrorText(null);
            setOKActionEnabled(false);
            return false;
        }
        if (myTestResult != null && repository.equals(myTestURL)) {
            if (!myTestResult.booleanValue()) {
                setErrorText(DvcsBundle.getString("clone.test.failed.error"));
                setOKActionEnabled(false);
                return false;
            } else {
                return true;
            }
        }
        try {
            if (new URI(repository).isAbsolute()) {
                return true;
            }
        } catch (URISyntaxException urlExp) {
            // do nothing
        }
        // check if ssh url pattern
        if (SSH_URL_PATTERN.matcher(repository).matches()) {
            return true;
        }
        try {
            File file = new File(repository);
            if (file.exists()) {
                if (!file.isDirectory()) {
                    setErrorText(DvcsBundle.getString("clone.url.is.not.directory.error"));
                    setOKActionEnabled(false);
                }
                return true;
            }
        } catch (Exception fileExp) {
            // do nothing
        }
        setErrorText(DvcsBundle.getString("clone.invalid.url"));
        setOKActionEnabled(false);
        return false;
    }

    private String getCurrentUrlText() {
        return myRepositoryURL.getText().trim();
    }

    private void createUIComponents() {
        myRepositoryURL = new EditorComboBox("");
        final DvcsRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
        myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
        myRepositoryURL.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
            @Override
            public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
                // enable test button only if something is entered in repository URL
                final String url = getCurrentUrlText();
                myTestButton.setEnabled(url.length() != 0);
                if (myDefaultDirectoryName.equals(myDirectoryName.getText())
                        || myDirectoryName.getText().length() == 0) {
                    // modify field if it was unmodified or blank
                    myDefaultDirectoryName = defaultDirectoryName(url);
                    myDirectoryName.setText(myDefaultDirectoryName);
                }
                updateButtons();
            }
        });
    }

    public void prependToHistory(final String item) {
        myRepositoryURL.prependItem(item);
    }

    public void rememberSettings() {
        final DvcsRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
        rememberedInputs.addUrl(getSourceRepositoryURL());
        rememberedInputs.setCloneParentDir(getParentDirectory());
    }

    /**
     * Get default name for checked out directory
     *
     * @param url an URL to checkout
     * @return a default repository name
     */
    private static String defaultDirectoryName(final String url) {

        String nonSystemName;
        if (url.endsWith("/" + GitUtil.DOT_GIT) || url.endsWith(File.separator + GitUtil.DOT_GIT)) {
            nonSystemName = url.substring(0, url.length() - 5);
        } else {
            if (url.endsWith(GitUtil.DOT_GIT)) {
                nonSystemName = url.substring(0, url.length() - 4);
            } else {
                nonSystemName = url;
            }
        }
        int i = nonSystemName.lastIndexOf('/');
        if (i == -1 && File.separatorChar != '/') {
            i = nonSystemName.lastIndexOf(File.separatorChar);
        }
        return i >= 0 ? nonSystemName.substring(i + 1) : "";
    }

    protected JComponent createCenterPanel() {
        return myRootPanel;
    }

    @Override
    protected String getDimensionServiceKey() {
        return "GitCloneDialog";
    }

    @Override
    public JComponent getPreferredFocusedComponent() {
        return myRepositoryURL;
    }

    @Override
    protected String getHelpId() {
        return "reference.VersionControl.Git.CloneRepository";
    }

}