blob: 311327ec311377db17a4ebed45994dc6327e22c7 [file] [log] [blame]
/*
* Copyright 2018 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.bazel.kotlin.builder.utils
import java.io.File
import java.io.FileInputStream
import java.nio.charset.Charset
import java.nio.file.Paths
import java.util.*
/** Utility class for getting runfiles on windows and *nix. */
object BazelRunFiles {
private val isWindows = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0
/**
* Populated on windows. The RUNFILES_MANIFEST_FILE is set on platforms other then windows but it can be empty,]
*/
private val manifestFile: String? =
if (isWindows) {
checkNotNull(System.getenv("RUNFILES_MANIFEST_FILE")) { "RUNFILES_MANIFEST_FILE not set in environment" }
} else null
private val javaRunFiles = Paths.get(System.getenv("JAVA_RUNFILES"))
private val runfiles by lazy {
with(mutableMapOf<String, String>()) {
FileInputStream(manifestFile)
.bufferedReader(Charset.forName("UTF-8"))
.lines()
.forEach { it ->
val line = it.trim { it <= ' ' }
if (!line.isEmpty()) {
// TODO(bazel-team): This is buggy when the path contains spaces, we should fix the manifest format.
line.split(" ").also {
check(it.size == 2) { "RunFiles manifest entry $line contains more than one space" }
put(it[0], it[1])
}
}
}
Collections.unmodifiableMap(this)
}
}
/**
* Resolve a run file on windows or *nix.
*/
@JvmStatic
fun resolveVerified(vararg path: String): File {
check(path.isNotEmpty())
val fromManifest = manifestFile?.let { mf ->
path.joinToString("/").let { rfPath ->
// trim off the external/ prefix if it is present.
val trimmedPath =
if (rfPath.startsWith("external/")) {
rfPath.replaceFirst("external/", "")
} else {
rfPath
}
File(
checkNotNull(runfiles[trimmedPath]) {
"runfile manifest $mf did not contain path mapping for $rfPath"
}
)
}.also {
check(it.exists()) { "file $it resolved from runfiles did not exist" }
}
}
if(fromManifest != null) {
return fromManifest
}
/// if it could not be resolved from the manifest then first try to resolve it directly.
val resolvedDirect = File(path.joinToString(File.separator)).takeIf { it.exists() }
if(resolvedDirect != null) {
return resolvedDirect
}
// Try the java runfiles as the last resort.
return javaRunFiles.resolveVerified(path.joinToString(File.separator))
}
}