mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] Merge GitBranchUiUtil to GitBranchUtil
It was always hard to distinguish the two.
This commit is contained in:
@@ -21,24 +21,37 @@ import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
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.roots.*;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.*;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
import git4idea.config.GitConfigUtil;
|
||||
import git4idea.repo.GitBranchTrackInfo;
|
||||
import git4idea.repo.GitConfig;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.ui.branch.GitBranchUiUtil;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.*;
|
||||
import git4idea.ui.branch.GitMultiRootBranchConfig;
|
||||
import git4idea.validators.GitNewBranchNameValidator;
|
||||
import org.intellij.images.editor.ImageFileEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
@@ -46,6 +59,7 @@ import java.util.HashMap;
|
||||
public class GitBranchUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GitBranchUtil.class);
|
||||
|
||||
private static final Function<GitBranch,String> BRANCH_TO_NAME = new Function<GitBranch, String>() {
|
||||
@Override
|
||||
public String apply(@Nullable GitBranch input) {
|
||||
@@ -81,7 +95,7 @@ public class GitBranchUtil {
|
||||
else {
|
||||
assert !repositories.isEmpty() : "No repositories passed to GitBranchOperationsProcessor.";
|
||||
GitRepository repository = repositories.iterator().next();
|
||||
return GitBranchUiUtil.getBranchNameOrRev(repository);
|
||||
return getBranchNameOrRev(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,4 +318,228 @@ public class GitBranchUtil {
|
||||
return branchName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current branch name (if on branch) or current revision otherwise.
|
||||
* For fresh repository returns an empty string.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getBranchNameOrRev(@NotNull GitRepository repository) {
|
||||
if (repository.isOnBranch()) {
|
||||
GitBranch currentBranch = repository.getCurrentBranch();
|
||||
assert currentBranch != null;
|
||||
return currentBranch.getName();
|
||||
} else {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
return currentRevision != null ? currentRevision.substring(0, 7) : "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a message dialog to enter the name of new branch.
|
||||
* @return name of new branch or {@code null} if user has cancelled the dialog.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getNewBranchNameFromUser(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String dialogTitle) {
|
||||
return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "",
|
||||
GitNewBranchNameValidator.newInstance(repositories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text that is displaying current branch.
|
||||
* In the simple case it is just the branch name, but in detached HEAD state it displays the hash or "rebasing master".
|
||||
*/
|
||||
public static String getDisplayableBranchText(@NotNull GitRepository repository) {
|
||||
GitRepository.State state = repository.getState();
|
||||
if (state == GitRepository.State.DETACHED) {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
assert currentRevision != null : "Current revision can't be null in DETACHED state, only on the fresh repository.";
|
||||
return currentRevision.substring(0, 7);
|
||||
}
|
||||
|
||||
String prefix = "";
|
||||
if (state == GitRepository.State.MERGING || state == GitRepository.State.REBASING) {
|
||||
prefix = state.toString() + " ";
|
||||
}
|
||||
|
||||
GitBranch branch = repository.getCurrentBranch();
|
||||
String branchName = (branch == null ? "" : branch.getName());
|
||||
return prefix + branchName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected file, based on which GitBranch components ({@link git4idea.ui.branch.GitBranchPopup}, {@link git4idea.ui.branch.GitBranchWidget})
|
||||
* will identify the current repository root.
|
||||
*/
|
||||
@Nullable
|
||||
static VirtualFile getSelectedFile(@NotNull Project project) {
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
|
||||
final FileEditor fileEditor = StatusBarUtil.getCurrentFileEditor(project, statusBar);
|
||||
VirtualFile result = null;
|
||||
if (fileEditor != null) {
|
||||
if (fileEditor instanceof TextEditor) {
|
||||
Document document = ((TextEditor)fileEditor).getEditor().getDocument();
|
||||
result = FileDocumentManager.getInstance().getFile(document);
|
||||
} else if (fileEditor instanceof ImageFileEditor) {
|
||||
result = ((ImageFileEditor)fileEditor).getImageEditor().getFile();
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
final FileEditorManager manager = FileEditorManager.getInstance(project);
|
||||
if (manager != null) {
|
||||
Editor editor = manager.getSelectedTextEditor();
|
||||
if (editor != null) {
|
||||
result = FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the Git root on which a Git action is to be invoked.
|
||||
* <ol>
|
||||
* <li>
|
||||
* Returns the root for the selected file. Selected file is determined by {@link #getSelectedFile(com.intellij.openapi.project.Project)}.
|
||||
* If selected file is unknown (for example, no file is selected in the Project View or Changes View and no file is open in the editor),
|
||||
* continues guessing. Otherwise returns the Git root for the selected file. If the file is not under a known Git root,
|
||||
* <code>null</code> will be returned - the file is definitely determined, but it is not under Git.
|
||||
* </li>
|
||||
* <li>
|
||||
* Takes all Git roots registered in the Project. If there is only one, it is returned.
|
||||
* </li>
|
||||
* <li>
|
||||
* If there are several Git roots,
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* NB: This method has to be accessed from the <b>read action</b>, because it may query
|
||||
* {@link com.intellij.openapi.fileEditor.FileEditorManager#getSelectedTextEditor()}.
|
||||
* </p>
|
||||
* @param project current project
|
||||
* @return Git root that may be considered as "current".
|
||||
* <code>null</code> is returned if a file not under Git was explicitly selected, if there are no Git roots in the project,
|
||||
* or if the current Git root couldn't be determined.
|
||||
*/
|
||||
@Nullable
|
||||
public static GitRepository getCurrentRepository(@NotNull Project project) {
|
||||
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
|
||||
VirtualFile file = getSelectedFile(project);
|
||||
VirtualFile root = getVcsRootOrGuess(project, file);
|
||||
return manager.getRepositoryForRoot(root);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile getVcsRootOrGuess(@NotNull Project project, @Nullable VirtualFile file) {
|
||||
VirtualFile root = null;
|
||||
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (file != null) {
|
||||
if (fileIndex.isInLibrarySource(file) || fileIndex.isInLibraryClasses(file)) {
|
||||
LOG.debug("File is in library sources " + file);
|
||||
root = getVcsRootForLibraryFile(project, file);
|
||||
}
|
||||
else {
|
||||
LOG.debug("File is not in library sources " + file);
|
||||
root = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(file);
|
||||
}
|
||||
}
|
||||
return root != null ? root : guessGitRoot(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile getVcsRootForLibraryFile(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
// for a file inside .jar/.zip consider the .jar/.zip file itself
|
||||
VirtualFile root = vcsManager.getVcsRootFor(VfsUtilCore.getVirtualFileForJar(file));
|
||||
if (root != null) {
|
||||
LOG.debug("Found root for zip/jar file: " + root);
|
||||
return root;
|
||||
}
|
||||
|
||||
// for other libs which don't have jars inside the project dir (such as JDK) take the owner module of the lib
|
||||
List<OrderEntry> entries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
|
||||
Set<VirtualFile> libraryRoots = new HashSet<VirtualFile>();
|
||||
for (OrderEntry entry : entries) {
|
||||
if (entry instanceof LibraryOrderEntry || entry instanceof JdkOrderEntry) {
|
||||
VirtualFile moduleRoot = vcsManager.getVcsRootFor(entry.getOwnerModule().getModuleFile());
|
||||
if (moduleRoot != null) {
|
||||
libraryRoots.add(moduleRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (libraryRoots.size() == 0) {
|
||||
LOG.debug("No library roots");
|
||||
return null;
|
||||
}
|
||||
|
||||
// if the lib is used in several modules, take the top module
|
||||
// (for modules of the same level we can't guess anything => take the first one)
|
||||
Iterator<VirtualFile> libIterator = libraryRoots.iterator();
|
||||
VirtualFile topLibraryRoot = libIterator.next();
|
||||
while (libIterator.hasNext()) {
|
||||
VirtualFile libRoot = libIterator.next();
|
||||
if (VfsUtilCore.isAncestor(libRoot, topLibraryRoot, true)) {
|
||||
topLibraryRoot = libRoot;
|
||||
}
|
||||
}
|
||||
LOG.debug("Several library roots, returning " + topLibraryRoot);
|
||||
return topLibraryRoot;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile guessGitRoot(@NotNull Project project) {
|
||||
LOG.debug("Guessing Git root...");
|
||||
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
AbstractVcs gitVcs = GitVcs.getInstance(project);
|
||||
if (gitVcs == null) {
|
||||
LOG.debug("GitVcs not found.");
|
||||
return null;
|
||||
}
|
||||
VirtualFile[] gitRoots = vcsManager.getRootsUnderVcs(gitVcs);
|
||||
if (gitRoots.length == 0) {
|
||||
LOG.debug("No Git roots in the project.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (gitRoots.length == 1) {
|
||||
VirtualFile onlyRoot = gitRoots[0];
|
||||
LOG.debug("Only one Git root in the project, returning: " + onlyRoot);
|
||||
return onlyRoot;
|
||||
}
|
||||
|
||||
// remember the last visited Git root
|
||||
GitVcsSettings settings = GitVcsSettings.getInstance(project);
|
||||
if (settings != null) {
|
||||
String recentRootPath = settings.getRecentRootPath();
|
||||
if (recentRootPath != null) {
|
||||
VirtualFile recentRoot = VcsUtil.getVirtualFile(recentRootPath);
|
||||
if (recentRoot != null) {
|
||||
LOG.debug("Returning the recent root: " + recentRoot);
|
||||
return recentRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise return the root of the project dir or the root containing the project dir, if there is such
|
||||
VirtualFile projectBaseDir = project.getBaseDir();
|
||||
if (projectBaseDir == null) {
|
||||
VirtualFile firstRoot = gitRoots[0];
|
||||
LOG.debug("Project base dir is null, returning the first root: " + firstRoot);
|
||||
return firstRoot;
|
||||
}
|
||||
VirtualFile rootCandidate = null;
|
||||
for (VirtualFile root : gitRoots) {
|
||||
if (root.equals(projectBaseDir)) {
|
||||
return root;
|
||||
}
|
||||
else if (VfsUtilCore.isAncestor(root, projectBaseDir, true)) {
|
||||
rootCandidate = root;
|
||||
}
|
||||
}
|
||||
LOG.debug("Returning the best candidate: " + rootCandidate);
|
||||
return rootCandidate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.branch.GitBrancher;
|
||||
import git4idea.changes.GitChangeUtils;
|
||||
import git4idea.history.browser.*;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.ui.branch.GitBranchUiUtil;
|
||||
import icons.Git4ideaIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -2508,7 +2508,8 @@ public class GitLogUI implements Disposable {
|
||||
if (repository == null) return;
|
||||
|
||||
String reference = commitAt.getHash().getString();
|
||||
final String name = GitBranchUiUtil.getNewBranchNameFromUser(myProject, Collections.singleton(repository), "Checkout New Branch From " + reference);
|
||||
final String name = GitBranchUtil
|
||||
.getNewBranchNameFromUser(myProject, Collections.singleton(repository), "Checkout New Branch From " + reference);
|
||||
if (name != null) {
|
||||
GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class);
|
||||
brancher.checkoutNewBranchStartingFrom(name, reference, Collections.singletonList(repository), myRefresh);
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
@@ -154,14 +155,14 @@ class GitBranchPopup {
|
||||
if (myRepositoryManager.moreThanOneRoot()) {
|
||||
if (myMultiRootBranchConfig.diverged()) {
|
||||
currentBranchText += " in " + GitUIUtil.getShortRepositoryName(myCurrentRepository) + ": " +
|
||||
GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
GitBranchUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
}
|
||||
else {
|
||||
currentBranchText += ": " + myMultiRootBranchConfig.getCurrentBranch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentBranchText += ": " + GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
currentBranchText += ": " + GitBranchUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
}
|
||||
myPopup.setAdText(currentBranchText, SwingConstants.CENTER);
|
||||
}
|
||||
@@ -277,12 +278,12 @@ class GitBranchPopup {
|
||||
@NotNull
|
||||
public String getCaption() {
|
||||
return "Current branch in " + GitUIUtil.getShortRepositoryName(myRepository) + ": " +
|
||||
GitBranchUiUtil.getDisplayableBranchText(myRepository);
|
||||
GitBranchUtil.getDisplayableBranchText(myRepository);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getBranch() {
|
||||
return GitBranchUiUtil.getBranchNameOrRev(myRepository);
|
||||
return GitBranchUtil.getBranchNameOrRev(myRepository);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.util.IconUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.branch.GitBrancher;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.validators.GitNewBranchNameValidator;
|
||||
@@ -92,7 +93,7 @@ class GitBranchPopupActions {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final String name = GitBranchUiUtil.getNewBranchNameFromUser(myProject, myRepositories, "Create New Branch");
|
||||
final String name = GitBranchUtil.getNewBranchNameFromUser(myProject, myRepositories, "Create New Branch");
|
||||
if (name != null) {
|
||||
GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class);
|
||||
brancher.checkoutNewBranch(name, myRepositories);
|
||||
|
||||
@@ -1,287 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 git4idea.ui.branch;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
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.roots.*;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import git4idea.validators.GitNewBranchNameValidator;
|
||||
import org.intellij.images.editor.ImageFileEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* UI Utilities specific for Git branch features.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranchUiUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GitBranchUiUtil.class);
|
||||
|
||||
private GitBranchUiUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current branch name (if on branch) or current revision otherwise.
|
||||
* For fresh repository returns an empty string.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getBranchNameOrRev(@NotNull GitRepository repository) {
|
||||
if (repository.isOnBranch()) {
|
||||
GitBranch currentBranch = repository.getCurrentBranch();
|
||||
assert currentBranch != null;
|
||||
return currentBranch.getName();
|
||||
} else {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
return currentRevision != null ? currentRevision.substring(0, 7) : "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a message dialog to enter the name of new branch.
|
||||
* @return name of new branch or {@code null} if user has cancelled the dialog.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getNewBranchNameFromUser(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String dialogTitle) {
|
||||
return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "",
|
||||
GitNewBranchNameValidator.newInstance(repositories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text that is displaying current branch.
|
||||
* In the simple case it is just the branch name, but in detached HEAD state it displays the hash or "rebasing master".
|
||||
*/
|
||||
static String getDisplayableBranchText(@NotNull GitRepository repository) {
|
||||
GitRepository.State state = repository.getState();
|
||||
if (state == GitRepository.State.DETACHED) {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
assert currentRevision != null : "Current revision can't be null in DETACHED state, only on the fresh repository.";
|
||||
return currentRevision.substring(0, 7);
|
||||
}
|
||||
|
||||
String prefix = "";
|
||||
if (state == GitRepository.State.MERGING || state == GitRepository.State.REBASING) {
|
||||
prefix = state.toString() + " ";
|
||||
}
|
||||
|
||||
GitBranch branch = repository.getCurrentBranch();
|
||||
String branchName = (branch == null ? "" : branch.getName());
|
||||
return prefix + branchName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected file, based on which GitBranch components ({@link GitBranchPopup}, {@link GitBranchWidget})
|
||||
* will identify the current repository root.
|
||||
*/
|
||||
@Nullable
|
||||
static VirtualFile getSelectedFile(@NotNull Project project) {
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
|
||||
final FileEditor fileEditor = StatusBarUtil.getCurrentFileEditor(project, statusBar);
|
||||
VirtualFile result = null;
|
||||
if (fileEditor != null) {
|
||||
if (fileEditor instanceof TextEditor) {
|
||||
Document document = ((TextEditor)fileEditor).getEditor().getDocument();
|
||||
result = FileDocumentManager.getInstance().getFile(document);
|
||||
} else if (fileEditor instanceof ImageFileEditor) {
|
||||
result = ((ImageFileEditor)fileEditor).getImageEditor().getFile();
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
final FileEditorManager manager = FileEditorManager.getInstance(project);
|
||||
if (manager != null) {
|
||||
Editor editor = manager.getSelectedTextEditor();
|
||||
if (editor != null) {
|
||||
result = FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the Git root on which a Git action is to be invoked.
|
||||
* <ol>
|
||||
* <li>
|
||||
* Returns the root for the selected file. Selected file is determined by {@link #getSelectedFile(com.intellij.openapi.project.Project)}.
|
||||
* If selected file is unknown (for example, no file is selected in the Project View or Changes View and no file is open in the editor),
|
||||
* continues guessing. Otherwise returns the Git root for the selected file. If the file is not under a known Git root,
|
||||
* <code>null</code> will be returned - the file is definitely determined, but it is not under Git.
|
||||
* </li>
|
||||
* <li>
|
||||
* Takes all Git roots registered in the Project. If there is only one, it is returned.
|
||||
* </li>
|
||||
* <li>
|
||||
* If there are several Git roots,
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* NB: This method has to be accessed from the <b>read action</b>, because it may query
|
||||
* {@link com.intellij.openapi.fileEditor.FileEditorManager#getSelectedTextEditor()}.
|
||||
* </p>
|
||||
* @param project current project
|
||||
* @return Git root that may be considered as "current".
|
||||
* <code>null</code> is returned if a file not under Git was explicitly selected, if there are no Git roots in the project,
|
||||
* or if the current Git root couldn't be determined.
|
||||
*/
|
||||
@Nullable
|
||||
public static GitRepository getCurrentRepository(@NotNull Project project) {
|
||||
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
|
||||
VirtualFile file = getSelectedFile(project);
|
||||
VirtualFile root = getVcsRootOrGuess(project, file);
|
||||
return manager.getRepositoryForRoot(root);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile getVcsRootOrGuess(@NotNull Project project, @Nullable VirtualFile file) {
|
||||
VirtualFile root = null;
|
||||
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (file != null) {
|
||||
if (fileIndex.isInLibrarySource(file) || fileIndex.isInLibraryClasses(file)) {
|
||||
LOG.debug("File is in library sources " + file);
|
||||
root = getVcsRootForLibraryFile(project, file);
|
||||
}
|
||||
else {
|
||||
LOG.debug("File is not in library sources " + file);
|
||||
root = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(file);
|
||||
}
|
||||
}
|
||||
return root != null ? root : guessGitRoot(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile getVcsRootForLibraryFile(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
// for a file inside .jar/.zip consider the .jar/.zip file itself
|
||||
VirtualFile root = vcsManager.getVcsRootFor(VfsUtilCore.getVirtualFileForJar(file));
|
||||
if (root != null) {
|
||||
LOG.debug("Found root for zip/jar file: " + root);
|
||||
return root;
|
||||
}
|
||||
|
||||
// for other libs which don't have jars inside the project dir (such as JDK) take the owner module of the lib
|
||||
List<OrderEntry> entries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
|
||||
Set<VirtualFile> libraryRoots = new HashSet<VirtualFile>();
|
||||
for (OrderEntry entry : entries) {
|
||||
if (entry instanceof LibraryOrderEntry || entry instanceof JdkOrderEntry) {
|
||||
VirtualFile moduleRoot = vcsManager.getVcsRootFor(entry.getOwnerModule().getModuleFile());
|
||||
if (moduleRoot != null) {
|
||||
libraryRoots.add(moduleRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (libraryRoots.size() == 0) {
|
||||
LOG.debug("No library roots");
|
||||
return null;
|
||||
}
|
||||
|
||||
// if the lib is used in several modules, take the top module
|
||||
// (for modules of the same level we can't guess anything => take the first one)
|
||||
Iterator<VirtualFile> libIterator = libraryRoots.iterator();
|
||||
VirtualFile topLibraryRoot = libIterator.next();
|
||||
while (libIterator.hasNext()) {
|
||||
VirtualFile libRoot = libIterator.next();
|
||||
if (VfsUtilCore.isAncestor(libRoot, topLibraryRoot, true)) {
|
||||
topLibraryRoot = libRoot;
|
||||
}
|
||||
}
|
||||
LOG.debug("Several library roots, returning " + topLibraryRoot);
|
||||
return topLibraryRoot;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile guessGitRoot(@NotNull Project project) {
|
||||
LOG.debug("Guessing Git root...");
|
||||
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
AbstractVcs gitVcs = GitVcs.getInstance(project);
|
||||
if (gitVcs == null) {
|
||||
LOG.debug("GitVcs not found.");
|
||||
return null;
|
||||
}
|
||||
VirtualFile[] gitRoots = vcsManager.getRootsUnderVcs(gitVcs);
|
||||
if (gitRoots.length == 0) {
|
||||
LOG.debug("No Git roots in the project.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (gitRoots.length == 1) {
|
||||
VirtualFile onlyRoot = gitRoots[0];
|
||||
LOG.debug("Only one Git root in the project, returning: " + onlyRoot);
|
||||
return onlyRoot;
|
||||
}
|
||||
|
||||
// remember the last visited Git root
|
||||
GitVcsSettings settings = GitVcsSettings.getInstance(project);
|
||||
if (settings != null) {
|
||||
String recentRootPath = settings.getRecentRootPath();
|
||||
if (recentRootPath != null) {
|
||||
VirtualFile recentRoot = VcsUtil.getVirtualFile(recentRootPath);
|
||||
if (recentRoot != null) {
|
||||
LOG.debug("Returning the recent root: " + recentRoot);
|
||||
return recentRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise return the root of the project dir or the root containing the project dir, if there is such
|
||||
VirtualFile projectBaseDir = project.getBaseDir();
|
||||
if (projectBaseDir == null) {
|
||||
VirtualFile firstRoot = gitRoots[0];
|
||||
LOG.debug("Project base dir is null, returning the first root: " + firstRoot);
|
||||
return firstRoot;
|
||||
}
|
||||
VirtualFile rootCandidate = null;
|
||||
for (VirtualFile root : gitRoots) {
|
||||
if (root.equals(projectBaseDir)) {
|
||||
return root;
|
||||
}
|
||||
else if (VfsUtilCore.isAncestor(root, projectBaseDir, true)) {
|
||||
rootCandidate = root;
|
||||
}
|
||||
}
|
||||
LOG.debug("Returning the best candidate: " + rootCandidate);
|
||||
return rootCandidate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
|
||||
import com.intellij.util.Consumer;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryChangeListener;
|
||||
@@ -94,7 +95,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
GitRepository repo = GitBranchUiUtil.getCurrentRepository(project);
|
||||
GitRepository repo = GitBranchUtil.getCurrentRepository(project);
|
||||
if (repo == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -138,14 +139,14 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge
|
||||
return;
|
||||
}
|
||||
|
||||
GitRepository repo = GitBranchUiUtil.getCurrentRepository(project);
|
||||
GitRepository repo = GitBranchUtil.getCurrentRepository(project);
|
||||
if (repo == null) { // the file is not under version control => display nothing
|
||||
emptyTextAndTooltip();
|
||||
return;
|
||||
}
|
||||
|
||||
int maxLength = myMaxString.length() - 1; // -1, because there are arrows indicating that it is a popup
|
||||
myText = StringUtil.shortenTextWithEllipsis(GitBranchUiUtil.getDisplayableBranchText(repo), maxLength, 5);
|
||||
myText = StringUtil.shortenTextWithEllipsis(GitBranchUtil.getDisplayableBranchText(repo), maxLength, 5);
|
||||
myTooltip = getDisplayableBranchTooltip(repo);
|
||||
myStatusBar.updateWidget(ID());
|
||||
mySettings.setRecentRoot(repo.getRoot().getPath());
|
||||
@@ -160,7 +161,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge
|
||||
|
||||
@NotNull
|
||||
private static String getDisplayableBranchTooltip(GitRepository repo) {
|
||||
String text = GitBranchUiUtil.getDisplayableBranchText(repo);
|
||||
String text = GitBranchUtil.getDisplayableBranchText(repo);
|
||||
if (!GitUtil.justOneGitRepository(repo.getProject())) {
|
||||
return text + "\n" + "Root: " + repo.getRoot().getName();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
|
||||
@@ -40,8 +41,8 @@ public class GitBranchesAction extends DumbAwareAction {
|
||||
GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);
|
||||
VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE);
|
||||
GitRepository repository = (file == null ?
|
||||
GitBranchUiUtil.getCurrentRepository(project):
|
||||
repositoryManager.getRepositoryForRoot(GitBranchUiUtil.getVcsRootOrGuess(project, file)));
|
||||
GitBranchUtil.getCurrentRepository(project):
|
||||
repositoryManager.getRepositoryForRoot(GitBranchUtil.getVcsRootOrGuess(project, file)));
|
||||
if (repository == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user