diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserActionGroup.kt b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserActionGroup.kt index b2d3cf760352..d851bbdedab8 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserActionGroup.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserActionGroup.kt @@ -71,7 +71,7 @@ open class GithubOpenInBrowserActionGroup private fun getDataFromPullRequest(project: Project, dataContext: DataContext): Pair, Data>? { val pullRequest = dataContext.getData(GithubPullRequestKeys.SELECTED_PULL_REQUEST) ?: return null val serverPath = dataContext.getData(GithubPullRequestKeys.SERVER_PATH) ?: return null - val fullPath = dataContext.getData(GithubPullRequestKeys.FULL_PATH) ?: return null + val fullPath = dataContext.getData(GithubPullRequestKeys.REPO_DETAILS)?.fullPath ?: return null val htmlUrl = pullRequest.pullRequestLinks?.htmlUrl ?: return null return setOf(GithubRepositoryPath(serverPath, fullPath)) to Data.URL(project, htmlUrl) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubViewPullRequestsAction.kt b/plugins/github/src/org/jetbrains/plugins/github/GithubViewPullRequestsAction.kt index 3fa4abe4f758..fa7254dc953a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubViewPullRequestsAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubViewPullRequestsAction.kt @@ -4,12 +4,19 @@ package org.jetbrains.plugins.github import com.intellij.icons.AllIcons import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.components.service +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.Task import com.intellij.openapi.project.Project import com.intellij.openapi.util.registry.Registry import git4idea.repo.GitRemote import git4idea.repo.GitRepository +import org.jetbrains.plugins.github.api.GithubApiRequestExecutorManager +import org.jetbrains.plugins.github.api.GithubApiRequests +import org.jetbrains.plugins.github.api.data.GithubRepoDetailed import org.jetbrains.plugins.github.authentication.accounts.GithubAccount import org.jetbrains.plugins.github.pullrequest.GithubPullRequestsToolWindowManager +import org.jetbrains.plugins.github.util.GithubNotifications +import org.jetbrains.plugins.github.util.GithubUrlUtil class GithubViewPullRequestsAction : AbstractGithubUrlGroupingAction("View Pull Requests", null, AllIcons.Vcs.Vendors.Github) { override fun isEnabledAndVisible(e: AnActionEvent): Boolean { @@ -22,6 +29,37 @@ class GithubViewPullRequestsAction : AbstractGithubUrlGroupingAction("View Pull remote: GitRemote, remoteUrl: String, account: GithubAccount) { - project.service().showPullRequestsTab(repository, remote, remoteUrl, account) + val fullPath = GithubUrlUtil.getUserAndRepositoryFromRemoteUrl(remoteUrl) + if (fullPath == null) { + GithubNotifications.showError(project, "Invalid GitHub Repository URL", "$remoteUrl is not a GitHub repository.") + return + } + + val requestExecutor = service().getExecutor(account, project) ?: return + + val toolWindowManager = project.service() + if (toolWindowManager.showPullRequestsTabIfExists(repository, remote, remoteUrl, account)) return + + object : Task.Backgroundable(project, "Loading GitHub Repository Information", true) { + lateinit var repoDetails: GithubRepoDetailed + + override fun run(indicator: ProgressIndicator) { + val details = requestExecutor.execute(indicator, GithubApiRequests.Repos.get(account.server, fullPath.user, fullPath.repository)) + ?: throw IllegalArgumentException( + "Repository $fullPath does not exist at ${account.server} or you don't have access.") + + repoDetails = details + indicator.checkCanceled() + } + + override fun onSuccess() { + toolWindowManager.createPullRequestsTab(requestExecutor, repository, remote, remoteUrl, repoDetails, account) + toolWindowManager.showPullRequestsTabIfExists(repository, remote, remoteUrl, account) + } + + override fun onThrowable(error: Throwable) { + GithubNotifications.showError(project, "Failed To Load Repository Information", error) + } + }.queue() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsComponentFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsComponentFactory.kt index b2aee1d6fe58..ef781c524542 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsComponentFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsComponentFactory.kt @@ -13,8 +13,8 @@ import com.intellij.ui.components.panels.Wrapper import git4idea.commands.Git import git4idea.repo.GitRemote import git4idea.repo.GitRepository -import org.jetbrains.plugins.github.api.GithubApiRequestExecutorManager -import org.jetbrains.plugins.github.api.GithubFullPath +import org.jetbrains.plugins.github.api.GithubApiRequestExecutor +import org.jetbrains.plugins.github.api.data.GithubRepoDetailed import org.jetbrains.plugins.github.authentication.accounts.GithubAccount import org.jetbrains.plugins.github.pullrequest.action.GithubPullRequestKeys import org.jetbrains.plugins.github.pullrequest.avatars.CachingGithubAvatarIconsProvider @@ -24,13 +24,11 @@ import org.jetbrains.plugins.github.pullrequest.data.GithubPullRequestsLoader import org.jetbrains.plugins.github.pullrequest.ui.* import org.jetbrains.plugins.github.util.CachingGithubUserAvatarLoader import org.jetbrains.plugins.github.util.GithubImageResizer -import org.jetbrains.plugins.github.util.GithubUrlUtil import javax.swing.JComponent class GithubPullRequestsComponentFactory(private val project: Project, private val progressManager: ProgressManager, - private val requestExecutorManager: GithubApiRequestExecutorManager, private val git: Git, private val uiSettings: GithubPullRequestsUISettings, private val avatarLoader: CachingGithubUserAvatarLoader, @@ -38,12 +36,13 @@ class GithubPullRequestsComponentFactory(private val project: Project, private val actionManager: ActionManager, private val autoPopupController: AutoPopupController) { - fun createComponent(repository: GitRepository, remote: GitRemote, remoteUrl: String, account: GithubAccount): JComponent? { + fun createComponent(requestExecutor: GithubApiRequestExecutor, + repository: GitRepository, remote: GitRemote, + repoDetails: GithubRepoDetailed, + account: GithubAccount): JComponent? { - val requestExecutor = requestExecutorManager.getExecutor(account, project) ?: return null - val repoPath = GithubUrlUtil.getUserAndRepositoryFromRemoteUrl(remoteUrl)!! val listLoader = GithubPullRequestsLoader(progressManager, requestExecutor, - account.server, repoPath) + account.server, repoDetails.fullPath) val selectionModel = GithubPullRequestsListSelectionModel() val list = GithubPullRequestsListComponent(project, actionManager, autoPopupController, selectionModel, listLoader, @@ -64,8 +63,8 @@ class GithubPullRequestsComponentFactory(private val project: Project, // disposed by content manager when tab is closed val wrapper = WrappingComponent(splitter, - repository, remote, repoPath, account, - list, selectionModel, dataLoader) + repository, remote, repoDetails, account, + list,selectionModel, dataLoader) Disposer.register(wrapper, Disposable { Disposer.dispose(list) Disposer.dispose(preview) @@ -81,7 +80,7 @@ class GithubPullRequestsComponentFactory(private val project: Project, private class WrappingComponent(wrapped: JComponent, private val repository: GitRepository, private val remote: GitRemote, - private val repoPath: GithubFullPath, + private val repoDetails: GithubRepoDetailed, private val account: GithubAccount, private val list: GithubPullRequestsListComponent, private val selectionModel: GithubPullRequestsListSelectionModel, @@ -95,7 +94,7 @@ class GithubPullRequestsComponentFactory(private val project: Project, return when { GithubPullRequestKeys.REPOSITORY.`is`(dataId) -> repository GithubPullRequestKeys.REMOTE.`is`(dataId) -> remote - GithubPullRequestKeys.FULL_PATH.`is`(dataId) -> repoPath + GithubPullRequestKeys.REPO_DETAILS.`is`(dataId) -> repoDetails GithubPullRequestKeys.SERVER_PATH.`is`(dataId) -> account.server GithubPullRequestKeys.PULL_REQUESTS_LIST_COMPONENT.`is`(dataId) -> list GithubPullRequestKeys.SELECTED_PULL_REQUEST_DATA_PROVIDER.`is`(dataId) -> selectionModel.current?.let(dataLoader::getDataProvider) diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsToolWindowManager.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsToolWindowManager.kt index ebab541fff76..3b585f41d858 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsToolWindowManager.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GithubPullRequestsToolWindowManager.kt @@ -18,6 +18,8 @@ import git4idea.repo.GitRepository import git4idea.repo.GitRepositoryChangeListener import git4idea.repo.GitRepositoryManager import icons.GithubIcons +import org.jetbrains.plugins.github.api.GithubApiRequestExecutor +import org.jetbrains.plugins.github.api.data.GithubRepoDetailed import org.jetbrains.plugins.github.authentication.accounts.AccountTokenChangedListener import org.jetbrains.plugins.github.authentication.accounts.GithubAccount import org.jetbrains.plugins.github.authentication.accounts.GithubAccountManager @@ -36,13 +38,15 @@ class GithubPullRequestsToolWindowManager internal constructor(private val proje private val accountManager: GithubAccountManager, private val componentFactory: GithubPullRequestsComponentFactory) { - fun showPullRequestsTab(repository: GitRepository, remote: GitRemote, remoteUrl: String, account: GithubAccount) { + fun createPullRequestsTab(requestExecutor: GithubApiRequestExecutor, + repository: GitRepository, remote: GitRemote, remoteUrl: String, + repoDetails: GithubRepoDetailed, + account: GithubAccount) { var toolWindow = toolWindowManager.getToolWindow(TOOL_WINDOW_ID) val contentManager: ContentManager - val content: Content if (toolWindow == null) { - val component = componentFactory.createComponent(repository, remote, remoteUrl, account) ?: return + val component = componentFactory.createComponent(requestExecutor, repository, remote, repoDetails, account) ?: return toolWindow = toolWindowManager.registerToolWindow(TOOL_WINDOW_ID, true, ToolWindowAnchor.BOTTOM, project, true) .apply { @@ -56,22 +60,26 @@ class GithubPullRequestsToolWindowManager internal constructor(private val proje } }) - content = createContent(contentManager, component, repository, remote, remoteUrl, account) + val content = createContent(contentManager, component, repository, remote, remoteUrl, account) contentManager.addContent(content) } else { contentManager = toolWindow.contentManager - val existingContent = contentManager.findContentByRemoteUrlInContent(remoteUrl) - - content = if (existingContent != null) existingContent - else { - val component = componentFactory.createComponent(repository, remote, remoteUrl, account) ?: return - createContent(contentManager, component, repository, remote, remoteUrl, account) + val existingContent = contentManager.findContent(repository, remote, remoteUrl, account) + if (existingContent == null) { + val component = componentFactory.createComponent(requestExecutor, repository, remote, repoDetails, account) ?: return + val content = createContent(contentManager, component, repository, remote, remoteUrl, account) + contentManager.addContent(content) } } + } - contentManager.setSelectedContent(content, true) + fun showPullRequestsTabIfExists(repository: GitRepository, remote: GitRemote, remoteUrl: String, account: GithubAccount): Boolean { + val toolWindow = toolWindowManager.getToolWindow(TOOL_WINDOW_ID) ?: return false + val content = toolWindow.contentManager.findContent(repository, remote, remoteUrl, account) ?: return false + toolWindow.contentManager.setSelectedContent(content, true) toolWindow.show { } + return true } private fun createContent(contentManager: ContentManager, @@ -162,6 +170,11 @@ class GithubPullRequestsToolWindowManager internal constructor(private val proje } } - private fun ContentManager.findContentByRemoteUrlInContent(remoteUrl: String) = - contents.find { it.getUserData(REMOTE_URL_KEY) == remoteUrl } + private fun ContentManager.findContent(repository: GitRepository, remote: GitRemote, remoteUrl: String, account: GithubAccount) = + contents.find { + it.getUserData(REMOTE_URL_KEY) == remoteUrl && + it.getUserData(REMOTE_KEY) == remote && + it.getUserData(REPOSITORY_KEY) == repository && + it.getUserData(ACCOUNT_KEY) == account + } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/action/GithubPullRequestKeys.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/action/GithubPullRequestKeys.kt index d26a788ca34e..388b0b8598c4 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/action/GithubPullRequestKeys.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/action/GithubPullRequestKeys.kt @@ -4,8 +4,8 @@ package org.jetbrains.plugins.github.pullrequest.action import com.intellij.openapi.actionSystem.DataKey import git4idea.repo.GitRemote import git4idea.repo.GitRepository -import org.jetbrains.plugins.github.api.GithubFullPath import org.jetbrains.plugins.github.api.GithubServerPath +import org.jetbrains.plugins.github.api.data.GithubRepoDetailed import org.jetbrains.plugins.github.api.data.GithubSearchedIssue import org.jetbrains.plugins.github.pullrequest.data.GithubPullRequestsDataLoader import org.jetbrains.plugins.github.pullrequest.ui.GithubPullRequestsListComponent @@ -24,7 +24,7 @@ object GithubPullRequestKeys { @JvmStatic val REMOTE = DataKey.create("org.jetbrains.plugins.github.pullrequest.remote") @JvmStatic - val FULL_PATH = DataKey.create("org.jetbrains.plugins.github.pullrequest.remote.fullpath") + val REPO_DETAILS = DataKey.create("org.jetbrains.plugins.github.pullrequest.remote.repo.details") @JvmStatic val SERVER_PATH = DataKey.create("org.jetbrains.plugins.github.pullrequest.server.path") } \ No newline at end of file