Gitnuro/src/main/kotlin/app/git/LogManager.kt
2021-12-18 02:23:39 +01:00

112 lines
3.5 KiB
Kotlin

package app.git
import app.extensions.isBranch
import app.extensions.simpleName
import app.git.graph.GraphCommitList
import app.git.graph.GraphWalk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.CreateBranchCommand
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.ResetCommand
import org.eclipse.jgit.lib.Constants
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.revwalk.RevCommit
import javax.inject.Inject
class LogManager @Inject constructor(
private val statusManager: StatusManager,
private val branchesManager: BranchesManager,
) {
private val _logStatus = MutableStateFlow<LogStatus>(LogStatus.Loading)
val logStatus: StateFlow<LogStatus>
get() = _logStatus
suspend fun loadLog(git: Git) = withContext(Dispatchers.IO) {
_logStatus.value = LogStatus.Loading
val currentBranch = branchesManager.currentBranchRef(git)
val commitList = GraphCommitList()
if(currentBranch != null) { // Current branch is null when there is no log (new repo)
val logList = git.log().setMaxCount(2).call().toList()
val walk = GraphWalk(git.repository)
walk.use {
walk.markStartAllRefs(Constants.R_HEADS)
walk.markStartAllRefs(Constants.R_REMOTES)
walk.markStartAllRefs(Constants.R_TAGS)
if (statusManager.checkHasUncommitedChanges(git))
commitList.addUncommitedChangesGraphCommit(logList.first())
commitList.source(walk)
commitList.fillTo(1000) // TODO: Limited commits to show to 1000, add a setting to let the user adjust this
}
ensureActive()
}
val loadedStatus = LogStatus.Loaded(commitList, currentBranch)
_logStatus.value = loadedStatus
}
suspend fun checkoutCommit(git: Git, revCommit: RevCommit) = withContext(Dispatchers.IO) {
git
.checkout()
.setName(revCommit.name)
.call()
}
suspend fun checkoutRef(git: Git, ref: Ref) = withContext(Dispatchers.IO) {
git.checkout().apply {
setName(ref.name)
if (ref.isBranch && ref.name.startsWith("refs/remotes/")) {
setCreateBranch(true)
setName(ref.simpleName)
setStartPoint(ref.objectId.name)
setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
}
call()
}
}
suspend fun revertCommit(git: Git, revCommit: RevCommit) = withContext(Dispatchers.IO) {
git
.revert()
.include(revCommit)
.call()
}
suspend fun resetToCommit(git: Git, revCommit: RevCommit, resetType: ResetType) = withContext(Dispatchers.IO) {
val reset = when (resetType) {
ResetType.SOFT -> ResetCommand.ResetType.SOFT
ResetType.MIXED -> ResetCommand.ResetType.MIXED
ResetType.HARD -> ResetCommand.ResetType.HARD
}
git
.reset()
.setMode(reset)
.setRef(revCommit.name)
.call()
}
}
// TODO Move this to
enum class ResetType {
SOFT,
MIXED,
HARD,
}
sealed class LogStatus {
object Loading : LogStatus()
class Loaded(val plotCommitList: GraphCommitList, val currentBranch: Ref?) : LogStatus()
}