org.community.intellij.plugins.communitycase.Vcs.java Source code

Java tutorial

Introduction

Here is the source code for org.community.intellij.plugins.communitycase.Vcs.java

Source

/*
 * Copyright 2000-2010 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 org.community.intellij.plugins.communitycase;

import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.progress.BackgroundTaskQueue;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.CommitExecutor;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EventDispatcher;
import com.intellij.util.containers.ComparatorDelegate;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.UIUtil;
import org.community.intellij.plugins.communitycase.annotate.IntellijAnnotationProvider;
import org.community.intellij.plugins.communitycase.changes.ChangeUtils;
import org.community.intellij.plugins.communitycase.changes.CommittedChangeListProvider;
import org.community.intellij.plugins.communitycase.changes.OutgoingChangesProvider;
import org.community.intellij.plugins.communitycase.checkin.CheckinEnvironment;
import org.community.intellij.plugins.communitycase.checkin.CommitAndPushExecutor;
import org.community.intellij.plugins.communitycase.checkout.branches.BranchConfigurations;
import org.community.intellij.plugins.communitycase.commands.Command;
import org.community.intellij.plugins.communitycase.commands.SimpleHandler;
import org.community.intellij.plugins.communitycase.config.*;
import org.community.intellij.plugins.communitycase.diff.TreeDiffProvider;
import org.community.intellij.plugins.communitycase.history.HistoryProvider;
import org.community.intellij.plugins.communitycase.history.NewUsersComponent;
import org.community.intellij.plugins.communitycase.history.browser.ProjectLogManager;
import org.community.intellij.plugins.communitycase.i18n.Bundle;
import org.community.intellij.plugins.communitycase.merge.MergeProvider;
import org.community.intellij.plugins.communitycase.update.UpdateEnvironment;
import org.community.intellij.plugins.communitycase.vfs.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *  VCS implementation
 */
public class Vcs extends AbstractVcs<CommittedChangeList> {
    public static final String NOTIFICATION_GROUP_ID = "ClearCase";
    public static final String NAME = "ClearCase"; // Vcs name

    //private static final Logger log = Logger.getInstance("#"+Vcs.class.getName());
    private static final VcsKey ourKey = createKey(NAME);

    private final com.intellij.openapi.vcs.changes.ChangeProvider myChangeProvider;
    private final CheckinEnvironment myCheckinEnvironment;
    private final com.intellij.openapi.vcs.rollback.RollbackEnvironment myRollbackEnvironment;
    private final UpdateEnvironment myUpdateEnvironment;
    private final IntellijAnnotationProvider myAnnotationProvider;
    private final com.intellij.openapi.vcs.diff.DiffProvider myDiffProvider;
    private final VcsHistoryProvider myHistoryProvider;
    private final com.intellij.openapi.vcs.EditFileProvider myEditFileProvider;
    private final ProjectLevelVcsManager myVcsManager;
    private final VcsSettings mySettings;
    private final Configurable myConfigurable;
    private final com.intellij.openapi.vcs.diff.RevisionSelector myRevSelector;
    private final MergeProvider myMergeProvider;
    private final MergeProvider myReverseMergeProvider;
    private final CommittedChangeListProvider myCommittedChangeListProvider;

    private VfsListener myVfsListener; // a VFS listener that tracks file addition, deletion, and renaming.
    @SuppressWarnings({ "FieldAccessedSynchronizedAndUnsynchronized" })
    private Version myVersion; // The currently detected  version or null.
    private final Object myCheckingVersion = new Object(); // Checking the version lock (used to prevent infinite recursion)
    private String myVersionCheckExcecutable = ""; // The path to executable at the time of version check

    private RootTracker myRootTracker; // The tracker that checks validity of  roots
    private final EventDispatcher<RootsListener> myRootListeners = EventDispatcher.create(RootsListener.class);
    private final EventDispatcher<ConfigListener> myConfigListeners = EventDispatcher.create(ConfigListener.class);
    private final EventDispatcher<ReferenceListener> myReferenceListeners = EventDispatcher
            .create(ReferenceListener.class);
    private IgnoreTracker myIgnoreTracker;
    private ConfigTracker myConfigTracker;
    private final BackgroundTaskQueue myTaskQueue; // The queue that is used to schedule background task from actions
    private final ReadWriteLock myCommandLock = new ReentrantReadWriteLock(true); // The command read/write lock
    private final TreeDiffProvider myTreeDiffProvider;
    private final CommitAndPushExecutor myCommitAndPushExecutor;
    private ReferenceTracker myReferenceTracker;
    private boolean isActivated; // If true, the vcs was activated
    private ExecutableValidator myExecutableValidator;

    public static Vcs getInstance(@NotNull Project project) {
        return (Vcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME);
    }

    public Vcs(@NotNull Project project,
            @NotNull final org.community.intellij.plugins.communitycase.changes.ChangeProvider changeProvider,
            @NotNull final CheckinEnvironment checkinEnvironment, @NotNull final ProjectLevelVcsManager vcsManager,
            @NotNull final IntellijAnnotationProvider annotationProvider,
            @NotNull final org.community.intellij.plugins.communitycase.diff.DiffProvider diffProvider,
            @NotNull final HistoryProvider historyProvider,
            @NotNull final org.community.intellij.plugins.communitycase.rollback.RollbackEnvironment rollbackEnvironment,
            @NotNull final org.community.intellij.plugins.communitycase.edit.EditFileProvider editFileProvider,
            @NotNull final VcsSettings settings) {
        super(project, NAME);
        myVcsManager = vcsManager;
        mySettings = settings;
        myChangeProvider = changeProvider;
        myCheckinEnvironment = checkinEnvironment;
        myAnnotationProvider = annotationProvider;
        myDiffProvider = diffProvider;
        myHistoryProvider = historyProvider;
        myRollbackEnvironment = rollbackEnvironment;
        myEditFileProvider = editFileProvider;
        myRevSelector = new RevisionSelector();
        myConfigurable = new VcsConfigurable(settings, myProject);
        myUpdateEnvironment = new org.community.intellij.plugins.communitycase.update.UpdateEnvironment(myProject,
                this, settings);
        myMergeProvider = new org.community.intellij.plugins.communitycase.merge.MergeProvider(myProject);
        myReverseMergeProvider = new org.community.intellij.plugins.communitycase.merge.MergeProvider(myProject,
                true);
        myCommittedChangeListProvider = new CommittedChangeListProvider(myProject);
        myOutgoingChangesProvider = new OutgoingChangesProvider(myProject);
        myTreeDiffProvider = new TreeDiffProvider(myProject);
        myCommitAndPushExecutor = new CommitAndPushExecutor(checkinEnvironment);
        myReferenceTracker = new ReferenceTracker(myProject, this, myReferenceListeners.getMulticaster());
        myTaskQueue = new BackgroundTaskQueue(myProject, Bundle.getString("task.queue.title"));
    }

    /**
     * @return the vfs listener instance
     */
    public VfsListener getVfsListener() {
        return myVfsListener;
    }

    /**
     * @return the command lock
     */
    public ReadWriteLock getCommandLock() {
        return myCommandLock;
    }

    /**
     * Run task in background using the common queue (per project)
     *
     * @param task the task to run
     */
    public void runInBackground(Task.Backgroundable task) {
        myTaskQueue.run(task);
    }

    /**
     * Add listener for  roots
     *
     * @param listener the listener to add
     */
    public void addConfigListener(ConfigListener listener) {
        myConfigListeners.addListener(listener);
    }

    /**
     * Remove listener for  roots
     *
     * @param listener the listener to remove
     */
    public void removeConfigListener(ConfigListener listener) {
        myConfigListeners.removeListener(listener);
    }

    /**
     * Add listener for  roots
     *
     * @param listener the listener to add
     */
    public void addReferenceListener(ReferenceListener listener) {
        myReferenceListeners.addListener(listener);
    }

    /**
     * Remove listener for  roots
     *
     * @param listener the listener to remove
     */
    public void removeReferenceListener(ReferenceListener listener) {
        myReferenceListeners.removeListener(listener);
    }

    /**
     * Add listener for  roots
     *
     * @param listener the listener to add
     */
    public void addRootsListener(RootsListener listener) {
        myRootListeners.addListener(listener);
    }

    /**
     * Remove listener for  roots
     *
     * @param listener the listener to remove
     */
    public void removeRootsListener(RootsListener listener) {
        myRootListeners.removeListener(listener);
    }

    /**
     * @return a reverse merge provider for  (with reversed meaning of "theirs" and "yours", needed for the rebase and unstash)
     */
    @NotNull
    public com.intellij.openapi.vcs.merge.MergeProvider getReverseMergeProvider() {
        return myReverseMergeProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CommittedChangesProvider getCommittedChangesProvider() {
        return myCommittedChangeListProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getRevisionPattern() {
        // return the full commit hash pattern, possibly other revision formats should be supported as well
        return "[0-9a-fA-F]{40}";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public CheckinEnvironment getCheckinEnvironment() {
        return myCheckinEnvironment;
    }

    /**
     * {@inheritDoc}
     */
    @NotNull
    @Override
    public com.intellij.openapi.vcs.merge.MergeProvider getMergeProvider() {
        return myMergeProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public com.intellij.openapi.vcs.rollback.RollbackEnvironment getRollbackEnvironment() {
        return myRollbackEnvironment;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public VcsHistoryProvider getVcsHistoryProvider() {
        return myHistoryProvider;
    }

    @Override
    public VcsHistoryProvider getVcsBlockHistoryProvider() {
        return myHistoryProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public String getDisplayName() {
        return NAME;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Nullable
    public com.intellij.openapi.vcs.update.UpdateEnvironment getUpdateEnvironment() {
        return myUpdateEnvironment;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public IntellijAnnotationProvider getAnnotationProvider() {
        return myAnnotationProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @NotNull
    public com.intellij.openapi.vcs.diff.DiffProvider getDiffProvider() {
        return myDiffProvider;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Nullable
    public com.intellij.openapi.vcs.diff.RevisionSelector getRevisionSelector() {
        return myRevSelector;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings({ "deprecation" })
    @Override
    @Nullable
    public VcsRevisionNumber parseRevisionNumber(String revision, FilePath path) {
        return parseRevisionNumber(revision);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings({ "deprecation" })
    @Override
    @Nullable
    public VcsRevisionNumber parseRevisionNumber(String revision) {
        return parseRevisionNumber(revision, null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isVersionedDirectory(VirtualFile dir) {
        return dir.isDirectory() && Util.rootOrNull(dir) != null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void start() throws VcsException {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void shutdown() throws VcsException {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void activate() {
        isActivated = true;
        myExecutableValidator = new ExecutableValidator(myProject);
        myExecutableValidator.checkExecutableAndNotifyIfNeeded();
        if (!myProject.isDefault() && myRootTracker == null) {
            myRootTracker = new RootTracker(this, myProject, myRootListeners.getMulticaster());
        }
        if (myVfsListener == null) {
            myVfsListener = new VfsListener(myProject, this);
        }
        if (myConfigTracker == null) {
            myConfigTracker = new ConfigTracker(myProject, this, myConfigListeners.getMulticaster());
        }
        if (myIgnoreTracker == null) {
            myIgnoreTracker = new IgnoreTracker(myProject, this);
        }
        myReferenceTracker.activate();
        NewUsersComponent.getInstance(myProject).activate();
        ProjectLogManager.getInstance(myProject).activate();
        //BranchConfigurations.getInstance(myProject).activate(); //TODO wc do we need this?
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void deactivate() {
        isActivated = false;
        BranchConfigurations.getInstance(myProject).deactivate();
        if (myRootTracker != null) {
            myRootTracker.dispose();
            myRootTracker = null;
        }
        if (myVfsListener != null) {
            Disposer.dispose(myVfsListener);
            myVfsListener = null;
        }
        if (myIgnoreTracker != null) {
            myIgnoreTracker.dispose();
            myIgnoreTracker = null;
        }
        if (myConfigTracker != null) {
            myConfigTracker.dispose();
            myConfigTracker = null;
        }
        myReferenceTracker.deactivate();
        NewUsersComponent.getInstance(myProject).deactivate();
        ProjectLogManager.getInstance(myProject).deactivate();
    }

    /**
     * {@inheritDoc}
     */
    @NotNull
    @Override
    public synchronized Configurable getConfigurable() {
        return myConfigurable;
    }

    /**
     * {@inheritDoc}
     */
    @Nullable
    public com.intellij.openapi.vcs.changes.ChangeProvider getChangeProvider() {
        return myChangeProvider;
    }

    /**
     * Show errors as popup and as messages in vcs view.
     *
     * @param list   a list of errors
     * @param action an action
     */
    public void showErrors(@NotNull List<VcsException> list, @NotNull String action) {
        if (list.size() > 0) {
            StringBuffer buffer = new StringBuffer();
            buffer.append("\n");
            buffer.append(Bundle.message("error.list.title", action));
            for (final VcsException exception : list) {
                buffer.append("\n");
                buffer.append(exception.getMessage());
            }
            final String msg = buffer.toString();
            UIUtil.invokeLaterIfNeeded(new Runnable() {
                @Override
                public void run() {
                    Messages.showErrorDialog(myProject, msg, Bundle.getString("error.dialog.title"));
                }
            });
        }
    }

    /**
     * Show a plain message in vcs view
     *
     * @param message a message to show
     */
    public void showMessages(@NotNull String message) {
        if (message.length() == 0)
            return;
        showMessage(message, ConsoleViewContentType.NORMAL_OUTPUT.getAttributes());
    }

    /**
     * @return vcs settings for the current project
     */
    @NotNull
    public VcsSettings getSettings() {
        return mySettings;
    }

    /**
     * Show message in the VCS view
     *
     * @param message a message to show
     * @param style   a style to use
     */
    private void showMessage(@NotNull String message, final TextAttributes style) {
        myVcsManager.addMessageToConsoleWindow(message, style);
    }

    /**
     * Check version and report problem
     */
    public void checkVersion() {
        final String executable = mySettings.getPathToExecutable();
        synchronized (myCheckingVersion) {
            if (myVersion != null && myVersionCheckExcecutable.equals(executable)) {
                return;
            }
            myVersionCheckExcecutable = executable;
            // this assignment is done to prevent recursive version check
            myVersion = Version.INVALID;
            final String version;
            try {
                version = version(myProject).trim();
            } catch (VcsException e) {
                String reason = (e.getCause() != null ? e.getCause() : e).getMessage();
                if (!myProject.isDefault()) {
                    showMessage(Bundle.message("vcs.unable.to.run", executable, reason),
                            ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
                }
                return;
            }
            myVersion = Version.parse(version);
            if (!Version.parse(version).isSupported() && !myProject.isDefault()) {
                showMessage(Bundle.message("vcs.unsupported.version", version, Version.MIN),
                        ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
            }
        }
    }

    /**
     * @return the configured version of
     */
    public Version version() {
        checkVersion();
        return myVersion;
    }

    /**
     * Get the version of configured
     *
     * @param project the project
     * @return a version of configured
     * @throws com.intellij.openapi.vcs.VcsException an error if there is a problem with running
     */
    public static String version(Project project) throws VcsException {
        final String s;
        SimpleHandler h = new SimpleHandler(project, new File("."), Command.VERSION);
        h.setRemote(true);
        h.setSilent(true);
        s = h.run();
        return s;
    }

    /**
     * Show command line
     *
     * @param cmdLine a command line text
     */
    public void showCommandLine(final String cmdLine) {
        SimpleDateFormat f = new SimpleDateFormat("HH:mm:ss.SSS");
        showMessage(f.format(new Date()) + ": " + cmdLine, ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
    }

    /**
     * The error line
     *
     * @param line a line to show
     */
    public void showErrorMessages(final String line) {
        showMessage(line, ConsoleViewContentType.ERROR_OUTPUT.getAttributes());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean allowsNestedRoots() {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <S> List<S> filterUniqueRoots(final List<S> in, final Convertor<S, VirtualFile> convertor) {
        Collections.sort(in, new ComparatorDelegate<S, VirtualFile>(convertor, FilePathComparator.getInstance()));

        for (int i = 1; i < in.size(); i++) {
            final S sChild = in.get(i);
            final VirtualFile child = convertor.convert(sChild);
            final VirtualFile childRoot = Util.rootOrNull(child);
            if (childRoot == null) {
                // non- file actually, skip it
                continue;
            }
            for (int j = i - 1; j >= 0; --j) {
                final S sParent = in.get(j);
                final VirtualFile parent = convertor.convert(sParent);
                // the method check both that parent is an ancestor of the child and that they share common  root
                if (VfsUtil.isAncestor(parent, child, false) && VfsUtil.isAncestor(childRoot, parent, false)) {
                    in.remove(i);
                    //noinspection AssignmentToForLoopParameter
                    --i;
                    break;
                }
            }
        }
        return in;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RootsConvertor getCustomConvertor() {
        return RootConverter.INSTANCE;
    }

    public static VcsKey getKey() {
        return ourKey;
    }

    @Override
    public VcsType getType() {
        return VcsType.centralized;
    }

    private final VcsOutgoingChangesProvider<CommittedChangeList> myOutgoingChangesProvider;

    @Override
    protected VcsOutgoingChangesProvider<CommittedChangeList> getOutgoingProviderImpl() {
        return myOutgoingChangesProvider;
    }

    @Override
    public RemoteDifferenceStrategy getRemoteDifferenceStrategy() {
        return RemoteDifferenceStrategy.ASK_TREE_PROVIDER;
    }

    @Override
    protected TreeDiffProvider getTreeDiffProviderImpl() {
        return myTreeDiffProvider;
    }

    @Override
    public List<CommitExecutor> getCommitExecutors() {
        return Collections.<CommitExecutor>singletonList(myCommitAndPushExecutor);
    }

    /**
     * @return true if vcs was activated
     */
    public boolean isActivated() {
        return isActivated;
    }

    public ExecutableValidator getExecutableValidator() {
        return myExecutableValidator;
    }

    /** {@inheritDoc} */
    @Override
    public com.intellij.openapi.vcs.EditFileProvider getEditFileProvider() {
        return myEditFileProvider;
    }

    public void refreshAllRoots() {
        VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
        //for(VirtualFile vf:ProjectLevelVcsManager.getInstance(myProject).getRootsUnderVcs(this))
    }
}