package io.provs import io.provs.docker.provideContainer import io.provs.processors.ContainerStartMode import io.provs.processors.ContainerUbuntuHostProcessor import io.provs.processors.RemoteProcessor import java.io.File /** * Returns the name of the calling function but excluding some functions of the prov framework * in order to return the "real" calling function. * Note: names of inner functions (i.e. which are defined inside other functions) are not * supported in the sense that always the name of the outer function is returned instead. */ fun getCallingMethodName(): String? { val offsetVal = 1 val exclude = arrayOf("def", "record", "invoke", "invoke0", "handle", "def\$default", "addResultToEval") // suffixes are also ignored as method names but will be added as suffix in the evaluation results val suffixes = arrayOf("optional", "requireAll", "requireLast", "inContainer") var suffix = "" val callingFrame = Thread.currentThread().stackTrace for (i in 0 until (callingFrame.size - 1)) { if (callingFrame[i].methodName == "getCallingMethodName") { var method = callingFrame[i + offsetVal].methodName var inc = 0 while ((method in exclude) or (method in suffixes)) { if (method in suffixes && suffix == "") { suffix = method } inc++ method = callingFrame[i + offsetVal + inc].methodName } return method + if (suffix.isBlank()) "" else " ($suffix)" } } return null } fun String.escapeNewline(): String = this.replace("\r\n", "\\n").replace("\n", "\\n") fun String.escapeBackslash(): String = this.replace("\\", "\\\\") fun String.escapeDoubleQuote(): String = this.replace("\"", "\\\"") fun String.escapeSingleQuote(): String = this.replace("'", "\'") fun String.escapeSingleQuoteForShell(): String = this.replace("'", "'\"'\"'") fun String.escapeProcentForPrintf(): String = this.replace("%", "%%") // see https://www.shellscript.sh/escape.html fun String.escapeAndEncloseByDoubleQuoteForShell(): String { return "\"" + this.escapeBackslash().replace("`", "\\`").escapeDoubleQuote().replace("$", "\\$") + "\"" } fun hostUserHome(): String = System.getProperty("user.home") + fileSeparator() fun newline(): String = System.getProperty("line.separator") fun fileSeparator(): String = File.separator /** * Returns default local Prov instance. */ @Suppress("unused") // used by other libraries resp. KotlinScript fun local(): Prov { return Prov.defaultInstance() } /** * Returns Prov instance for remote host with remote user with provided password. * If password is null, connection is done by ssh-key. * Platform (Linux, Windows) must be provided if different from local platform. */ @Suppress("unused") // used by other libraries resp. KotlinScript fun remote(host: String, remoteUser: String, password: Secret? = null, platform: String? = null): Prov { return Prov.newInstance(RemoteProcessor(host, remoteUser, password), platform) } /** * Returns Prov instance running in a local docker container with name containerName. * A potentially existing container with the same name is reused by default resp. if * parameter useExistingContainer is set to true. * If a new container needs to be created, on Linux systems the image _ubuntu_ is used. */ @Suppress("unused") // used by other libraries resp. KotlinScript fun docker(containerName: String = "provs_default", useExistingContainer: Boolean = true): Prov { val os = System.getProperty("os.name") if ("Linux".equals(os)) { val defaultDockerImage = "ubuntu" local().provideContainer(containerName, defaultDockerImage) return Prov.newInstance( ContainerUbuntuHostProcessor( containerName, defaultDockerImage, if (useExistingContainer) ContainerStartMode.USE_RUNNING_ELSE_CREATE else ContainerStartMode.CREATE_NEW_KILL_EXISTING ) ) } else { throw RuntimeException("ERROR: method docker() is currently not supported for " + os) } }