mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[log] Prohibit actions for external log
Check if the repository is external to the project, and don't allow such actions as Cherry-Pick, Reset, New Branch. Additionally rewrite the Cherry-Pick action update() not to consider the old log.
This commit is contained in:
@@ -39,6 +39,8 @@ public interface RepositoryManager<T extends Repository> {
|
||||
@Nullable
|
||||
T getRepositoryForRoot(@Nullable VirtualFile root);
|
||||
|
||||
boolean isExternal(@NotNull T repository);
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} which the given file belongs to, or {@code null} if the file is not under any Git or Hg repository.
|
||||
*/
|
||||
|
||||
@@ -27,12 +27,10 @@ import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
@@ -44,8 +42,6 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.vcs.log.TimedVcsCommit;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.VcsLogProvider;
|
||||
import org.intellij.images.editor.ImageFileEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -142,18 +138,6 @@ public class DvcsUtil {
|
||||
repositoryManager.getRepositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are hg roots in the VCS log.
|
||||
*/
|
||||
public static boolean logHasRootForVcs(@NotNull VcsLog log, @Nullable final VcsKey vcsKey) {
|
||||
return ContainerUtil.find(log.getLogProviders(), new Condition<VcsLogProvider>() {
|
||||
@Override
|
||||
public boolean value(VcsLogProvider logProvider) {
|
||||
return logProvider.getSupportedVcs().equals(vcsKey);
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String joinMessagesOrNull(@NotNull Collection<String> messages) {
|
||||
String joined = StringUtil.join(messages, "\n");
|
||||
|
||||
@@ -105,6 +105,17 @@ public abstract class AbstractRepositoryManager<T extends Repository> extends Ab
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExternal(@NotNull T repository) {
|
||||
try {
|
||||
REPO_LOCK.readLock().lock();
|
||||
return !myRepositories.containsValue(repository) && myExternalRepositories.containsValue(repository);
|
||||
}
|
||||
finally {
|
||||
REPO_LOCK.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T getRepositoryForFile(@NotNull VirtualFile file) {
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package com.intellij.dvcs.ui;
|
||||
|
||||
import com.intellij.dvcs.repo.AbstractRepositoryManager;
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import com.intellij.dvcs.repo.RepositoryManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
@@ -33,7 +37,7 @@ import java.util.List;
|
||||
public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getRequiredData(CommonDataKeys.PROJECT);
|
||||
VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG);
|
||||
List<VcsFullCommitDetails> details = log.getSelectedDetails();
|
||||
@@ -43,7 +47,7 @@ public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG);
|
||||
if (project == null || log == null) {
|
||||
@@ -57,7 +61,7 @@ public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAct
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
}
|
||||
else {
|
||||
e.getPresentation().setVisible(true);
|
||||
e.getPresentation().setVisible(isVisible(project, grouped));
|
||||
e.getPresentation().setEnabled(!grouped.isEmpty() && isEnabled(grouped));
|
||||
}
|
||||
}
|
||||
@@ -66,6 +70,19 @@ public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAct
|
||||
|
||||
protected abstract boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
|
||||
|
||||
protected boolean isVisible(@NotNull final Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
|
||||
return ContainerUtil.and(grouped.keySet(), new Condition<Repo>() {
|
||||
@Override
|
||||
public boolean value(Repo repo) {
|
||||
RepositoryManager<Repo> manager = getRepositoryManager(project);
|
||||
return !manager.isExternal(repo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract AbstractRepositoryManager<Repo> getRepositoryManager(@NotNull Project project);
|
||||
|
||||
@Nullable
|
||||
protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.actions;
|
||||
|
||||
import com.intellij.dvcs.repo.AbstractRepositoryManager;
|
||||
import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -26,10 +27,16 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class GitLogSingleCommitAction extends VcsLogSingleCommitAction<GitRepository> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected AbstractRepositoryManager<GitRepository> getRepositoryManager(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, GitRepositoryManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
|
||||
return ServiceManager.getService(project, GitRepositoryManager.class).getRepositoryForRoot(root);
|
||||
return getRepositoryManager(project).getRepositoryForRoot(root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package git4idea.cherrypick;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.dvcs.repo.RepositoryManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -25,9 +26,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import git4idea.GitLocalBranch;
|
||||
@@ -35,13 +34,9 @@ import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.history.browser.GitHeavyCommit;
|
||||
import git4idea.history.wholeTree.AbstractHash;
|
||||
import git4idea.history.wholeTree.GitCommitDetailsProvider;
|
||||
import git4idea.repo.GitRepository;
|
||||
import icons.Git4ideaIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -66,12 +61,9 @@ public class GitCherryPickAction extends DumbAwareAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getProject();
|
||||
final List<? extends VcsFullCommitDetails> commits = getSelectedCommits(e);
|
||||
if (project == null || commits == null || commits.isEmpty()) {
|
||||
LOG.info(String.format("Cherry-pick action should be disabled. Project: %s, commits: %s", project, commits));
|
||||
return;
|
||||
}
|
||||
final Project project = e.getRequiredData(CommonDataKeys.PROJECT);
|
||||
VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG);
|
||||
final List<? extends VcsFullCommitDetails> commits = log.getSelectedDetails();
|
||||
|
||||
for (VcsFullCommitDetails commit : commits) {
|
||||
myIdsInProgress.add(commit.getId());
|
||||
@@ -136,24 +128,47 @@ public class GitCherryPickAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
super.update(e);
|
||||
VcsLog log = getVcsLog(e);
|
||||
VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG);
|
||||
Project project = getEventProject(e);
|
||||
if (project == null || log == null || !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
|
||||
if (project == null || log == null || !logHasGitRoots(log)) {
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
e.getPresentation().setEnabled(enabled(e));
|
||||
e.getPresentation().setText(isAutoCommit(project) ? NAME : NAME + "...");
|
||||
|
||||
List<VcsFullCommitDetails> details = log.getSelectedDetails();
|
||||
if (notFromGitAndProject(project, details)) {
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
e.getPresentation().setEnabled(enabled(project, log, details));
|
||||
e.getPresentation().setText(isAutoCommit(project) ? NAME : NAME + "...");
|
||||
}
|
||||
|
||||
private boolean enabled(AnActionEvent e) {
|
||||
final List<? extends VcsFullCommitDetails> commits = getSelectedCommits(e);
|
||||
final Project project = e.getProject();
|
||||
public static boolean logHasGitRoots(@NotNull VcsLog log) {
|
||||
return ContainerUtil.find(log.getLogProviders(), new Condition<VcsLogProvider>() {
|
||||
@Override
|
||||
public boolean value(VcsLogProvider logProvider) {
|
||||
return logProvider.getSupportedVcs().equals(GitVcs.getKey());
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
if (commits == null || commits.isEmpty() || project == null) {
|
||||
private boolean notFromGitAndProject(@NotNull Project project, @NotNull List<VcsFullCommitDetails> details) {
|
||||
final RepositoryManager<GitRepository> manager = myPlatformFacade.getRepositoryManager(project);
|
||||
return ContainerUtil.and(details, new Condition<VcsFullCommitDetails>() {
|
||||
@Override
|
||||
public boolean value(VcsFullCommitDetails commit) {
|
||||
GitRepository repository = manager.getRepositoryForRoot(commit.getRoot());
|
||||
return repository != null && manager.isExternal(repository);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean enabled(@NotNull Project project, @NotNull VcsLog log, @NotNull List<VcsFullCommitDetails> commits) {
|
||||
if (commits.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -162,11 +177,9 @@ public class GitCherryPickAction extends DumbAwareAction {
|
||||
return false;
|
||||
}
|
||||
GitRepository repository = myPlatformFacade.getRepositoryManager(project).getRepositoryForRoot(commit.getRoot());
|
||||
if (repository == null) {
|
||||
return false;
|
||||
}
|
||||
assert repository != null;
|
||||
GitLocalBranch currentBranch = repository.getCurrentBranch();
|
||||
Collection<String> containingBranches = getContainingBranches(e, commit, repository);
|
||||
Collection<String> containingBranches = log.getContainingBranches(commit.getId());
|
||||
if (currentBranch != null && containingBranches != null && containingBranches.contains(currentBranch.getName())) {
|
||||
// already is contained in the current branch
|
||||
return false;
|
||||
@@ -175,85 +188,4 @@ public class GitCherryPickAction extends DumbAwareAction {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO remove after removing the old Vcs Log implementation
|
||||
@Nullable
|
||||
private List<? extends VcsFullCommitDetails> getSelectedCommits(AnActionEvent e) {
|
||||
final Project project = e.getProject();
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
List<GitHeavyCommit> commits = e.getData(GitVcs.SELECTED_COMMITS);
|
||||
if (commits != null) {
|
||||
return convertHeavyCommitToFullDetails(commits, project);
|
||||
}
|
||||
final VcsLog log = getVcsLog(e);
|
||||
if (log == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Hash> selectedCommits = log.getSelectedCommits();
|
||||
List<VcsFullCommitDetails> selectedDetails = ContainerUtil.newArrayList();
|
||||
for (Hash commit : selectedCommits) {
|
||||
VcsFullCommitDetails details = log.getDetailsIfAvailable(commit);
|
||||
if (details == null) { // let the action be unavailable until all details are loaded
|
||||
return null;
|
||||
}
|
||||
GitRepository root = myPlatformFacade.getRepositoryManager(project).getRepositoryForRoot(details.getRoot());
|
||||
// don't allow to cherry-pick if a non-Git commit was selected
|
||||
// we could cherry-pick just Git commits filtered from the list, but it might provide confusion
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
selectedDetails.add(details);
|
||||
}
|
||||
return selectedDetails;
|
||||
}
|
||||
|
||||
private static List<? extends VcsFullCommitDetails> convertHeavyCommitToFullDetails(List<GitHeavyCommit> commits, final Project project) {
|
||||
return ContainerUtil.map(commits, new Function<GitHeavyCommit, VcsFullCommitDetails>() {
|
||||
@Override
|
||||
public VcsFullCommitDetails fun(GitHeavyCommit commit) {
|
||||
final VcsLogObjectsFactory factory = ServiceManager.getService(project, VcsLogObjectsFactory.class);
|
||||
List<Hash> parents = ContainerUtil.map(commit.getParentsHashes(), new Function<String, Hash>() {
|
||||
@Override
|
||||
public Hash fun(String hashValue) {
|
||||
return factory.createHash(hashValue);
|
||||
}
|
||||
});
|
||||
final List<Change> changes = commit.getChanges();
|
||||
return factory.createFullDetails(
|
||||
factory.createHash(commit.getHash().getValue()), parents, commit.getAuthorTime(), commit.getRoot(), commit.getSubject(),
|
||||
commit.getAuthor(), commit.getAuthorEmail(), commit.getDescription(), commit.getCommitter(), commit.getCommitterEmail(),
|
||||
commit.getDate().getTime(), new ThrowableComputable<Collection<Change>, Exception>() {
|
||||
@Override
|
||||
public Collection<Change> compute() throws Exception {
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static VcsLog getVcsLog(@NotNull AnActionEvent event) {
|
||||
return event.getData(VcsLogDataKeys.VCS_LOG);
|
||||
}
|
||||
|
||||
// TODO remove after removing the old Vcs Log implementation
|
||||
@Nullable
|
||||
private static Collection<String> getContainingBranches(AnActionEvent event, VcsFullCommitDetails commit, GitRepository repository) {
|
||||
GitCommitDetailsProvider detailsProvider = event.getData(GitVcs.COMMIT_DETAILS_PROVIDER);
|
||||
if (detailsProvider != null) {
|
||||
return detailsProvider.getContainingBranches(repository.getRoot(), AbstractHash.create(commit.getId().toShortString()));
|
||||
}
|
||||
if (event.getProject() == null) {
|
||||
return null;
|
||||
}
|
||||
VcsLog log = getVcsLog(event);
|
||||
if (log == null) {
|
||||
return null;
|
||||
}
|
||||
return log.getContainingBranches(commit.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package git4idea.reset;
|
||||
|
||||
import com.intellij.dvcs.repo.AbstractRepositoryManager;
|
||||
import com.intellij.dvcs.ui.VcsLogOneCommitPerRepoAction;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -24,15 +26,20 @@ import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static git4idea.GitUtil.getRepositoryManager;
|
||||
|
||||
public class GitResetAction extends VcsLogOneCommitPerRepoAction<GitRepository> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected AbstractRepositoryManager<GitRepository> getRepositoryManager(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, GitRepositoryManager.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.zmlx.hg4idea.action;
|
||||
|
||||
import com.intellij.dvcs.repo.AbstractRepositoryManager;
|
||||
import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -27,10 +28,16 @@ import org.zmlx.hg4idea.repo.HgRepositoryManager;
|
||||
|
||||
public abstract class HgLogSingleCommitAction extends VcsLogSingleCommitAction<HgRepository> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected AbstractRepositoryManager<HgRepository> getRepositoryManager(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, HgRepositoryManager.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected HgRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
|
||||
return ServiceManager.getService(project, HgRepositoryManager.class).getRepositoryForRoot(root);
|
||||
return getRepositoryManager(project).getRepositoryForRoot(root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user