mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[github] Check repo information before viewing pull requests
This allows to: 1. Check if user has access to repo 2. Follow repo rename redirects
This commit is contained in:
@@ -71,7 +71,7 @@ open class GithubOpenInBrowserActionGroup
|
||||
private fun getDataFromPullRequest(project: Project, dataContext: DataContext): Pair<Set<GithubRepositoryPath>, 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)
|
||||
|
||||
@@ -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<GithubPullRequestsToolWindowManager>().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<GithubApiRequestExecutorManager>().getExecutor(account, project) ?: return
|
||||
|
||||
val toolWindowManager = project.service<GithubPullRequestsToolWindowManager>()
|
||||
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()
|
||||
}
|
||||
}
|
||||
+11
-12
@@ -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)
|
||||
|
||||
+26
-13
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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<GitRemote>("org.jetbrains.plugins.github.pullrequest.remote")
|
||||
@JvmStatic
|
||||
val FULL_PATH = DataKey.create<GithubFullPath>("org.jetbrains.plugins.github.pullrequest.remote.fullpath")
|
||||
val REPO_DETAILS = DataKey.create<GithubRepoDetailed>("org.jetbrains.plugins.github.pullrequest.remote.repo.details")
|
||||
@JvmStatic
|
||||
val SERVER_PATH = DataKey.create<GithubServerPath>("org.jetbrains.plugins.github.pullrequest.server.path")
|
||||
}
|
||||
Reference in New Issue
Block a user