Added remote branch deletion

This commit is contained in:
Abdelilah El Aissaoui 2022-02-04 18:53:21 +01:00
parent fc4d52b57a
commit 07703a66be
6 changed files with 121 additions and 39 deletions

View File

@ -9,6 +9,7 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.ProgressMonitor
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.transport.*
import java.io.File
import javax.inject.Inject
@ -25,11 +26,7 @@ class RemoteOperationsManager @Inject constructor(
git
.pull()
.setTransportConfigCallback {
if (it is SshTransport) {
it.sshSessionFactory = sessionManager.generateSshSessionFactory()
} else if (it is HttpTransport) {
it.credentialsProvider = HttpCredentialsProvider()
}
handleTransportCredentials(it)
}
.setRebase(rebase)
.setCredentialsProvider(CredentialsProvider.getDefault())
@ -44,11 +41,7 @@ class RemoteOperationsManager @Inject constructor(
.setRemote(remote.name)
.setRefSpecs(remote.fetchRefSpecs)
.setTransportConfigCallback {
if (it is SshTransport) {
it.sshSessionFactory = sessionManager.generateSshSessionFactory()
} else if (it is HttpTransport) {
it.credentialsProvider = HttpCredentialsProvider()
}
handleTransportCredentials(it)
}
.setCredentialsProvider(CredentialsProvider.getDefault())
.call()
@ -64,11 +57,7 @@ class RemoteOperationsManager @Inject constructor(
.setForce(force)
.setPushTags()
.setTransportConfigCallback {
if (it is SshTransport) {
it.sshSessionFactory = sessionManager.generateSshSessionFactory()
} else if (it is HttpTransport) {
it.credentialsProvider = HttpCredentialsProvider()
}
handleTransportCredentials(it)
}
.call()
@ -87,6 +76,40 @@ class RemoteOperationsManager @Inject constructor(
}
}
private fun handleTransportCredentials(transport: Transport?) {
if (transport is SshTransport) {
transport.sshSessionFactory = sessionManager.generateSshSessionFactory()
} else if (transport is HttpTransport) {
transport.credentialsProvider = HttpCredentialsProvider()
}
}
suspend fun deleteBranch(git: Git, ref: Ref) = withContext(Dispatchers.IO) {
git
.branchDelete()
.setBranchNames(ref.name)
.call()
val branchSplit = ref.name.split("/").toMutableList()
val remoteName = branchSplit[2] // Remote name
repeat(3) {
branchSplit.removeAt(0)
}
val branchName = "refs/heads/${branchSplit.joinToString("/")}"
val refSpec = RefSpec()
.setSource(null)
.setDestination(branchName)
git.push()
.setTransportConfigCallback {
handleTransportCredentials(it)
}
.setRefSpecs(refSpec)
.setRemote(remoteName)
.call()
}
private val RemoteRefUpdate.Status.isRejected: Boolean
get() {
return this == RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD ||
@ -140,11 +163,7 @@ class RemoteOperationsManager @Inject constructor(
})
.setTransportConfigCallback {
if (it is SshTransport) {
it.sshSessionFactory = sessionManager.generateSshSessionFactory()
} else if (it is HttpTransport) {
it.credentialsProvider = HttpCredentialsProvider()
}
handleTransportCredentials(it)
}
.call()
@ -158,6 +177,7 @@ class RemoteOperationsManager @Inject constructor(
_cloneStatus.value = CloneStatus.None
}
}
sealed class CloneStatus {

View File

@ -1,5 +1,7 @@
package app.ui
import androidx.compose.foundation.ContextMenuArea
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
@ -11,10 +13,16 @@ import app.extensions.simpleVisibleName
import app.git.RemoteInfo
import app.ui.components.SideMenuPanel
import app.ui.components.SideMenuSubentry
import app.ui.components.VerticalExpandable
import app.ui.context_menu.remoteBranchesContextMenu
import app.viewmodels.RemotesViewModel
import org.eclipse.jgit.lib.Ref
@Composable
fun Remotes(remotesViewModel: RemotesViewModel) {
fun Remotes(
remotesViewModel: RemotesViewModel,
onBranchClicked: (Ref) -> Unit,
) {
val remotes by remotesViewModel.remotes.collectAsState()
val itemsCount = remember(remotes) {
@ -28,28 +36,48 @@ fun Remotes(remotesViewModel: RemotesViewModel) {
items = remotes,
itemsCountForMaxHeight = itemsCount,
itemContent = { remoteInfo ->
RemoteRow(remoteInfo)
RemoteRow(
remote = remoteInfo,
onBranchClicked = { branch -> onBranchClicked(branch) },
onDeleteBranch = { branch -> remotesViewModel.deleteBranch(branch) }
)
}
)
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun RemoteRow(
remote: RemoteInfo,
onBranchClicked: (Ref) -> Unit,
onDeleteBranch: (Ref) -> Unit,
) {
SideMenuSubentry(
text = remote.remoteConfig.name,
iconResourcePath = "cloud.svg",
)
val branches = remote.branchesList
Column {
branches.forEach { branch ->
VerticalExpandable(
header = {
SideMenuSubentry(
text = branch.simpleVisibleName,
extraPadding = 8.dp,
iconResourcePath = "branch.svg",
text = remote.remoteConfig.name,
iconResourcePath = "cloud.svg",
)
}
) {
val branches = remote.branchesList
Column {
branches.forEach { branch ->
ContextMenuArea(
items = {
remoteBranchesContextMenu(
onDeleteBranch = { onDeleteBranch(branch) }
)
}
) {
SideMenuSubentry(
text = branch.simpleVisibleName,
extraPadding = 8.dp,
iconResourcePath = "branch.svg",
onClick = { onBranchClicked(branch) }
)
}
}
}
}
}

View File

@ -65,7 +65,12 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) {
tabViewModel.newSelectedRef(it.objectId)
}
)
Remotes(remotesViewModel = tabViewModel.remotesViewModel)
Remotes(
remotesViewModel = tabViewModel.remotesViewModel,
onBranchClicked = {
tabViewModel.newSelectedRef(it.objectId)
}
)
Tags(
tagsViewModel = tabViewModel.tagsViewModel,
onTagClicked = {

View File

@ -25,14 +25,19 @@ fun SideMenuSubentry(
iconResourcePath: String,
bold: Boolean = false,
extraPadding: Dp = 0.dp,
onClick: () -> Unit = {},
onClick: (() -> Unit)? = null,
additionalInfo: @Composable () -> Unit = {}
) {
Row(
modifier = Modifier
.height(ENTRY_HEIGHT.dp)
.fillMaxWidth()
.clickable(onClick = onClick)
.run {
if(onClick != null)
clickable(onClick = onClick)
else
this
}
.padding(start = extraPadding),
verticalAlignment = Alignment.CenterVertically,
) {

View File

@ -0,0 +1,17 @@
@file:OptIn(ExperimentalFoundationApi::class)
package app.ui.context_menu
import androidx.compose.foundation.ContextMenuItem
import androidx.compose.foundation.ExperimentalFoundationApi
fun remoteBranchesContextMenu(
onDeleteBranch: () -> Unit
): List<ContextMenuItem> {
return mutableListOf(
ContextMenuItem(
label = "Delete remote branch",
onClick = onDeleteBranch
),
)
}

View File

@ -1,18 +1,19 @@
package app.viewmodels
import app.git.BranchesManager
import app.git.RemoteInfo
import app.git.RemotesManager
import app.git.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Ref
import javax.inject.Inject
class RemotesViewModel @Inject constructor(
private val remotesManager: RemotesManager,
private val remoteOperationsManager: RemoteOperationsManager,
private val branchesManager: BranchesManager,
private val tabState: TabState,
) {
private val _remotes = MutableStateFlow<List<RemoteInfo>>(listOf())
val remotes: StateFlow<List<RemoteInfo>>
@ -34,6 +35,12 @@ class RemotesViewModel @Inject constructor(
_remotes.value = remoteInfoList
}
fun deleteBranch(ref: Ref) = tabState.safeProcessing { git ->
remoteOperationsManager.deleteBranch(git, ref)
return@safeProcessing RefreshType.ALL_DATA
}
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
loadRemotes(git)
}