diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml index 663d1ef..40ebb51 100644 --- a/META-INF/plugin.xml +++ b/META-INF/plugin.xml @@ -1,8 +1,8 @@ ru.trylogic.idea.gitlab.integration GitLab integration - 1.0 - Sergei Egorov + 1.0.1 + Sergei BSiDeUp Egorov GitLab integration plugin. @@ -10,11 +10,11 @@ ]]> - + com.intellij.modules.vcs com.intellij.modules.lang diff --git a/src/ru/trylogic/idea/gitlab/integration/actions/AbstractGitLabShowCommitInBrowserAction.java b/src/ru/trylogic/idea/gitlab/integration/actions/AbstractGitLabShowCommitInBrowserAction.java deleted file mode 100644 index 5d26c22..0000000 --- a/src/ru/trylogic/idea/gitlab/integration/actions/AbstractGitLabShowCommitInBrowserAction.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.trylogic.idea.gitlab.integration.actions; - -import com.intellij.ide.BrowserUtil; -import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.project.Project; -import git4idea.repo.GitRepository; -import icons.GitlabIcons; -import ru.trylogic.idea.gitlab.integration.utils.GitlabUrlUtil; - -abstract class AbstractGitLabShowCommitInBrowserAction extends DumbAwareAction { - - public AbstractGitLabShowCommitInBrowserAction() { - super("Open on GitLab", "Open the selected commit in browser", GitlabIcons.Gitlab_icon); - } - - protected static void openInBrowser(GitRepository repository, String revisionHash) { - - String remote = GitlabUrlUtil.findRemoteUrl(repository); - final String repoUrl = GitlabUrlUtil.makeRepoUrlFromRemoteUrl(remote); - - String url = repoUrl + "/commit/" + revisionHash; - BrowserUtil.launchBrowser(url); - } - -} \ No newline at end of file diff --git a/src/ru/trylogic/idea/gitlab/integration/actions/GitLabOpenInBrowserAction.java b/src/ru/trylogic/idea/gitlab/integration/actions/GitLabOpenInBrowserAction.java index d377d5a..9b7d7cb 100644 --- a/src/ru/trylogic/idea/gitlab/integration/actions/GitLabOpenInBrowserAction.java +++ b/src/ru/trylogic/idea/gitlab/integration/actions/GitLabOpenInBrowserAction.java @@ -1,36 +1,96 @@ package ru.trylogic.idea.gitlab.integration.actions; import com.intellij.ide.BrowserUtil; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import git4idea.GitLocalBranch; import git4idea.GitRemoteBranch; import git4idea.GitUtil; +import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; -import ru.trylogic.idea.gitlab.integration.utils.GitlabUrlUtil; import icons.GitlabIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import ru.trylogic.idea.gitlab.integration.utils.GitlabUrlUtil; public class GitLabOpenInBrowserAction extends DumbAwareAction { public static final String CANNOT_OPEN_IN_BROWSER = "Cannot open in browser"; + protected GitLabOpenInBrowserAction() { + super("Open on GitLab", "Open corresponding link in browser", GitlabIcons.Gitlab_icon); + } + static void setVisibleEnabled(AnActionEvent e, boolean visible, boolean enabled) { e.getPresentation().setVisible(visible); e.getPresentation().setEnabled(enabled); } - protected GitLabOpenInBrowserAction() { - super("Open on GitLab", "Open corresponding link in browser", GitlabIcons.Gitlab_icon); + static void showError(Project project, String cannotOpenInBrowser) { + showError(project, cannotOpenInBrowser, null); + } + + static void showError(Project project, String cannotOpenInBrowser, String s) { + showError(project, cannotOpenInBrowser, s, null); + } + + static void showError(Project project, String cannotOpenInBrowser, String s, String s1) { + System.out.println(cannotOpenInBrowser + ";" + s + ";" + s1); + } + + @Nullable + static String makeUrlToOpen(@Nullable Editor editor, + @NotNull String relativePath, + @NotNull String branch, + @NotNull String remoteUrl) { + final StringBuilder builder = new StringBuilder(); + final String repoUrl = GitlabUrlUtil.makeRepoUrlFromRemoteUrl(remoteUrl); + if (repoUrl == null) { + return null; + } + builder.append(repoUrl).append("/blob/").append(branch).append(relativePath); + + if (editor != null && editor.getDocument().getLineCount() >= 1) { + // lines are counted internally from 0, but from 1 on gitlab + SelectionModel selectionModel = editor.getSelectionModel(); + final int begin = editor.getDocument().getLineNumber(selectionModel.getSelectionStart()) + 1; + final int selectionEnd = selectionModel.getSelectionEnd(); + int end = editor.getDocument().getLineNumber(selectionEnd) + 1; + if (editor.getDocument().getLineStartOffset(end - 1) == selectionEnd) { + end -= 1; + } + builder.append("#L").append(begin).append('-').append(end); + } + + return builder.toString(); + } + + @Nullable + public static String getBranchNameOnRemote(@NotNull Project project, @NotNull GitRepository repository) { + GitLocalBranch currentBranch = repository.getCurrentBranch(); + if (currentBranch == null) { + showError(project, CANNOT_OPEN_IN_BROWSER, + "Can't open the file on GitLab when repository is on detached HEAD. Please checkout a branch."); + return null; + } + + GitRemoteBranch tracked = currentBranch.findTrackedBranch(repository); + if (tracked == null) { + showError(project, CANNOT_OPEN_IN_BROWSER, "Can't open the file on GitLab when current branch doesn't have a tracked branch.", + "Current branch: " + currentBranch + ", tracked info: " + repository.getBranchTrackInfos()); + return null; + } + + return tracked.getNameForRemoteOperations(); } @Override @@ -41,9 +101,8 @@ public void update(final AnActionEvent e) { setVisibleEnabled(e, false, false); return; } - GitRepositoryManager manager = GitUtil.getRepositoryManager(project); - final GitRepository gitRepository = manager.getRepositoryForFile(virtualFile); + final GitRepository gitRepository = GitUtil.getRepositoryManager(project).getRepositoryForFile(virtualFile); if (gitRepository == null) { setVisibleEnabled(e, false, false); return; @@ -73,15 +132,6 @@ public void actionPerformed(final AnActionEvent e) { return; } - String urlToOpen = getUrl(project, virtualFile, editor); - if (urlToOpen != null) { - BrowserUtil.launchBrowser(urlToOpen); - } - } - - @Nullable - public static String getUrl(@NotNull Project project, @NotNull VirtualFile virtualFile, @Nullable Editor editor) { - GitRepositoryManager manager = GitUtil.getRepositoryManager(project); final GitRepository repository = manager.getRepositoryForFile(virtualFile); if (repository == null) { @@ -90,94 +140,96 @@ public static String getUrl(@NotNull Project project, @NotNull VirtualFile virtu details.append(repo.getPresentableUrl()).append("; "); } showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find git repository", details.toString()); - return null; + return; } - final String remoteUrl = GitlabUrlUtil.findRemoteUrl(repository); - if (remoteUrl == null) { + if (repository.getRemotes().size() == 0) { showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find gitlab remote"); - return null; + return; } final String rootPath = repository.getRoot().getPath(); final String path = virtualFile.getPath(); - if (!path.startsWith(rootPath)) { - showError(project, CANNOT_OPEN_IN_BROWSER, "File is not under repository root", "Root: " + rootPath + ", file: " + path); - return null; - } + DefaultActionGroup remotesActionGroup = new DefaultActionGroup(); + remotesActionGroup.add(new RemoteSelectedAction(project, repository, editor, repository.getRemotes().iterator().next(), rootPath, path)); - String branch = getBranchNameOnRemote(project, repository); - if (branch == null) { - return null; - } - String relativePath = path.substring(rootPath.length()); - String urlToOpen = makeUrlToOpen(editor, relativePath, branch, remoteUrl); - if (urlToOpen == null) { - showError(project, CANNOT_OPEN_IN_BROWSER, "Can't create properly url", remoteUrl); - return null; - } + DataContext dataContext = e.getDataContext(); + final ListPopup popup = + JBPopupFactory.getInstance().createActionGroupPopup( + "Select remote", + remotesActionGroup, + dataContext, + JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, + true); - return urlToOpen; + popup.showInBestPositionFor(dataContext); } - private static void showError(Project project, String cannotOpenInBrowser) { - showError(project, cannotOpenInBrowser, null); - } - private static void showError(Project project, String cannotOpenInBrowser, String s) { - showError(project, cannotOpenInBrowser, s, null); +} + +class RemoteSelectedAction extends AnAction { + + private final Editor editor; + + private final GitRemote remote; + + private final String rootPath; + + private final String path; + + private final Project project; + + private final GitRepository repository; + + public RemoteSelectedAction(@NotNull Project project, @NotNull GitRepository repository, @Nullable Editor editor, + @NotNull GitRemote remote, @NotNull String rootPath, @NotNull String path) { + super(remote.getName()); + this.project = project; + this.repository = repository; + this.editor = editor; + this.remote = remote; + this.rootPath = rootPath; + this.path = path; } - private static void showError(Project project, String cannotOpenInBrowser, String s, String s1) { - System.out.println(cannotOpenInBrowser + ";" + s + ";" + s1); + @Override + public void update(AnActionEvent e) { + super.update(e); + setEnabledInModalContext(true); + e.getPresentation().setEnabled(true); } - @Nullable - private static String makeUrlToOpen(@Nullable Editor editor, - @NotNull String relativePath, - @NotNull String branch, - @NotNull String remoteUrl) { - final StringBuilder builder = new StringBuilder(); - final String repoUrl = GitlabUrlUtil.makeRepoUrlFromRemoteUrl(remoteUrl); - if (repoUrl == null) { - return null; + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + if (!path.startsWith(rootPath)) { + GitLabOpenInBrowserAction.showError(project, GitLabOpenInBrowserAction.CANNOT_OPEN_IN_BROWSER, + "File is not under repository root", "Root: " + rootPath + ", file: " + path); + return; } - builder.append(repoUrl).append("/blob/").append(branch).append(relativePath); - if (editor != null && editor.getDocument().getLineCount() >= 1) { - // lines are counted internally from 0, but from 1 on gitlab - SelectionModel selectionModel = editor.getSelectionModel(); - final int begin = editor.getDocument().getLineNumber(selectionModel.getSelectionStart()) + 1; - final int selectionEnd = selectionModel.getSelectionEnd(); - int end = editor.getDocument().getLineNumber(selectionEnd) + 1; - if (editor.getDocument().getLineStartOffset(end - 1) == selectionEnd) { - end -= 1; - } - builder.append("#L").append(begin).append('-').append(end); + String branch = GitLabOpenInBrowserAction.getBranchNameOnRemote(project, repository); + if (branch == null) { + return; } + + String remoteUrl = remote.getFirstUrl(); - return builder.toString(); - } - - @Nullable - public static String getBranchNameOnRemote(@NotNull Project project, @NotNull GitRepository repository) { - GitLocalBranch currentBranch = repository.getCurrentBranch(); - if (currentBranch == null) { - showError(project, CANNOT_OPEN_IN_BROWSER, - "Can't open the file on GitLab when repository is on detached HEAD. Please checkout a branch."); - return null; + if (remoteUrl == null) { + GitLabOpenInBrowserAction.showError(project, GitLabOpenInBrowserAction.CANNOT_OPEN_IN_BROWSER, + "Can't obtain url for remote", remote.getName()); + return; } - GitRemoteBranch tracked = currentBranch.findTrackedBranch(repository); - if (tracked == null) { - showError(project, CANNOT_OPEN_IN_BROWSER, "Can't open the file on GitLab when current branch doesn't have a tracked branch.", - "Current branch: " + currentBranch + ", tracked info: " + repository.getBranchTrackInfos()); - return null; + String relativePath = path.substring(rootPath.length()); + String urlToOpen = GitLabOpenInBrowserAction.makeUrlToOpen(editor, relativePath, branch, remoteUrl); + if (urlToOpen == null) { + GitLabOpenInBrowserAction.showError(project, GitLabOpenInBrowserAction.CANNOT_OPEN_IN_BROWSER, + "Can't create properly url", remote.getFirstUrl()); + return; } - return tracked.getNameForRemoteOperations(); + BrowserUtil.launchBrowser(urlToOpen); } - - -} +} \ No newline at end of file diff --git a/src/ru/trylogic/idea/gitlab/integration/actions/GitLabShowCommitInBrowserFromLogAction.java b/src/ru/trylogic/idea/gitlab/integration/actions/GitLabShowCommitInBrowserFromLogAction.java deleted file mode 100644 index c9bc817..0000000 --- a/src/ru/trylogic/idea/gitlab/integration/actions/GitLabShowCommitInBrowserFromLogAction.java +++ /dev/null @@ -1,75 +0,0 @@ -package ru.trylogic.idea.gitlab.integration.actions; - - -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import git4idea.GitUtil; -import git4idea.GitVcs; -import git4idea.history.browser.GitCommit; -import git4idea.repo.GitRepository; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class GitLabShowCommitInBrowserFromLogAction extends AbstractGitLabShowCommitInBrowserAction { - - @Nullable - private static EventData collectData(AnActionEvent e) { - Project project = e.getData(PlatformDataKeys.PROJECT); - if (project == null || project.isDefault()) { - return null; - } - - GitCommit commit = e.getData(GitVcs.GIT_COMMIT); - if (commit == null) { - return null; - } - - VirtualFile root = commit.getRoot(); - GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(root); - if (repository == null) { - return null; - } - - return new EventData(repository, commit); - } - - @Override - public void update(AnActionEvent e) { - EventData eventData = collectData(e); - e.getPresentation().setVisible(eventData != null); - e.getPresentation().setEnabled(eventData != null); - } - - @Override - public void actionPerformed(AnActionEvent e) { - EventData eventData = collectData(e); - if (eventData != null) { - openInBrowser(eventData.getRepository(), eventData.getCommit().getHash().getValue()); - } - } - - private static class EventData { - @NotNull - private final GitRepository myRepository; - @NotNull - private final GitCommit myCommit; - - private EventData(@NotNull GitRepository repository, @NotNull GitCommit commit) { - myRepository = repository; - myCommit = commit; - } - - @NotNull - public GitRepository getRepository() { - return myRepository; - } - - @NotNull - public GitCommit getCommit() { - return myCommit; - } - } - -} \ No newline at end of file diff --git a/src/ru/trylogic/idea/gitlab/integration/utils/GitlabUrlUtil.java b/src/ru/trylogic/idea/gitlab/integration/utils/GitlabUrlUtil.java index 4fb9639..ee41cdc 100644 --- a/src/ru/trylogic/idea/gitlab/integration/utils/GitlabUrlUtil.java +++ b/src/ru/trylogic/idea/gitlab/integration/utils/GitlabUrlUtil.java @@ -1,15 +1,20 @@ package ru.trylogic.idea.gitlab.integration.utils; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + public class GitlabUrlUtil { @Nullable public static String findRemoteUrl(@NotNull GitRepository repository) { + List remotes = new ArrayList(); for (GitRemote remote : repository.getRemotes()) { if (remote.getName().equals("origin")) { return remote.getFirstUrl(); @@ -20,6 +25,8 @@ public static String findRemoteUrl(@NotNull GitRepository repository) { public static String makeRepoUrlFromRemoteUrl(@NotNull String remoteUrl) { String cleanedFromDotGit = StringUtil.trimEnd(remoteUrl, ".git"); + + System.out.println(cleanedFromDotGit); if (remoteUrl.startsWith("http://")) { return cleanedFromDotGit;