111 lines
3.6 KiB
Kotlin
111 lines
3.6 KiB
Kotlin
package app.git
|
|
|
|
import app.TempFilesManager
|
|
import app.extensions.systemSeparator
|
|
import dagger.assisted.Assisted
|
|
import dagger.assisted.AssistedInject
|
|
import org.eclipse.jgit.diff.ContentSource
|
|
import org.eclipse.jgit.diff.DiffEntry
|
|
import org.eclipse.jgit.diff.RawText
|
|
import org.eclipse.jgit.errors.BinaryBlobException
|
|
import org.eclipse.jgit.lib.*
|
|
import org.eclipse.jgit.storage.pack.PackConfig
|
|
import org.eclipse.jgit.treewalk.AbstractTreeIterator
|
|
import org.eclipse.jgit.treewalk.WorkingTreeIterator
|
|
import org.eclipse.jgit.util.LfsFactory
|
|
import java.io.FileOutputStream
|
|
import java.nio.file.Path
|
|
import kotlin.io.path.createTempFile
|
|
|
|
|
|
private const val DEFAULT_BINARY_FILE_THRESHOLD = PackConfig.DEFAULT_BIG_FILE_THRESHOLD
|
|
|
|
class RawFileManager @AssistedInject constructor(
|
|
@Assisted private val repository: Repository,
|
|
private val tempFilesManager: TempFilesManager,
|
|
) : AutoCloseable {
|
|
private var reader: ObjectReader = repository.newObjectReader()
|
|
private var source: ContentSource.Pair
|
|
|
|
private val imageFormatsSupported = listOf(
|
|
"png",
|
|
"jpg",
|
|
"jpeg",
|
|
"webp",
|
|
)
|
|
|
|
init {
|
|
val cs = ContentSource.create(reader)
|
|
source = ContentSource.Pair(cs, cs)
|
|
}
|
|
|
|
fun scan(oldTreeIterator: AbstractTreeIterator, newTreeIterator: AbstractTreeIterator) {
|
|
source = ContentSource.Pair(source(oldTreeIterator), source(newTreeIterator))
|
|
}
|
|
|
|
private fun source(iterator: AbstractTreeIterator): ContentSource {
|
|
return if (iterator is WorkingTreeIterator)
|
|
ContentSource.create(iterator)
|
|
else
|
|
ContentSource.create(reader)
|
|
}
|
|
|
|
fun getRawContent(side: DiffEntry.Side, entry: DiffEntry): EntryContent {
|
|
if (entry.getMode(side) === FileMode.MISSING) return EntryContent.Missing
|
|
if (entry.getMode(side).objectType != Constants.OBJ_BLOB) return EntryContent.InvalidObjectBlob
|
|
|
|
val ldr = LfsFactory.getInstance().applySmudgeFilter(
|
|
repository,
|
|
source.open(side, entry), entry.diffAttribute
|
|
)
|
|
|
|
return try {
|
|
EntryContent.Text(RawText.load(ldr, DEFAULT_BINARY_FILE_THRESHOLD))
|
|
} catch (ex: BinaryBlobException) {
|
|
if (isImage(entry)) {
|
|
generateImageBinary(ldr, entry, side)
|
|
} else
|
|
EntryContent.Binary
|
|
}
|
|
}
|
|
|
|
private fun generateImageBinary(
|
|
ldr: ObjectLoader,
|
|
entry: DiffEntry,
|
|
side: DiffEntry.Side
|
|
): EntryContent.ImageBinary {
|
|
val tempDir = tempFilesManager.tempDir
|
|
|
|
val tempFile = createTempFile(tempDir, prefix = "${entry.newPath.replace(systemSeparator, "_")}_${side.name}")
|
|
tempFile.toFile().deleteOnExit()
|
|
|
|
val out = FileOutputStream(tempFile.toFile())
|
|
out.use {
|
|
ldr.copyTo(out)
|
|
}
|
|
|
|
return EntryContent.ImageBinary(tempFile)
|
|
}
|
|
|
|
// todo check if it's an image checking the binary format, checking the extension is a temporary workaround
|
|
private fun isImage(entry: DiffEntry): Boolean {
|
|
val path = entry.newPath
|
|
val fileExtension = path.split(".").lastOrNull() ?: return false
|
|
|
|
return imageFormatsSupported.contains(fileExtension.lowercase())
|
|
}
|
|
|
|
override fun close() {
|
|
reader.close()
|
|
}
|
|
}
|
|
|
|
sealed class EntryContent {
|
|
object Missing : EntryContent()
|
|
object InvalidObjectBlob : EntryContent()
|
|
data class Text(val rawText: RawText) : EntryContent()
|
|
sealed class BinaryContent : EntryContent()
|
|
data class ImageBinary(val tempFilePath: Path) : BinaryContent()
|
|
object Binary : BinaryContent()
|
|
object TooLargeEntry : EntryContent()
|
|
} |