Commit Diff


commit - ba570446954968ad7b2feb330d7b6371087d413b
commit + f6dbcd6e78bee67c9aa0d8594048ff3763574c09
blob - 3c6290cecb06079e14f45563523a392484d336b2
blob + 3a132b68a94c64d99f1a7cfa3f540b599cfc9c73
--- src/main/kotlin/dev/nezzontli/gotvcs/GotCommandLineWrapper.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/GotCommandLineWrapper.kt
@@ -63,4 +63,28 @@ class GotCommandLineWrapper {
             ?: throw VcsException("got info no reportó un commit base para $workDir")
         return line.substringAfter("work tree base commit:").trim()
     }
+
+    @Throws(VcsException::class)
+    fun commit(workDir: File, message: String, paths: List<String>) {
+        if (paths.isEmpty()) return
+        run(workDir, *(arrayOf("commit", "-m", message) + paths))
+    }
+
+    @Throws(VcsException::class)
+    fun add(workDir: File, paths: List<String>) {
+        if (paths.isEmpty()) return
+        run(workDir, *(arrayOf("add") + paths))
+    }
+
+    @Throws(VcsException::class)
+    fun remove(workDir: File, paths: List<String>) {
+        if (paths.isEmpty()) return
+        run(workDir, *(arrayOf("remove", "-f") + paths))
+    }
+
+    @Throws(VcsException::class)
+    fun revert(workDir: File, paths: List<String>) {
+        if (paths.isEmpty()) return
+        run(workDir, *(arrayOf("revert", "-R") + paths))
+    }
 }
blob - /dev/null
blob + 51c4a974493b4ffe3d9726a408194e64017e917f (mode 644)
--- /dev/null
+++ src/main/kotlin/dev/nezzontli/gotvcs/GotCheckinEnvironment.kt
@@ -0,0 +1,85 @@
+package dev.nezzontli.gotvcs
+
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vcs.FilePath
+import com.intellij.openapi.vcs.ProjectLevelVcsManager
+import com.intellij.openapi.vcs.VcsException
+import com.intellij.openapi.vcs.changes.Change
+import com.intellij.openapi.vcs.checkin.CheckinEnvironment
+import com.intellij.openapi.vfs.VfsUtilCore
+import com.intellij.openapi.vfs.VirtualFile
+import java.io.File
+
+/**
+ * got no tiene un índice/staging equivalente al de git en el flujo normal
+ * (aparte de `got stage`, que no usamos aquí): en vez de eso, se commitean
+ * exactamente los paths seleccionados por el usuario en el panel de Commit,
+ * vía `got commit -m msg <paths>`. Ver got(1), sección commit.
+ */
+class GotCheckinEnvironment(
+    private val project: Project,
+    private val commandLine: GotCommandLineWrapper,
+) : CheckinEnvironment {
+
+    override fun getHelpId(): String? = null
+
+    override fun getCheckinOperationName(): String = "Commit"
+
+    override fun isRefreshAfterCommitNeeded(): Boolean = true
+
+    override fun commit(changes: MutableList<out Change>, commitMessage: String): MutableList<VcsException> {
+        val exceptions = mutableListOf<VcsException>()
+        val filePaths = changes.mapNotNull { it.afterRevision?.file ?: it.beforeRevision?.file }
+        for ((workDir, paths) in groupByRoot(filePaths)) {
+            try {
+                commandLine.commit(workDir, commitMessage, paths)
+            } catch (e: VcsException) {
+                exceptions.add(e)
+            }
+        }
+        return exceptions
+    }
+
+    override fun scheduleMissingFileForDeletion(files: MutableList<out FilePath>): MutableList<VcsException> {
+        val exceptions = mutableListOf<VcsException>()
+        for ((workDir, paths) in groupByRoot(files)) {
+            try {
+                commandLine.remove(workDir, paths)
+            } catch (e: VcsException) {
+                exceptions.add(e)
+            }
+        }
+        return exceptions
+    }
+
+    override fun scheduleUnversionedFilesForAddition(files: MutableList<out VirtualFile>): MutableList<VcsException> {
+        val exceptions = mutableListOf<VcsException>()
+        val vcsManager = ProjectLevelVcsManager.getInstance(project)
+        val byRoot = mutableMapOf<File, MutableList<String>>()
+        for (file in files) {
+            val vcsRoot = vcsManager.getVcsRootFor(file) ?: continue
+            val relativePath = VfsUtilCore.getRelativePath(file, vcsRoot) ?: continue
+            byRoot.getOrPut(File(vcsRoot.path)) { mutableListOf() }.add(relativePath)
+        }
+        for ((workDir, paths) in byRoot) {
+            try {
+                commandLine.add(workDir, paths)
+            } catch (e: VcsException) {
+                exceptions.add(e)
+            }
+        }
+        return exceptions
+    }
+
+    private fun groupByRoot(filePaths: List<FilePath>): Map<File, List<String>> {
+        val vcsManager = ProjectLevelVcsManager.getInstance(project)
+        val byRoot = mutableMapOf<File, MutableList<String>>()
+        for (filePath in filePaths) {
+            val vcsRoot = vcsManager.getVcsRootFor(filePath) ?: continue
+            val workDir = File(vcsRoot.path)
+            val relativePath = workDir.toPath().relativize(File(filePath.path).toPath()).toString()
+            byRoot.getOrPut(workDir) { mutableListOf() }.add(relativePath)
+        }
+        return byRoot
+    }
+}
blob - c7ec1298940b9e9368ea674e3d1b32b8ecdd8718
blob + 361c64c88ee0ab4cdf957b1ed9fc7d775b12f158
--- src/main/kotlin/dev/nezzontli/gotvcs/GotVcs.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/GotVcs.kt
@@ -4,13 +4,17 @@ import com.intellij.openapi.project.Project
 import com.intellij.openapi.vcs.AbstractVcs
 import com.intellij.openapi.vcs.VcsKey
 import com.intellij.openapi.vcs.changes.ChangeProvider
+import com.intellij.openapi.vcs.checkin.CheckinEnvironment
 import com.intellij.openapi.vcs.diff.DiffProvider
+import com.intellij.openapi.vcs.rollback.RollbackEnvironment
 
 class GotVcs(project: Project) : AbstractVcs(project, NAME) {
 
     private val commandLine = GotCommandLineWrapper()
     private val changeProvider = GotChangeProvider(commandLine)
     private val diffProvider = GotDiffProvider(project, commandLine)
+    private val checkinEnvironment = GotCheckinEnvironment(project, commandLine)
+    private val rollbackEnvironment = GotRollbackEnvironment(project, commandLine)
 
     override fun getDisplayName(): String = NAME
 
@@ -18,6 +22,10 @@ class GotVcs(project: Project) : AbstractVcs(project, 
 
     override fun getDiffProvider(): DiffProvider = diffProvider
 
+    override fun getCheckinEnvironment(): CheckinEnvironment = checkinEnvironment
+
+    override fun getRollbackEnvironment(): RollbackEnvironment = rollbackEnvironment
+
     companion object {
         const val NAME = "got"
 
blob - /dev/null
blob + 872fb3d6af72f071f2821499de70d42b52630165 (mode 644)
--- /dev/null
+++ src/main/kotlin/dev/nezzontli/gotvcs/GotRollbackEnvironment.kt
@@ -0,0 +1,67 @@
+package dev.nezzontli.gotvcs
+
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vcs.FilePath
+import com.intellij.openapi.vcs.ProjectLevelVcsManager
+import com.intellij.openapi.vcs.VcsException
+import com.intellij.openapi.vcs.changes.Change
+import com.intellij.openapi.vcs.rollback.RollbackEnvironment
+import com.intellij.openapi.vcs.rollback.RollbackProgressListener
+import com.intellij.openapi.vfs.VirtualFile
+import java.io.File
+
+class GotRollbackEnvironment(
+    private val project: Project,
+    private val commandLine: GotCommandLineWrapper,
+) : RollbackEnvironment {
+
+    override fun getRollbackOperationName(): String = "Revert"
+
+    override fun rollbackChanges(
+        changes: MutableList<out Change>,
+        exceptions: MutableList<VcsException>,
+        listener: RollbackProgressListener,
+    ) {
+        listener.determinate()
+        val filePaths = changes.mapNotNull { it.afterRevision?.file ?: it.beforeRevision?.file }
+        revertPaths(filePaths, exceptions, listener)
+    }
+
+    override fun rollbackMissingFileDeletion(
+        files: MutableList<out FilePath>,
+        exceptions: MutableList<in VcsException>,
+        listener: RollbackProgressListener,
+    ) {
+        listener.determinate()
+        revertPaths(files, exceptions, listener)
+    }
+
+    override fun rollbackModifiedWithoutCheckout(
+        files: MutableList<out VirtualFile>,
+        exceptions: MutableList<in VcsException>,
+        listener: RollbackProgressListener,
+    ) = Unit
+
+    private fun revertPaths(
+        filePaths: List<FilePath>,
+        exceptions: MutableList<in VcsException>,
+        listener: RollbackProgressListener,
+    ) {
+        val vcsManager = ProjectLevelVcsManager.getInstance(project)
+        val byRoot = mutableMapOf<File, MutableList<String>>()
+        for (filePath in filePaths) {
+            val vcsRoot = vcsManager.getVcsRootFor(filePath) ?: continue
+            val workDir = File(vcsRoot.path)
+            val relativePath = workDir.toPath().relativize(File(filePath.path).toPath()).toString()
+            byRoot.getOrPut(workDir) { mutableListOf() }.add(relativePath)
+        }
+        for ((workDir, paths) in byRoot) {
+            try {
+                commandLine.revert(workDir, paths)
+                paths.forEach { listener.accept(File(workDir, it)) }
+            } catch (e: VcsException) {
+                exceptions.add(e)
+            }
+        }
+    }
+}