Added persistance of commit message

Merge message is also recovered when having conflicts
This commit is contained in:
Abdelilah El Aissaoui 2022-06-06 00:49:02 +02:00
parent 7335499f97
commit 67aff36bc4
3 changed files with 86 additions and 12 deletions

View File

@ -404,7 +404,7 @@ fun DiffLine(
}
Text(
text = line.text.replace("\t", " "), // this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615
text = line.text.replace("\t", " "), // TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615
modifier = Modifier
.padding(start = 8.dp)
.fillMaxSize(),

View File

@ -40,6 +40,7 @@ import app.ui.components.SecondaryButton
import app.ui.context_menu.*
import app.viewmodels.StageStatus
import app.viewmodels.StatusViewModel
import kotlinx.coroutines.flow.collect
import org.eclipse.jgit.lib.RepositoryState
@Composable
@ -53,7 +54,7 @@ fun UncommitedChanges(
onHistoryFile: (String) -> Unit,
) {
val stageStatusState = statusViewModel.stageStatus.collectAsState()
var commitMessage by remember { mutableStateOf(statusViewModel.savedCommitMessage) }
var commitMessage by remember { mutableStateOf(statusViewModel.savedCommitMessage.message) }
val stageStatus = stageStatusState.value
val staged: List<StatusEntry>
@ -70,13 +71,18 @@ fun UncommitedChanges(
val doCommit = { amend: Boolean ->
statusViewModel.commit(commitMessage, amend)
onStagedDiffEntrySelected(null)
statusViewModel.savedCommitMessage = ""
commitMessage = ""
}
val canCommit = commitMessage.isNotEmpty() && staged.isNotEmpty()
val canAmend = (commitMessage.isNotEmpty() || staged.isNotEmpty()) && statusViewModel.hasPreviousCommits
LaunchedEffect(Unit) {
statusViewModel.commitMessageChangesFlow.collect { newCommitMessage ->
commitMessage = newCommitMessage
}
}
Column {
AnimatedVisibility(
visible = stageStatus is StageStatus.Loading,
@ -94,7 +100,7 @@ fun UncommitedChanges(
title = "Staged",
allActionTitle = "Unstage all",
actionTitle = "Unstage",
selectedEntryType = if(selectedEntryType is DiffEntryType.StagedDiff) selectedEntryType else null,
selectedEntryType = if (selectedEntryType is DiffEntryType.StagedDiff) selectedEntryType else null,
actionColor = MaterialTheme.colors.unstageButton,
statusEntries = staged,
onDiffEntrySelected = onStagedDiffEntrySelected,
@ -122,7 +128,7 @@ fun UncommitedChanges(
.fillMaxWidth(),
title = "Unstaged",
actionTitle = "Stage",
selectedEntryType = if(selectedEntryType is DiffEntryType.UnstagedDiff) selectedEntryType else null,
selectedEntryType = if (selectedEntryType is DiffEntryType.UnstagedDiff) selectedEntryType else null,
actionColor = MaterialTheme.colors.stageButton,
statusEntries = unstaged,
onDiffEntrySelected = onUnstagedDiffEntrySelected,
@ -175,7 +181,8 @@ fun UncommitedChanges(
value = commitMessage,
onValueChange = {
commitMessage = it
statusViewModel.savedCommitMessage = it
statusViewModel.updateCommitMessage(it)
},
label = { Text("Write your commit message here", fontSize = 14.sp) },
colors = textFieldColors(),
@ -185,13 +192,19 @@ fun UncommitedChanges(
when {
repositoryState.isMerging -> MergeButtons(
haveConflictsBeenSolved = unstaged.isEmpty(),
onAbort = { statusViewModel.abortMerge() },
onAbort = {
statusViewModel.abortMerge()
statusViewModel.updateCommitMessage("")
},
onMerge = { doCommit(false) }
)
repositoryState.isRebasing -> RebasingButtons(
canContinue = staged.isNotEmpty() || unstaged.isNotEmpty(),
haveConflictsBeenSolved = unstaged.isEmpty(),
onAbort = { statusViewModel.abortRebase() },
onAbort = {
statusViewModel.abortRebase()
statusViewModel.updateCommitMessage("")
},
onContinue = { statusViewModel.continueRebase() },
onSkip = { statusViewModel.skipRebase() },
)
@ -502,7 +515,7 @@ private fun FileEntry(
tint = statusEntry.iconColor,
)
if(statusEntry.parentDirectoryPath.isNotEmpty()) {
if (statusEntry.parentDirectoryPath.isNotEmpty()) {
Text(
text = statusEntry.parentDirectoryPath,
modifier = Modifier.weight(1f, fill = false),

View File

@ -1,19 +1,21 @@
package app.viewmodels
import app.extensions.isMerging
import app.git.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.RepositoryState
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,
@ -21,11 +23,32 @@ class StatusViewModel @Inject constructor(
private val _stageStatus = MutableStateFlow<StageStatus>(StageStatus.Loaded(listOf(), listOf()))
val stageStatus: StateFlow<StageStatus> = _stageStatus
var savedCommitMessage: String = ""
var savedCommitMessage = CommitMessage("", MessageType.NORMAL)
var hasPreviousCommits = true // When false, disable "amend previous commit"
private var lastUncommitedChangesState = false
/**
* Notify the UI that the commit message has been changed by the view model
*/
private val _commitMessageChangesFlow = MutableSharedFlow<String>()
val commitMessageChangesFlow: SharedFlow<String> = _commitMessageChangesFlow
private fun persistMessage() = tabState.runOperation(
refreshType = RefreshType.NONE,
) { git ->
val messageToPersist = savedCommitMessage.message.ifBlank { null }
println("Persisting message: $messageToPersist")
if (git.repository.repositoryState.isMerging) {
git.repository.writeMergeCommitMsg(messageToPersist)
} else if (git.repository.repositoryState == RepositoryState.SAFE) {
git.repository.writeCommitEditMsg(messageToPersist)
}
}
fun stage(statusEntry: StatusEntry) = tabState.runOperation(
refreshType = RefreshType.UNCOMMITED_CHANGES,
) { git ->
@ -66,6 +89,21 @@ class StatusViewModel @Inject constructor(
private suspend fun loadStatus(git: Git) {
val previousStatus = _stageStatus.value
val requiredMessageType = if (git.repository.repositoryState == RepositoryState.MERGING) {
MessageType.MERGE
} else {
MessageType.NORMAL
}
if (requiredMessageType != savedCommitMessage.messageType) {
savedCommitMessage = CommitMessage(messageByRepoState(git), requiredMessageType)
_commitMessageChangesFlow.emit(savedCommitMessage.message)
} else if (savedCommitMessage.message.isEmpty()) {
savedCommitMessage = savedCommitMessage.copy(message = messageByRepoState(git))
_commitMessageChangesFlow.emit(savedCommitMessage.message)
}
try {
_stageStatus.value = StageStatus.Loading
val status = statusManager.getStatus(git)
@ -79,6 +117,17 @@ class StatusViewModel @Inject constructor(
}
}
private fun messageByRepoState(git: Git): String {
val message: String? = if (git.repository.repositoryState == RepositoryState.MERGING) {
git.repository.readMergeCommitMsg()
} else {
git.repository.readCommitEditMsg()
}
//TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615
return message.orEmpty().replace("\t", " ")
}
private suspend fun loadHasUncommitedChanges(git: Git) = withContext(Dispatchers.IO) {
lastUncommitedChangesState = statusManager.hasUncommitedChanges(git)
}
@ -92,6 +141,7 @@ class StatusViewModel @Inject constructor(
message
statusManager.commit(git, commitMessage, amend)
updateCommitMessage("")
}
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
@ -148,6 +198,11 @@ class StatusViewModel @Inject constructor(
fileToDelete.delete()
}
fun updateCommitMessage(message: String) {
savedCommitMessage = savedCommitMessage.copy(message = message)
persistMessage()
}
}
sealed class StageStatus {
@ -155,3 +210,9 @@ sealed class StageStatus {
data class Loaded(val staged: List<StatusEntry>, val unstaged: List<StatusEntry>) : StageStatus()
}
data class CommitMessage(val message: String, val messageType: MessageType)
enum class MessageType {
NORMAL,
MERGE;
}