158 lines
4.8 KiB
Kotlin
158 lines
4.8 KiB
Kotlin
package app.viewmodels
|
|
|
|
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 java.io.File
|
|
import javax.inject.Inject
|
|
|
|
class StatusViewModel @Inject constructor(
|
|
private val tabState: TabState,
|
|
private val statusManager: StatusManager,
|
|
private val branchesManager: BranchesManager,
|
|
private val repositoryManager: RepositoryManager,
|
|
private val rebaseManager: RebaseManager,
|
|
private val mergeManager: MergeManager,
|
|
private val logManager: LogManager,
|
|
) {
|
|
private val _stageStatus = MutableStateFlow<StageStatus>(StageStatus.Loaded(listOf(), listOf()))
|
|
val stageStatus: StateFlow<StageStatus> = _stageStatus
|
|
|
|
var savedCommitMessage: String = ""
|
|
var hasPreviousCommits = true // When false, disable "amend previous commit"
|
|
|
|
private var lastUncommitedChangesState = false
|
|
|
|
fun stage(statusEntry: StatusEntry) = tabState.runOperation(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.stage(git, statusEntry)
|
|
}
|
|
|
|
fun unstage(statusEntry: StatusEntry) = tabState.runOperation(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.unstage(git, statusEntry)
|
|
}
|
|
|
|
|
|
fun unstageAll() = tabState.safeProcessing(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.unstageAll(git)
|
|
}
|
|
|
|
fun stageAll() = tabState.safeProcessing(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.stageAll(git)
|
|
}
|
|
|
|
fun resetStaged(statusEntry: StatusEntry) = tabState.runOperation(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.reset(git, statusEntry, staged = true)
|
|
}
|
|
|
|
fun resetUnstaged(statusEntry: StatusEntry) = tabState.runOperation(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
statusManager.reset(git, statusEntry, staged = false)
|
|
}
|
|
|
|
private suspend fun loadStatus(git: Git) {
|
|
val previousStatus = _stageStatus.value
|
|
|
|
try {
|
|
_stageStatus.value = StageStatus.Loading
|
|
val status = statusManager.getStatus(git)
|
|
val staged = statusManager.getStaged(status)
|
|
val unstaged = statusManager.getUnstaged(status)
|
|
|
|
_stageStatus.value = StageStatus.Loaded(staged, unstaged)
|
|
} catch (ex: Exception) {
|
|
_stageStatus.value = previousStatus
|
|
throw ex
|
|
}
|
|
}
|
|
|
|
private suspend fun loadHasUncommitedChanges(git: Git) = withContext(Dispatchers.IO) {
|
|
lastUncommitedChangesState = statusManager.hasUncommitedChanges(git)
|
|
}
|
|
|
|
fun commit(message: String, amend: Boolean) = tabState.safeProcessing(
|
|
refreshType = RefreshType.ALL_DATA,
|
|
) { git ->
|
|
val commitMessage = if (amend && message.isBlank()) {
|
|
logManager.latestMessage(git)
|
|
} else
|
|
message
|
|
|
|
statusManager.commit(git, commitMessage, amend)
|
|
}
|
|
|
|
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
|
|
loadStatus(git)
|
|
loadHasUncommitedChanges(git)
|
|
}
|
|
|
|
/**
|
|
* Checks if there are uncommited changes and returns if the state has changed (
|
|
*/
|
|
suspend fun updateHasUncommitedChanges(git: Git): Boolean {
|
|
val hadUncommitedChanges = this.lastUncommitedChangesState
|
|
|
|
loadStatus(git)
|
|
loadHasUncommitedChanges(git)
|
|
|
|
val hasNowUncommitedChanges = this.lastUncommitedChangesState
|
|
hasPreviousCommits = logManager.hasPreviousCommits(git)
|
|
|
|
// Return true to update the log only if the uncommitedChanges status has changed
|
|
return (hasNowUncommitedChanges != hadUncommitedChanges)
|
|
}
|
|
|
|
fun continueRebase() = tabState.safeProcessing(
|
|
refreshType = RefreshType.ALL_DATA,
|
|
) { git ->
|
|
rebaseManager.continueRebase(git)
|
|
}
|
|
|
|
fun abortRebase() = tabState.safeProcessing(
|
|
refreshType = RefreshType.ALL_DATA,
|
|
) { git ->
|
|
rebaseManager.abortRebase(git)
|
|
}
|
|
|
|
fun skipRebase() = tabState.safeProcessing(
|
|
refreshType = RefreshType.ALL_DATA,
|
|
) { git ->
|
|
rebaseManager.skipRebase(git)
|
|
}
|
|
|
|
fun abortMerge() = tabState.safeProcessing(
|
|
refreshType = RefreshType.ALL_DATA,
|
|
) { git ->
|
|
mergeManager.abortMerge(git)
|
|
}
|
|
|
|
fun deleteFile(statusEntry: StatusEntry) = tabState.runOperation(
|
|
refreshType = RefreshType.UNCOMMITED_CHANGES,
|
|
) { git ->
|
|
val path = statusEntry.filePath
|
|
|
|
val fileToDelete = File(git.repository.directory.parent, path)
|
|
|
|
fileToDelete.delete()
|
|
}
|
|
}
|
|
|
|
sealed class StageStatus {
|
|
object Loading : StageStatus()
|
|
data class Loaded(val staged: List<StatusEntry>, val unstaged: List<StatusEntry>) : StageStatus()
|
|
}
|
|
|