6CR2EFUN7JXFHCBTNX3WWOOP4WFOCFO6KSPEBN6V6J5HFZO2LHNQC
val dirtDirs = dirtyScope.recursivelyDirtyDirectories
val project = dirtyScope.project
val vcsManager = ProjectLevelVcsManager.getInstance(project)
val revisionMap = mutableMapOf<Path, PijulRevisionNumber?>()
val changesMap = mutableMapOf<Path, PijulLogEntry?>()
for (dir in dirtyScope.recursivelyDirtyDirectories + dirtyScope.dirtyFilesNoExpand) {
val root = vcsManager.getVcsRootFor(dir)
val rootPath = Paths.get(root!!.path)
val head = revisionMap.computeIfAbsent(rootPath) {
pijul(this.project).latestRevisionNumber(this.project, root).result
} ?: continue
val change = changesMap.computeIfAbsent(rootPath) {
pijul(this.project).diff(this.project, root).result
} ?: continue
for (hunk in change.hunks) {
when (hunk) {
is FileAddHunk -> {
val path = Paths.get(dir.path, hunk.path)
val filePath = LocalFilePath(path, Files.isDirectory(path))
println(dirtDirs)
builder.processChange(
Change(
PijulContentRevision(
rootPath,
filePath,
head,
this.project
), CurrentContentRevision.create(filePath),
FileStatus.ADDED
), this.key)
}
is FileDelHunk -> {
val path = Paths.get(dir.path, hunk.path)
val filePath = LocalFilePath(path, Files.isDirectory(path))
builder.processChange(
Change(
PijulContentRevision(
rootPath,
filePath,
head,
this.project
), CurrentContentRevision.create(filePath),
FileStatus.DELETED
), this.key)
}
is ReplacementHunk -> {
val path = Paths.get(dir.path, hunk.path)
val filePath = LocalFilePath(path, Files.isDirectory(path))
builder.processChange(
Change(
PijulContentRevision(
rootPath,
filePath,
head,
this.project
), CurrentContentRevision.create(filePath),
FileStatus.MODIFIED
), this.key)
}
is EditHunk -> {
val path = Paths.get(dir.path, hunk.path)
val filePath = LocalFilePath(path, Files.isDirectory(path))
builder.processChange(
Change(
PijulContentRevision(
rootPath,
filePath,
head,
this.project
), CurrentContentRevision.create(filePath),
FileStatus.MODIFIED
), this.key)
}
else -> Unit
}
}
}
GSON.fromJson<Map<String, List<ChangeData>>>(json, typeOf<Map<String, List<ChangeData>>>().javaType).entries.map {
if (json.isEmpty()) emptyList()
else GSON.fromJson<Map<String, List<ChangeData>>>(json, typeOf<Map<String, List<ChangeData>>>().javaType).entries.map {
package com.github.jonathanxd.dracon.content
import com.github.jonathanxd.dracon.pijul.pijul
import com.github.jonathanxd.dracon.revision.PijulRevisionNumber
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vcs.FilePath
import com.intellij.openapi.vcs.changes.ContentRevision
import com.intellij.openapi.vcs.history.VcsRevisionNumber
import com.intellij.vcsUtil.VcsUtil
import java.io.File
import java.io.IOException
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.relativeTo
import java.util.Comparator
class PijulContentRevision(
val root: Path,
val filePath: FilePath,
val revision: PijulRevisionNumber,
val project: Project
): ContentRevision {
override fun getContent(): String {
return loadStateInRevision()
}
override fun getFile(): FilePath =
this.filePath
override fun getRevisionNumber(): VcsRevisionNumber =
this.revision
@OptIn(ExperimentalPathApi::class)
private fun loadStateInRevision(): String {
val tmpTarget = Paths.get(this.project.baseDir.path, ".idea", "dracon_diffs", this.revision.hash)
if (Files.exists(tmpTarget)) {
Files.walk(tmpTarget).use { walk ->
walk.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete)
}
}
Files.createDirectories(tmpTarget)
copyFolder(this.root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
val rollbackOp = pijul(project).reset(this.project, tmpTarget)
val relative = Paths.get(filePath.path).relativeTo(this.root).toString()
return Files.readString(tmpTarget.resolve(relative))
}
@Throws(IOException::class)
fun copyFolder(source: Path, target: Path, vararg options: CopyOption) {
Files.walkFileTree(source, object : SimpleFileVisitor<Path>() {
@Throws(IOException::class)
override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
if (dir.fileName.toString().equals(".idea", ignoreCase = true))
return FileVisitResult.SKIP_SUBTREE
Files.createDirectories(target.resolve(source.relativize(dir)))
return FileVisitResult.CONTINUE
}
@Throws(IOException::class)
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
Files.copy(file, target.resolve(source.relativize(file)), *options)
return FileVisitResult.CONTINUE
}
})
}
}
return this.doExecutionWithMapper("file_status", execution) {
val changes = PijulDiffJson.parseJson(it)
val changeMap = changes.toFileStatusMap()
val fileStatusBasedInPijulDiff = this.doExecutionWithMapper("file_status", execution) {
try {
val changes = PijulDiffJson.parseJson(it)
val changeMap = changes.toFileStatusMap()
val fPath = Paths.get(VcsUtil.getFilePath(file.path).path).relativeTo(rootPath).toString()
if (fPath.isEmpty()) {
FileStatus.SUPPRESSED
} else {
changeMap[fPath]?.firstOrNull()
}
} catch(t: Throwable) {
logger<PijulCmd>().error(t)
null
}
}
val fileStatusBasedInPijulLs = this.doExecutionWithMapper("file_status_from_ls", this.execPijul(project, rootPath, listOf("ls"), delay = 10L)) {
val trackedFiles = it.split("\n")
changeMap[fPath]?.firstOrNull()
null
}
}
return if (fileStatusBasedInPijulDiff.statusCode !is SuccessStatusCode
|| fileStatusBasedInPijulDiff.result == null
|| fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED) {
fileStatusBasedInPijulLs
} else {
fileStatusBasedInPijulDiff
}
}
override fun rollbackTo(hash: String, project: Project, root: Path): PijulOperationResult<Boolean> {
val logHashExecution = this.execPijul(project, root, listOf("log", "--hash-only"), delay = 10L)
val hashes = this.doExecutionWithMapper("log--hash-only", logHashExecution) {
it.lines()
}
if (hashes.statusCode !is SuccessStatusCode) {
return hashes as PijulOperationResult<Boolean>
} else {
val hashList = hashes.result!!
if (hashList.none { it == hash } || hashList.isEmpty()) {
return PijulOperationResult("rollbackTo_${hash}", NonZeroExitStatusCode(-1, "Could not find hash $hash in Pijul log."), false)
} else {
if (hashList[0] == hash) {
return PijulOperationResult("rollbackTo_${hash}", SuccessStatusCode, true)
} else {
val rollbacks = hashList.subList(0, hashList.indexOf(hash))
for (rollbackHash in rollbacks) {
val rollback = this.doExecution(
"rollback_$rollbackHash",
this.execPijul(project, root, listOf("unrecord", rollbackHash), delay = 10L)
)
if (rollback.statusCode !is SuccessStatusCode) {
return rollback as PijulOperationResult<Boolean>
}
}
return PijulOperationResult("rollbackTo_${hash}", SuccessStatusCode, true)
}
}
}
override fun diff(project: Project, root: VirtualFile): PijulOperationResult<PijulLogEntry> {
val rootPath = Paths.get(VcsUtil.getFilePath(root).path)
val change = this.doExecutionWithMapper("diff", this.execPijul(project, rootPath, listOf("diff"), delay = 10L)) {
if (it.isEmpty()) null
else it.parseChange("")