Gitnuro/src/main/kotlin/app/viewmodels/RemotesViewModel.kt
2022-02-17 19:24:36 +01:00

133 lines
4.4 KiB
Kotlin

package app.viewmodels
import app.exceptions.InvalidRemoteUrlException
import app.git.*
import app.ui.dialogs.RemoteWrapper
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.api.RemoteSetUrlCommand
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.transport.URIish
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<RemoteView>>(listOf())
val remotes: StateFlow<List<RemoteView>>
get() = _remotes
suspend fun loadRemotes(git: Git) = withContext(Dispatchers.IO) {
val remotes = git.remoteList()
.call()
val allRemoteBranches = branchesManager.remoteBranches(git)
remotesManager.loadRemotes(git, allRemoteBranches)
val remoteInfoList = remotes.map { remoteConfig ->
val remoteBranches = allRemoteBranches.filter { branch ->
branch.name.startsWith("refs/remotes/${remoteConfig.name}")
}
RemoteInfo(remoteConfig, remoteBranches)
}
val remoteViewList = remoteInfoList.map { remoteInfo ->
RemoteView(remoteInfo, true)
}
_remotes.value = remoteViewList
}
fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing(
refreshType = RefreshType.ALL_DATA,
) { git ->
remoteOperationsManager.deleteBranch(git, ref)
}
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
loadRemotes(git)
}
fun onRemoteClicked(remoteInfo: RemoteView) {
val remotes = _remotes.value
val newRemoteInfo = remoteInfo.copy(isExpanded = !remoteInfo.isExpanded)
val newRemotesList = remotes.toMutableList()
val indexToReplace = newRemotesList.indexOf(remoteInfo)
newRemotesList[indexToReplace] = newRemoteInfo
_remotes.value = newRemotesList
}
fun selectBranch(ref: Ref) {
tabState.newSelectedRef(ref.objectId)
}
fun deleteRemote(remoteName: String, isNew: Boolean) = tabState.safeProcessing(
refreshType = if(isNew) RefreshType.REMOTES else RefreshType.ALL_DATA,
showError = true,
) { git ->
remotesManager.deleteRemote(git, remoteName)
val remoteBranches = branchesManager.remoteBranches(git)
val remoteToDeleteBranchesNames = remoteBranches.filter {
it.name.startsWith("refs/remotes/$remoteName/")
}.map {
it.name
}
branchesManager.deleteLocallyRemoteBranches(git, remoteToDeleteBranchesNames)
}
fun addRemote(selectedRemoteConfig: RemoteWrapper) = tabState.runOperation(
refreshType = RefreshType.REMOTES,
showError = true,
) { git ->
if(selectedRemoteConfig.fetchUri.isBlank()) {
throw InvalidRemoteUrlException("Invalid empty fetch URI")
}
if(selectedRemoteConfig.pushUri.isBlank()) {
throw InvalidRemoteUrlException("Invalid empty push URI")
}
remotesManager.addRemote(git, selectedRemoteConfig.remoteName, selectedRemoteConfig.fetchUri)
updateRemote(selectedRemoteConfig) // Sets both, fetch and push uri
}
fun updateRemote(selectedRemoteConfig: RemoteWrapper) = tabState.runOperation(
refreshType = RefreshType.REMOTES,
showError = true,
) { git ->
if(selectedRemoteConfig.fetchUri.isBlank()) {
throw InvalidRemoteUrlException("Invalid empty fetch URI")
}
if(selectedRemoteConfig.pushUri.isBlank()) {
throw InvalidRemoteUrlException("Invalid empty push URI")
}
remotesManager.updateRemote(
git = git,
remoteName = selectedRemoteConfig.remoteName,
uri = selectedRemoteConfig.fetchUri,
uriType = RemoteSetUrlCommand.UriType.FETCH
)
remotesManager.updateRemote(
git = git,
remoteName = selectedRemoteConfig.remoteName,
uri = selectedRemoteConfig.pushUri,
uriType = RemoteSetUrlCommand.UriType.PUSH
)
}
}
data class RemoteView(val remoteInfo: RemoteInfo, val isExpanded: Boolean)