larc r24

127 lines ยท 3.6 KB Raw
1 package org.iwakura.larcjb
2
3 import com.intellij.execution.configurations.GeneralCommandLine
4 import com.intellij.execution.process.CapturingProcessHandler
5 import com.intellij.execution.process.ProcessOutput
6 import com.intellij.openapi.diagnostic.Logger
7 import com.intellij.openapi.project.Project
8 import com.intellij.openapi.vfs.VirtualFile
9 import java.io.File
10 import java.nio.charset.StandardCharsets
11
12 /**
13 * Wrapper for larc CLI commands.
14 * Similar to how Git4Idea calls git binary.
15 */
16 class LarcExecutable(private val project: Project) {
17
18 private val log = Logger.getInstance(LarcExecutable::class.java)
19
20 fun getExecutablePath(): String {
21 /* TODO(kroot): make configurable via settings */
22 return LarcVcsSettings.getInstance(project).executablePath.ifEmpty { "larc" }
23 }
24
25 /**
26 * Execute larc command and return output
27 */
28 fun execute(
29 workingDir: VirtualFile,
30 vararg args: String
31 ): LarcCommandResult {
32 return execute(File(workingDir.path), *args)
33 }
34
35 fun execute(
36 workingDir: File,
37 vararg args: String
38 ): LarcCommandResult {
39 val commandLine = GeneralCommandLine()
40 .withExePath(getExecutablePath())
41 .withWorkDirectory(workingDir)
42 .withCharset(StandardCharsets.UTF_8)
43 .withParameters(*args)
44
45 log.debug("Executing: ${commandLine.commandLineString}")
46
47 return try {
48 val handler = CapturingProcessHandler(commandLine)
49 val output = handler.runProcess(TIMEOUT_MS)
50
51 LarcCommandResult(
52 exitCode = output.exitCode,
53 stdout = output.stdout.trim(),
54 stderr = output.stderr.trim(),
55 isTimeout = output.isTimeout
56 )
57 } catch (e: Exception) {
58 log.error("Failed to execute larc command", e)
59 LarcCommandResult(
60 exitCode = -1,
61 stdout = "",
62 stderr = e.message ?: "Unknown error",
63 isTimeout = false
64 )
65 }
66 }
67
68 /*
69 * Convenience methods for common commands
70 */
71
72 fun status(workingDir: VirtualFile): LarcCommandResult {
73 return execute(workingDir, "status")
74 }
75
76 fun add(workingDir: VirtualFile, vararg files: String): LarcCommandResult {
77 return execute(workingDir, "add", *files)
78 }
79
80 fun commit(
81 workingDir: VirtualFile,
82 message: String,
83 author: String
84 ): LarcCommandResult {
85 return execute(workingDir, "commit", "-m", message, "-a", author)
86 }
87
88 fun log(workingDir: VirtualFile, limit: Int = 10): LarcCommandResult {
89 return execute(workingDir, "log", "-n", limit.toString())
90 }
91
92 fun branch(workingDir: VirtualFile): LarcCommandResult {
93 return execute(workingDir, "branch")
94 }
95
96 fun currentBranch(workingDir: VirtualFile): String? {
97 val result = branch(workingDir)
98 if (result.isSuccess) {
99 /* parse branch output to find current branch (marked with *) */
100 return result.stdout.lines()
101 .firstOrNull { it.trimStart().startsWith("*") }
102 ?.substringAfter("*")
103 ?.trim()
104 }
105 return null
106 }
107
108 fun version(): LarcCommandResult {
109 return execute(File("."), "version")
110 }
111
112 companion object {
113 private const val TIMEOUT_MS = 30_000
114 }
115 }
116
117 data class LarcCommandResult(
118 val exitCode: Int,
119 val stdout: String,
120 val stderr: String,
121 val isTimeout: Boolean
122 ) {
123 val isSuccess: Boolean get() = exitCode == 0 && !isTimeout
124
125 fun getOutputOrError(): String = if (isSuccess) stdout else stderr
126 }
127