Added option to discard hunks

This commit is contained in:
Abdelilah El Aissaoui 2022-06-19 19:52:53 +02:00
parent 1835ff748d
commit 15827d119a
5 changed files with 90 additions and 4 deletions

View File

@ -29,3 +29,14 @@ val String.dirPath: String
} else
this
}
val String.lineDelimiter: String?
get() {
return if (this.contains("\r\n"))
"\r\n"
else if (this.contains("\n"))
"\n"
else
null
}

View File

@ -20,6 +20,8 @@ import org.eclipse.jgit.lib.FileMode
import org.eclipse.jgit.lib.ObjectInserter
import org.eclipse.jgit.lib.Repository
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.nio.ByteBuffer
import java.time.Instant
@ -145,6 +147,10 @@ class StatusManager @Inject constructor(
val content = rawFile.rawContent.toString(Charsets.UTF_8)//.removeSuffix(rawFile.lineDelimiter)
val lineDelimiter: String? = rawFile.lineDelimiter
return getTextLines(content, lineDelimiter)
}
private fun getTextLines(content: String, lineDelimiter: String?): List<String> {
var splitted: List<String> = if (lineDelimiter != null) {
content.split(lineDelimiter).toMutableList().apply {
if (this.last() == "")
@ -344,6 +350,52 @@ class StatusManager @Inject constructor(
addCommand.call()
}
}
suspend fun resetHunk(git: Git, diffEntry: DiffEntry, hunk: Hunk) = withContext(Dispatchers.IO) {
val repository = git.repository
try {
val file = File(repository.directory.parent, diffEntry.oldPath)
val content = file.readText()
val textLines = getTextLines(content, content.lineDelimiter).toMutableList()
val hunkLines = hunk.lines.filter { it.lineType != LineType.CONTEXT }
val addedLines = hunkLines
.filter { it.lineType == LineType.ADDED }
.sortedBy { it.newLineNumber }
val removedLines = hunkLines
.filter { it.lineType == LineType.REMOVED }
.sortedBy { it.newLineNumber }
var linesRemoved = 0
// Start by removing the added lines to the index
for (line in addedLines) {
textLines.removeAt(line.newLineNumber + linesRemoved)
linesRemoved--
}
var linesAdded = 0
// Restore previously removed lines to the index
for (line in removedLines) {
// Check how many lines before this one have been deleted
val previouslyRemovedLines = addedLines.count { it.newLineNumber < line.newLineNumber }
textLines.add(line.newLineNumber + linesAdded - previouslyRemovedLines, line.text)
linesAdded++
}
val stagedFileText = textLines.joinToString("")
FileWriter(file).use { fw ->
fw.write(stagedFileText)
}
} catch (ex: Exception) {
throw Exception("Discard hunk failed. Check if the file still exists and has the write permissions set", ex)
}
}
}

View File

@ -105,9 +105,13 @@ fun Diff(
onUnstageHunk = { entry, hunk ->
diffViewModel.unstageHunk(entry, hunk)
},
) { entry, hunk ->
diffViewModel.stageHunk(entry, hunk)
}
onStageHunk = { entry, hunk ->
diffViewModel.stageHunk(entry, hunk)
},
onResetHunk = { entry, hunk ->
diffViewModel.resetHunk(entry, hunk)
}
)
} else if (diffResult is DiffResult.NonText) {
NonTextDiff(diffResult)
}
@ -220,6 +224,7 @@ fun TextDiff(
diffResult: DiffResult.Text,
onUnstageHunk: (DiffEntry, Hunk) -> Unit,
onStageHunk: (DiffEntry, Hunk) -> Unit,
onResetHunk: (DiffEntry, Hunk) -> Unit,
) {
val hunks = diffResult.hunks
@ -237,6 +242,7 @@ fun TextDiff(
diffEntryType = diffEntryType,
onUnstageHunk = { onUnstageHunk(diffResult.diffEntry, hunk) },
onStageHunk = { onStageHunk(diffResult.diffEntry, hunk) },
onResetHunk = { onResetHunk(diffResult.diffEntry, hunk) },
)
}
}
@ -261,6 +267,7 @@ fun HunkHeader(
diffEntryType: DiffEntryType,
onUnstageHunk: () -> Unit,
onStageHunk: () -> Unit,
onResetHunk: () -> Unit,
) {
Row(
modifier = Modifier
@ -293,6 +300,14 @@ fun HunkHeader(
color = MaterialTheme.colors.stageButton
}
if(diffEntryType is DiffEntryType.UnstagedDiff) {
SecondaryButton(
text = "Discard hunk",
backgroundButton = MaterialTheme.colors.error,
onClick = onResetHunk
)
}
SecondaryButton(
text = buttonText,
backgroundButton = color,

View File

@ -173,7 +173,8 @@ fun HistoryContentLoaded(
scrollState = scrollState,
diffResult = diffResult,
onUnstageHunk = { _, _ -> },
onStageHunk = { _, _ -> }
onStageHunk = { _, _ -> },
onResetHunk = { _, _ -> },
)
} else {
Box(

View File

@ -73,6 +73,13 @@ class DiffViewModel @Inject constructor(
statusManager.stageHunk(git, diffEntry, hunk)
}
fun resetHunk(diffEntry: DiffEntry, hunk: Hunk) = tabState.runOperation(
refreshType = RefreshType.UNCOMMITED_CHANGES,
showError = true,
) { git ->
statusManager.resetHunk(git, diffEntry, hunk)
}
fun unstageHunk(diffEntry: DiffEntry, hunk: Hunk) = tabState.runOperation(
refreshType = RefreshType.UNCOMMITED_CHANGES,
) { git ->