Package com.urswolfer.intellij.plugin.gerrit.ui

Source Code of com.urswolfer.intellij.plugin.gerrit.ui.RepositoryChangesBrowserProvider

/*
* Copyright 2013-2014 Urs Wolfer
*
* 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 com.urswolfer.intellij.plugin.gerrit.ui;

import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.inject.Inject;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.committed.RepositoryChangesBrowser;
import com.intellij.openapi.vcs.changes.ui.ChangeNodeDecorator;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNodeRenderer;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.table.TableView;
import com.intellij.util.Consumer;
import com.urswolfer.intellij.plugin.gerrit.SelectedRevisions;
import com.urswolfer.intellij.plugin.gerrit.git.GerritGitUtil;
import com.urswolfer.intellij.plugin.gerrit.git.RevisionFetcher;
import com.urswolfer.intellij.plugin.gerrit.rest.GerritUtil;
import com.urswolfer.intellij.plugin.gerrit.ui.changesbrowser.ChangesWithCommitMessageProvider;
import com.urswolfer.intellij.plugin.gerrit.ui.changesbrowser.CommitDiffBuilder;
import com.urswolfer.intellij.plugin.gerrit.ui.changesbrowser.SelectBaseRevisionAction;
import com.urswolfer.intellij.plugin.gerrit.util.GerritDataKeys;
import com.urswolfer.intellij.plugin.gerrit.util.NotificationBuilder;
import com.urswolfer.intellij.plugin.gerrit.util.NotificationService;
import git4idea.history.GitHistoryUtils;
import git4idea.history.browser.GitCommit;
import git4idea.history.browser.SymbolicRefs;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.concurrent.Callable;

/**
* @author Thomas Forrer
*/
public class RepositoryChangesBrowserProvider {
    @Inject
    private GerritGitUtil gerritGitUtil;
    @Inject
    private GerritUtil gerritUtil;
    @Inject
    private NotificationService notificationService;
    @Inject
    private Logger log;
    @Inject
    private Set<GerritChangeNodeDecorator> changeNodeDecorators;
    @Inject
    private SelectedRevisions selectedRevisions;

    private SelectBaseRevisionAction selectBaseRevisionAction;

    public RepositoryChangesBrowser get(Project project, GerritChangeListPanel changeListPanel) {
        selectBaseRevisionAction = new SelectBaseRevisionAction(project, selectedRevisions);

        TableView<ChangeInfo> table = changeListPanel.getTable();

        final GerritRepositoryChangesBrowser changesBrowser = new GerritRepositoryChangesBrowser(project);
        changesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), table);
        changesBrowser.getViewer().setScrollPaneBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.TOP));
        changesBrowser.getViewer().setChangeDecorator(changesBrowser.getChangeNodeDecorator());

        changeListPanel.addListSelectionListener(new Consumer<ChangeInfo>() {
            @Override
            public void consume(ChangeInfo changeInfo) {
                changesBrowser.setSelectedChange(changeInfo);
            }
        });
        return changesBrowser;
    }

    private final class GerritRepositoryChangesBrowser extends RepositoryChangesBrowser {
        private ChangeInfo selectedChange;
        private Optional<Pair<String, RevisionInfo>> baseRevision = Optional.absent();
        private Project project;

        public GerritRepositoryChangesBrowser(Project project) {
            super(project, Collections.<CommittedChangeList>emptyList(), Collections.<Change>emptyList(), null);
            this.project = project;
            selectBaseRevisionAction.addRevisionSelectedListener(new SelectBaseRevisionAction.Listener() {
                @Override
                public void revisionSelected(Optional<Pair<String, RevisionInfo>> revisionInfo) {
                    baseRevision = revisionInfo;
                    updateChangesBrowser();
                }
            });
            selectedRevisions.addObserver(new Observer() {
                @Override
                public void update(Observable o, Object arg) {
                    if (arg != null && arg instanceof String && selectedChange != null) {
                        if (selectedChange.changeId.equals(arg)) {
                            updateChangesBrowser();
                        }
                    }
                }
            });
        }

        @Override
        public void calcData(DataKey key, DataSink sink) {
            super.calcData(key, sink);
            sink.put(GerritDataKeys.CHANGE, selectedChange);
            sink.put(GerritDataKeys.BASE_REVISION, baseRevision);
        }

        @Override
        protected void buildToolBar(DefaultActionGroup toolBarGroup) {
            toolBarGroup.add(selectBaseRevisionAction);
            toolBarGroup.add(new Separator());
            super.buildToolBar(toolBarGroup);
        }

        protected void setSelectedChange(ChangeInfo changeInfo) {
            selectedChange = changeInfo;
            gerritUtil.getChangeDetails(changeInfo._number, project, new Consumer<ChangeInfo>() {
                @Override
                public void consume(ChangeInfo changeDetails) {
                    if (selectedChange.changeId.equals(changeDetails.changeId)) {
                        selectedChange = changeDetails;
                        baseRevision = Optional.absent();
                        selectBaseRevisionAction.setSelectedChange(selectedChange);
                        for (GerritChangeNodeDecorator decorator : changeNodeDecorators) {
                            decorator.onChangeSelected(project, selectedChange);
                        }
                        updateChangesBrowser();
                    }
                }
            });
        }

        protected void updateChangesBrowser() {
            getViewer().setEmptyText("Loading...");
            setChangesToDisplay(Collections.<Change>emptyList());
            Optional<GitRepository> gitRepositoryOptional = gerritGitUtil.getRepositoryForGerritProject(project, selectedChange.project);
            if (!gitRepositoryOptional.isPresent()) return;
            final GitRepository gitRepository = gitRepositoryOptional.get();
            final VirtualFile virtualFile = gitRepository.getGitDir();
            final FilePathImpl filePath = new FilePathImpl(virtualFile);

            Map<String, RevisionInfo> revisions = selectedChange.revisions;
            final String revisionId = selectedRevisions.get(selectedChange);
            RevisionInfo currentRevision = revisions.get(revisionId);
            RevisionFetcher revisionFetcher = new RevisionFetcher(gerritUtil, gerritGitUtil, notificationService, project, gitRepository)
                    .addRevision(currentRevision);
            if (baseRevision.isPresent()) {
                revisionFetcher.addRevision(baseRevision.get().getSecond());
            }
            revisionFetcher.fetch(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    final List<GitCommit> gitCommits;
                    try {
                        List<String> hashes = Lists.newArrayList();
                        if (baseRevision.isPresent()) {
                            hashes.add(baseRevision.get().first);
                        }
                        hashes.add(revisionId);

                        gitCommits = GitHistoryUtils.commitsDetails(project, filePath, new SymbolicRefs(), hashes);
                    } catch (VcsException e) {
                        log.warn("Error getting Git commit details.", e);
                        NotificationBuilder notification = new NotificationBuilder(
                                project, "Cannot show change",
                                "Git error occurred while getting commit. Please check if Gerrit is configured as remote " +
                                        "for the currently used Git repository."
                        );
                        notificationService.notifyError(notification);
                        return null;
                    }
                    final List<Change> totalDiff;
                    CommitDiffBuilder.ChangesProvider changesProvider = new ChangesWithCommitMessageProvider(
                            gerritGitUtil, project, selectedChange);
                    if (gitCommits.size() == 1) {
                        final GitCommit gitCommit = Iterables.getLast(gitCommits);
                        totalDiff = changesProvider.provide(gitCommit);
                    } else {
                        GitCommit base = gitCommits.get(0);
                        GitCommit current = gitCommits.get(1);
                        totalDiff = new CommitDiffBuilder(base, current)
                                .withChangesProvider(changesProvider).getDiff();
                    }

                    ApplicationManager.getApplication().invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            getViewer().setEmptyText("No changes");
                            setChangesToDisplay(totalDiff);
                        }
                    });
                    return null;
                }
            });
        }

        private ChangeNodeDecorator getChangeNodeDecorator() {
            return new ChangeNodeDecorator() {
                @Override
                public void decorate(Change change, SimpleColoredComponent component, boolean isShowFlatten) {
                    for (GerritChangeNodeDecorator decorator : changeNodeDecorators) {
                        decorator.decorate(project, change, component, selectedChange);
                    }
                }

                @Nullable
                @Override
                public List<Pair<String, Stress>> stressPartsOfFileName(Change change, String parentPath) {
                    return null;
                }

                @Override
                public void preDecorate(Change change, ChangesBrowserNodeRenderer renderer, boolean showFlatten) {
                }
            };
        }
    }
}
TOP

Related Classes of com.urswolfer.intellij.plugin.gerrit.ui.RepositoryChangesBrowserProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.