B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC 5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC MTPTFTHGAOKQGRUDXC55AM6XJHZZZ5EF6FPVXKFVCUYVXJNEANYQC GGYFPXND4VBCROZZXTKAP7Y4JOP2OOYQAFVLMUE7SLFM225EUSIAC EAGIDXOLFTHZMZ77ZWAM7MVVUBBXJMZD7RZUNBHJPYRFGGKILGVAC 6CR2EFUN7JXFHCBTNX3WWOOP4WFOCFO6KSPEBN6V6J5HFZO2LHNQC FNNW5IEAXQ43WKB6QSQB7DFLG3Y3T5FYPXIUX7KQ2URR2GU3QLTAC FRFFQV7VNYKGCA7ZAOSRPC2HHYTAIZ6AGGR7A5QEV6QPAQGFDYGAC QXUEMZ3B2FUHFUC7ZZHJMH5FVWLEMEYXUMFA6JNXTJKIVZNMRIOAC Q7FXTHVUPVAFMNY277C3NFJO3VXLZU5G6C6UYSD5QPURHSG3A7OQC 7L5LODGZ7AN4ZULDJZMLALD7PL6E57VZSNNSG67SFJARUJGCT47QC OPFG6CZ26PPTGTH7ULLRQGZGR3YEIEJOV5W2E3WN7PFRZS62CVLQC package com.github.jonathanxd.dracon.utilimport java.io.Fileimport java.nio.file.Filesimport java.nio.file.Pathimport java.nio.file.Pathsfun findBinary(app: String): String {// Works in Windows, Linux and MacOS when app is installed with cargo.val localPijul = findCargo(app)// For Homebrew/Linuxbrew installationsval brewPijul = findBrew(app)// For *nix only.val usrBinPijul = Paths.get(File.pathSeparator, "usr", "bin", app).asExecutableStringOrNull()val usrLocalBinPijul = Paths.get(File.pathSeparator, "usr", "local", "bin", app).asExecutableStringOrNull()val binPijul = Paths.get(File.pathSeparator, "bin", app).asExecutableStringOrNull()// For Windows only.// Windows could download Pijul binaries from https://github.com/boringcactus/pijul-windows-builds/releases/latest// However, Dracon plugin could not detect Pijul outside from these directories, for the cases where// Pijul is not in these locations, a search through $PATH variable will be made, so if the $PATH is correctly// configured to point to Pijul executable, then it will be found, this applies to all OSes.val programFiles = Paths.get("C:"+ File.pathSeparator, "Program Files", app, "$app.exe").asExecutableStringOrNull()val programFiles86 = Paths.get("C:"+ File.pathSeparator, "Program Files (x86)", app, "$app.exe").asExecutableStringOrNull()return localPijul?: brewPijul?: usrBinPijul?: usrLocalBinPijul?: binPijul?: programFiles?: programFiles86?: findExecutableOnPath(app)?: app}private fun Path.asExecutableStringOrNull(): String? =this.existsOrNull()?.isRegularFileOrNull()?.isExecutableOrNull()?.toAbsolutePath()?.toString()private fun findCargo(app: String): String? {return System.getProperty("user.dir")?.let {Paths.get(it, ".cargo", "bin", app)}?.asExecutableStringOrNull()}private fun findBrew(app: String): String? {return System.getenv("HOMEBREW_PREFIX")?.ifBlank { null }?.ifEmpty { null }?.let {Paths.get(it, "bin", app)}?.asExecutableStringOrNull()}fun findExecutableOnPath(name: String): String? {for (dirname in System.getenv("PATH").split(File.pathSeparator)) {val path = Paths.get(dirname, name)if (Files.isRegularFile(path) && Files.isExecutable(path)) {return path.toAbsolutePath().toString()}}return null}
// TODO: Should we limit to show only one revision when introspecting directories instead of all revisions?
val deleted = it.hunks.filterIsInstance<HunkWithPath>().filter {it.resolvePath(ctx.root) == path}.filterIsInstance<FileDelHunk>().isNotEmpty()partner.acceptRevision(PijulVcsFileRevision(this.project,root.toNioPath(),pathToView,PijulRevisionNumber(it.changeHash, it.date),it.authors.map { VcsUserImpl(it.name ?: "", it.email ?: "") }.filter { it.name.isNotEmpty() },it.message,currentChannel,deleted))/*// TODO: Should we limit to show only one revision when introspecting directories instead of all revisions?
package com.github.jonathanxd.dracon.editorimport com.github.jonathanxd.dracon.util.findBinaryimport java.net.ServerSocketimport java.net.URIimport java.net.http.HttpClientimport java.net.http.HttpRequestimport java.net.http.HttpResponseimport java.time.Durationimport java.time.Instantclass EditorServer(val port: Int, val isClosed: () -> Boolean) {private var connected: Boolean = falseprivate val client = HttpClient.newHttpClient()private lateinit var content: Stringfun connectAndRetrieveContent() {val start = Instant.now()while (!this.isClosed()) {if (Duration.between(start, Instant.now()).seconds > 10) {throw IllegalStateException("Could not connect to editor server! Timeout after 10 seconds.")}try {val response = this.client.send(HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/read")).GET().version(HttpClient.Version.HTTP_2).build(),HttpResponse.BodyHandlers.ofString())if (response.statusCode() == 200) {this.connected = truethis.content = response.body();break;}} catch (t: Throwable) {}Thread.sleep(200)}}fun content() = this.contentfun connected() = this.connectedfun write(text: String) {if (this.isClosed()) {throw IllegalStateException("Could not write: editor-server is already closed.")}if (!this.connected) {throw IllegalStateException("Could not write: Not connected to editor-server!")}val response = this.client.send(HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/write")).POST(HttpRequest.BodyPublishers.ofString(text)).version(HttpClient.Version.HTTP_2).build(),HttpResponse.BodyHandlers.ofString())handleResponse(response)}private fun handleResponse(response: HttpResponse<*>) {if (response.statusCode() != 200) {throw IllegalStateException("editor-server responded with $response.")}}fun close() {if (this.isClosed()) {throw IllegalStateException("Could not close: editor-server is already closed.")}if (!this.connected) {throw IllegalStateException("Could not close: Not connected to editor-server!")}try {// This will make the connection close immediately// thus throwing an exception.this.client.send(HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/close")).GET().version(HttpClient.Version.HTTP_2).build(),HttpResponse.BodyHandlers.ofString())} catch (t: Throwable) {}}}fun freePort(): Int = ServerSocket(0).use {it.localPort}fun editorServerPath(): String = findBinary("editor-server")
val record = pijul(this.project).recordFromString(this.project, this.vcsRoot, this.editor.text)
this.editorServer.write(this.editor.text)this.editorServer.close()/*val record = pijul(this.project).recordFromString(this.project, this.vcsRoot, this.editor.text)
import com.github.jonathanxd.dracon.util.existsOrNullimport com.github.jonathanxd.dracon.util.isExecutableOrNullimport com.github.jonathanxd.dracon.util.isRegularFileOrNullimport com.github.jonathanxd.dracon.util.linesToFlow
import com.github.jonathanxd.dracon.util.*
}}override fun record(project: Project,root: Path,editorServerConsumer: (EditorServer) -> Unit): PijulOperationResult<String> {val arguments = mutableListOf("record")val operation = this.createPainlessExecPijulWithEditorServer(this.project,root,arguments,editorServerConsumer)return this.doExecutionWithMapper("record", operation) {it
// For Homebrew/Linuxbrew installationsval brewPijul = this.findBrewPijul()
/*** Creates a [PijulExecution] operation that could be executed at any time. This operation uses Kotlin Coroutines* and can be executed immediately through [doExecution] or through [doExecutionWithMapper].** This implementation does not requires a delay value to be provided, like [createExecPijulOperation] does, instead* it uses the kotlin conversion from `CompletionStage` to `Coroutines` and awaits the process through [Process.onExit].** [doExecution] and [doExecutionWithMapper] does execution by scheduling task to [Dispatchers.IO], instead of Main Thread,* offloading the Process execution handling to a different scheduler. However, mapping operation of [doExecutionWithMapper]* is not offloaded from the caller context.**/@RequiresBackgroundThreadprivate fun createPainlessExecPijulWithEditorServer(project: Project,dir: Path,args: List<String>,editorServerConsumer: (EditorServer) -> Unit): PijulExecution {val freePort = freePort()val process = ProcessBuilder().apply {environment()["EDITOR_SERVER_PORT"] = freePort.toString()environment()["VISUAL"] = editorServerPath()environment()["EDITOR"] = editorServerPath()}.command(listOf(this.findPijul()) + args).directory(dir.toFile()).start()
// For *nix only.val usrBinPijul = Paths.get(File.pathSeparator, "usr", "bin", "pijul").asPijulExecutableStringOrNull()val usrLocalBinPijul = Paths.get(File.pathSeparator, "usr", "local", "bin", "pijul").asPijulExecutableStringOrNull()val binPijul = Paths.get(File.pathSeparator, "bin", "pijul").asPijulExecutableStringOrNull()
editorServerConsumer(EditorServer(freePort) {!process.isAlive})
// For Windows only.// Windows could download Pijul binaries from https://github.com/boringcactus/pijul-windows-builds/releases/latest// However, Dracon plugin could not detect Pijul outside from these directories, for the cases where// Pijul is not in these locations, a search through $PATH variable will be made, so if the $PATH is correctly// configured to point to Pijul executable, then it will be found, this applies to all OSes.val programFiles = Paths.get("C:"+ File.pathSeparator, "Program Files", "pijul", "pijul.exe").asPijulExecutableStringOrNull()val programFiles86 = Paths.get("C:"+ File.pathSeparator, "Program Files (x86)", "pijul", "pijul.exe").asPijulExecutableStringOrNull()
val input = process.inputStreamval error = process.errorStream
private fun Path.asPijulExecutableStringOrNull(): String? =this.existsOrNull()?.isRegularFileOrNull()?.isExecutableOrNull()?.toAbsolutePath()?.toString()
if (exit == 0) {draconConsoleWriter(project).logCommand("pijul", args, "<Exit status> $exit")} else {draconConsoleWriter(project).logCommandError("pijul", args, "<Exit status> $exit")}
fun findExecutableOnPath(name: String): String? {for (dirname in System.getenv("PATH").split(File.pathSeparator)) {val path = Paths.get(dirname, name)if (Files.isRegularFile(path) && Files.isExecutable(path)) {return path.toAbsolutePath().toString()}}
private fun findPijul(): String = findBinary("pijul")
private fun getChanges(settings: ChangeBrowserSettings,location: RepositoryLocation,maxCount: Int,consumer: (PijulCommittedChangeList) -> Unit) {
private fun getChanges(settings: ChangeBrowserSettings,maxCount: Int,revision: VcsRevisionNumber? = null,consumer: (PijulCommittedChangeList) -> Unit) {
val rev = pijul(this.project).log(this.project, ctx.root).result?.entries?.filter {it.revision.hash == number.asString()}?.map { entry ->PijulCommittedChangeList(entry.message,"",entry.authors.firstOrNull()?.name ?: "No author",Date.from(entry.date.toInstant()),entry.hunks.filterIsInstance<HunkWithPath>().map { hunk ->val beforeRevision =if (hunk is FileAddHunk) nullelse findARevisionBefore(entry.changeHash, allRevisions)?.let {PijulContentRevision(ctx.root,hunk.resolvePath(ctx.root),it,this.project)}
this.getChanges(ChangeBrowserSettings(), 1, number) {changes.add(it)}
val afterRevision =if (hunk is FileDelHunk) nullelse PijulContentRevision(ctx.root,hunk.resolvePath(ctx.root),entry.revision,this.project)Change(beforeRevision,afterRevision,hunk.status)}.toMutableList(),entry.revision,false,pijulVcs(this.project))}?.firstOrNull() ?: return null
val rev = changes.firstOrNull() ?: return null
if (recordString.result != null) {
if (record.statusCode is SuccessStatusCode) {val result = record.result!!val hash = result.substring(result.indexOf("Hash:") + "Hash:".length).trim()Notifications.Bus.notify(Notification(EXPERT_MODE_GROUP,DraconBundle.message("expert.mode.notification.title"),DraconBundle.message("expert.mode.notification.success", hash),NotificationType.ERROR,),project)} else {record.statusCode as NonZeroExitStatusCodeNotifications.Bus.notify(Notification(EXPERT_MODE_GROUP,DraconBundle.message("expert.mode.notification.title"),DraconBundle.message("expert.mode.notification.failure", record.statusCode.exitCode, record.statusCode.message),NotificationType.INFORMATION,),project)}/*if (recordString.result != null) {