Fixed state not updating properly after cherry-pick conflicting

This commit is contained in:
Abdelilah El Aissaoui 2024-06-12 11:24:23 +02:00
parent 995a29db52
commit 38867ebb07
No known key found for this signature in database
GPG Key ID: 7587FC860F594869
5 changed files with 117 additions and 67 deletions

View File

@ -38,7 +38,12 @@ class SharedRepositoryStateManager @Inject constructor(
}
}
launch {
tabState.refreshFlowFiltered(RefreshType.ALL_DATA, RefreshType.REPO_STATE) {
tabState.refreshFlowFiltered(
RefreshType.ALL_DATA,
RefreshType.REPO_STATE,
RefreshType.UNCOMMITTED_CHANGES,
RefreshType.UNCOMMITTED_CHANGES_AND_LOG
) {
updateRepositoryState(tabState.git)
}
}

View File

@ -8,6 +8,7 @@ import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.random.Random
private const val KEY_LENGTH = 16
@ -60,9 +61,8 @@ class CredentialsCacheRepository @Inject constructor() {
}
private fun String.cipherEncrypt(): String {
val secretKeySpec = SecretKeySpec(encryptionKey.toByteArray(), "AES")
val iv = encryptionKey.toByteArray()
val ivParameterSpec = IvParameterSpec(iv)
val secretKeySpec = SecretKeySpec(encryptionKey, "AES")
val ivParameterSpec = IvParameterSpec(encryptionKey)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
@ -72,9 +72,8 @@ class CredentialsCacheRepository @Inject constructor() {
}
private fun String.cipherDecrypt(): String {
val secretKeySpec = SecretKeySpec(encryptionKey.toByteArray(), "AES")
val iv = encryptionKey.toByteArray()
val ivParameterSpec = IvParameterSpec(iv)
val secretKeySpec = SecretKeySpec(encryptionKey, "AES")
val ivParameterSpec = IvParameterSpec(encryptionKey)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
@ -84,11 +83,11 @@ class CredentialsCacheRepository @Inject constructor() {
return String(decryptedValue)
}
private fun getRandomKey(): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9') + "#!$%=?-_.,@µ*:;+~".toList()
return (1..KEY_LENGTH)
.map { allowedChars.random() }
.joinToString("")
private fun getRandomKey(): ByteArray {
val byteArray = ByteArray(KEY_LENGTH)
Random.Default.nextBytes(byteArray)
return byteArray
}
}

View File

@ -67,6 +67,7 @@ import kotlinx.coroutines.launch
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.lib.RepositoryState
import org.eclipse.jgit.revwalk.RevCommit
import kotlin.math.log
private val colors = listOf(
Color(0xFF42a5f5),
@ -233,18 +234,27 @@ private fun LogLoaded(
repositoryState = repositoryState,
selectedItem = selectedItem,
commitList = commitList,
logViewModel = logViewModel,
graphWidth = graphWidth,
commitsLimit = logStatus.commitsLimit,
onMerge = { ref ->
logViewModel.mergeBranch(ref)
},
onRebase = { ref ->
logViewModel.rebaseBranch(ref)
},
onShowLogDialog = { dialog ->
logViewModel.showDialog(dialog)
}
onMerge = { ref -> logViewModel.mergeBranch(ref) },
onRebase = { ref -> logViewModel.rebaseBranch(ref) },
onShowLogDialog = { dialog -> logViewModel.showDialog(dialog) },
onCheckoutCommit = { logViewModel.checkoutCommit(it) },
onRevertCommit = { logViewModel.revertCommit(it) },
onCherryPickCommit = { logViewModel.cherryPickCommit(it) },
onCheckoutRemoteBranch = { logViewModel.checkoutRemoteBranch(it) },
onCheckoutRef = { logViewModel.checkoutRef(it) },
onRebaseInteractive = { logViewModel.rebaseInteractive(it) },
onCommitSelected = { logViewModel.selectCommit(it) },
onUncommittedChangesSelected = { logViewModel.selectUncommittedChanges() },
onDeleteStash = { logViewModel.deleteStash(it) },
onApplyStash = { logViewModel.applyStash(it) },
onPopStash = { logViewModel.popStash(it) },
onDeleteBranch = { logViewModel.deleteBranch(it) },
onDeleteRemoteBranch = { logViewModel.deleteRemoteBranch(it) },
onDeleteTag = { logViewModel.deleteTag(it) },
onPushToRemoteBranch = { logViewModel.pushToRemoteBranch(it) },
onPullFromRemoteBranch = { logViewModel.pullFromRemoteBranch(it) },
)
val density = LocalDensity.current.density
@ -443,10 +453,25 @@ fun CommitsList(
repositoryState: RepositoryState,
selectedItem: SelectedItem,
commitList: GraphCommitList,
logViewModel: LogViewModel,
commitsLimit: Int,
onCheckoutCommit: (GraphNode) -> Unit,
onRevertCommit: (GraphNode) -> Unit,
onCherryPickCommit: (GraphNode) -> Unit,
onCheckoutRemoteBranch: (Ref) -> Unit,
onCheckoutRef: (Ref) -> Unit,
onMerge: (Ref) -> Unit,
onRebase: (Ref) -> Unit,
onRebaseInteractive: (GraphNode) -> Unit,
onCommitSelected: (GraphNode) -> Unit,
onUncommittedChangesSelected: () -> Unit,
onDeleteStash: (GraphNode) -> Unit,
onApplyStash: (GraphNode) -> Unit,
onPopStash: (GraphNode) -> Unit,
onDeleteBranch: (Ref) -> Unit,
onDeleteRemoteBranch: (Ref) -> Unit,
onDeleteTag: (Ref) -> Unit,
onPushToRemoteBranch: (Ref) -> Unit,
onPullFromRemoteBranch: (Ref) -> Unit,
onShowLogDialog: (LogDialog) -> Unit,
graphWidth: Dp,
horizontalScrollState: ScrollState,
@ -478,7 +503,7 @@ fun CommitsList(
modifier = Modifier.height(MaterialTheme.linesHeight.logCommitHeight)
.clipToBounds()
.fillMaxWidth()
.clickable { logViewModel.selectUncommittedChanges() }
.clickable { onUncommittedChangesSelected() }
) {
UncommittedChangesGraphNode(
hasPreviousCommits = commitList.isNotEmpty(),
@ -501,7 +526,6 @@ fun CommitsList(
items(items = commitList) { graphNode ->
CommitLine(
graphWidth = graphWidth,
logViewModel = logViewModel,
graphNode = graphNode,
isSelected = selectedCommit?.name == graphNode.name,
currentBranch = logStatus.currentBranch,
@ -511,13 +535,23 @@ fun CommitsList(
showCreateNewTag = { onShowLogDialog(LogDialog.NewTag(graphNode)) },
resetBranch = { onShowLogDialog(LogDialog.ResetBranch(graphNode)) },
onMergeBranch = onMerge,
onDeleteBranch = onDeleteBranch,
onDeleteRemoteBranch = onDeleteRemoteBranch,
onDeleteTag = onDeleteTag,
onPushToRemoteBranch = onPushToRemoteBranch,
onPullFromRemoteBranch = onPullFromRemoteBranch,
onRebaseBranch = onRebase,
onRebaseInteractive = { logViewModel.rebaseInteractive(graphNode) },
onRevCommitSelected = { logViewModel.selectLogLine(graphNode) },
onRebaseInteractive = { onRebaseInteractive(graphNode) },
onRevCommitSelected = { onCommitSelected(graphNode) },
onChangeDefaultUpstreamBranch = { onShowLogDialog(LogDialog.ChangeDefaultBranch(it)) },
onDeleteStash = { logViewModel.deleteStash(graphNode) },
onApplyStash = { logViewModel.applyStash(graphNode) },
onPopStash = { logViewModel.popStash(graphNode) },
onDeleteStash = { onDeleteStash(graphNode) },
onApplyStash = { onApplyStash(graphNode) },
onPopStash = { onPopStash(graphNode) },
onCheckoutCommit = { onCheckoutCommit(graphNode) },
onRevertCommit = { onRevertCommit(graphNode) },
onCherryPickCommit = { onCherryPickCommit(graphNode) },
onCheckoutRemoteBranch = onCheckoutRemoteBranch,
onCheckoutRef = onCheckoutRef,
)
}
@ -751,7 +785,6 @@ fun SummaryEntry(
@Composable
private fun CommitLine(
graphWidth: Dp,
logViewModel: LogViewModel,
graphNode: GraphNode,
isSelected: Boolean,
currentBranch: Ref?,
@ -763,9 +796,19 @@ private fun CommitLine(
onPopStash: () -> Unit,
onDeleteStash: () -> Unit,
onMergeBranch: (Ref) -> Unit,
onDeleteBranch: (Ref) -> Unit,
onDeleteRemoteBranch: (Ref) -> Unit,
onDeleteTag: (Ref) -> Unit,
onPushToRemoteBranch: (Ref) -> Unit,
onPullFromRemoteBranch: (Ref) -> Unit,
onRebaseBranch: (Ref) -> Unit,
onRevCommitSelected: () -> Unit,
onRebaseInteractive: () -> Unit,
onCheckoutCommit: () -> Unit,
onRevertCommit: () -> Unit,
onCherryPickCommit: () -> Unit,
onCheckoutRemoteBranch: (Ref) -> Unit,
onCheckoutRef: (Ref) -> Unit,
onChangeDefaultUpstreamBranch: (Ref) -> Unit,
horizontalScrollState: ScrollState,
) {
@ -781,11 +824,11 @@ private fun CommitLine(
)
} else {
logContextMenu(
onCheckoutCommit = { logViewModel.checkoutCommit(graphNode) },
onCheckoutCommit = onCheckoutCommit,//{ logViewModel.checkoutCommit(graphNode) },
onCreateNewBranch = showCreateNewBranch,
onCreateNewTag = showCreateNewTag,
onRevertCommit = { logViewModel.revertCommit(graphNode) },
onCherryPickCommit = { logViewModel.cherrypickCommit(graphNode) },
onRevertCommit = onRevertCommit,//{ logViewModel.revertCommit(graphNode) },
onCherryPickCommit = onCherryPickCommit, //{ logViewModel.cherryPickCommit(graphNode) },
onRebaseInteractive = onRebaseInteractive,
onResetBranch = { resetBranch() },
isLastCommit = isLastCommitOfCurrentBranch
@ -848,18 +891,18 @@ private fun CommitLine(
currentBranch = currentBranch,
onCheckoutRef = { ref ->
if (ref.isRemote && ref.isBranch) {
logViewModel.checkoutRemoteBranch(ref)
onCheckoutRemoteBranch(ref)
} else {
logViewModel.checkoutRef(ref)
onCheckoutRef(ref)
}
},
onMergeBranch = { ref -> onMergeBranch(ref) },
onDeleteBranch = { ref -> logViewModel.deleteBranch(ref) },
onDeleteRemoteBranch = { ref -> logViewModel.deleteRemoteBranch(ref) },
onDeleteTag = { ref -> logViewModel.deleteTag(ref) },
onDeleteBranch = { ref -> onDeleteBranch(ref) },
onDeleteRemoteBranch = { ref -> onDeleteRemoteBranch(ref) },
onDeleteTag = { ref -> onDeleteTag(ref) },
onRebaseBranch = { ref -> onRebaseBranch(ref) },
onPushRemoteBranch = { ref -> logViewModel.pushToRemoteBranch(ref) },
onPullRemoteBranch = { ref -> logViewModel.pullFromRemoteBranch(ref) },
onPushRemoteBranch = { ref -> onPushToRemoteBranch(ref) },
onPullRemoteBranch = { ref -> onPullFromRemoteBranch(ref) },
onChangeDefaultUpstreamBranch = { ref -> onChangeDefaultUpstreamBranch(ref) },
)
}

View File

@ -180,17 +180,18 @@ class LogViewModel @Inject constructor(
fun resetToCommit(revCommit: RevCommit, resetType: ResetType) = tabState.safeProcessing(
refreshType = RefreshType.ALL_DATA,
title = "Branch reset",
subtitle = "Reseting branch to commit ${revCommit.shortName}",
subtitle = "Resetting branch to commit ${revCommit.shortName}",
taskType = TaskType.RESET_TO_COMMIT,
) { git ->
resetToCommitUseCase(git, revCommit, resetType = resetType)
}
fun cherrypickCommit(revCommit: RevCommit) = tabState.safeProcessing(
fun cherryPickCommit(revCommit: RevCommit) = tabState.safeProcessing(
refreshType = RefreshType.UNCOMMITTED_CHANGES_AND_LOG,
title = "Cherry-pick",
subtitle = "Cherry-picking commit ${revCommit.shortName}",
taskType = TaskType.CHERRY_PICK_COMMIT,
refreshEvenIfCrashes = true,
) { git ->
cherryPickCommitUseCase(git, revCommit)
}
@ -266,7 +267,7 @@ class LogViewModel @Inject constructor(
NONE_MATCHING_INDEX
}
fun selectLogLine(commit: GraphNode) = tabState.runOperation(
fun selectCommit(commit: GraphNode) = tabState.runOperation(
refreshType = RefreshType.NONE,
) {
tabState.newSelectedCommit(commit)

View File

@ -4,10 +4,7 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.ui.text.input.TextFieldValue
import com.jetpackduba.gitnuro.SharedRepositoryStateManager
import com.jetpackduba.gitnuro.TaskType
import com.jetpackduba.gitnuro.extensions.delayedStateChange
import com.jetpackduba.gitnuro.extensions.isMerging
import com.jetpackduba.gitnuro.extensions.isReverting
import com.jetpackduba.gitnuro.extensions.lowercaseContains
import com.jetpackduba.gitnuro.extensions.*
import com.jetpackduba.gitnuro.git.RefreshType
import com.jetpackduba.gitnuro.git.TabState
import com.jetpackduba.gitnuro.git.author.LoadAuthorUseCase
@ -125,7 +122,10 @@ class StatusViewModel @Inject constructor(
if (showAsTree) {
StageStateUi.TreeLoaded(
staged = entriesToTreeEntry(stageStateFiltered.staged, contractedDirectories) { it.filePath },
unstaged = entriesToTreeEntry(stageStateFiltered.unstaged, contractedDirectories) { it.filePath },
unstaged = entriesToTreeEntry(
stageStateFiltered.unstaged,
contractedDirectories
) { it.filePath },
isPartiallyReloading = stageStateFiltered.isPartiallyReloading,
)
} else {
@ -241,19 +241,19 @@ class StatusViewModel @Inject constructor(
private suspend fun loadStatus(git: Git) {
val previousStatus = _stageState.value
val requiredMessageType = if (git.repository.repositoryState == RepositoryState.MERGING) {
val type = if (
git.repository.repositoryState.isRebasing ||
git.repository.repositoryState.isMerging ||
git.repository.repositoryState.isReverting ||
git.repository.repositoryState.isCherryPicking
) {
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))
if (type != savedCommitMessage.type) {
savedCommitMessage = CommitMessage(messageByRepoState(git), type)
_commitMessageChangesFlow.emit(savedCommitMessage.message)
}
@ -300,15 +300,17 @@ class StatusViewModel @Inject constructor(
}
private fun messageByRepoState(git: Git): String {
val message: String? = if (
git.repository.repositoryState.isMerging ||
git.repository.repositoryState.isRebasing ||
git.repository.repositoryState.isReverting
) {
git.repository.readMergeCommitMsg()
} else {
git.repository.readCommitEditMsg()
}
val message: String? =
if (
git.repository.repositoryState.isMerging ||
git.repository.repositoryState.isRebasing ||
git.repository.repositoryState.isReverting ||
git.repository.repositoryState.isCherryPicking
) {
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", " ")
@ -579,7 +581,7 @@ sealed interface StageStateUi {
}
}
data class CommitMessage(val message: String, val messageType: MessageType)
data class CommitMessage(val message: String, val type: MessageType)
enum class MessageType {
NORMAL,