TestFileUtils.java
/*
* Copyright (C) 2018, R��gis D��camps
* SPDX-License-Identifier: BSD-3-Clause
*/
package jflex.testing;
import com.google.common.base.Preconditions;
import java.io.File;
import java.io.FileNotFoundException;
/**
* Helps to manipulate files independently of the current working directory.
*
* <p>See <a href="https://github.com/jflex-de/jflex/issues/449">#449</a>
*/
public class TestFileUtils {
/** Whether the process is in a Bazel <em>runfiles</em> sandbox. */
public static final boolean BAZEL_RUNFILES =
"__main__".equals(new File(".").getAbsoluteFile().getParentFile().getName());
/** Prefix used in Bazel packages to indicate an absolute paths. */
private static final String BAZEL_ROOT_PREFIX = "//";
private static final char BAZEL_SEP = '/';
/**
* Resolves a file or directory.
*
* @param bazelPackage Path of the working directory relative to the root of the git repository.
* @param path Path of the file to open, relative to the working directory, e.g. {@code
* src/main/resources/foo.txt}. Can also be an absolute path in the file system, e.g. {@code
* /tmp/foo/bar.log}.
*/
public static String resolvePath(String bazelPackage, String path) {
Preconditions.checkNotNull(path, "Path must not be null");
if (path.charAt(0) == File.separatorChar || path.charAt(0) == BAZEL_SEP) {
// Absolute path. Why not.
return path;
}
Preconditions.checkNotNull(bazelPackage, "You must provide the bazel package of the test");
Preconditions.checkArgument(
bazelPackage.startsWith(BAZEL_ROOT_PREFIX),
"The bazel package should be absolute, i.e. starts with `%s`, but `$` doesn't",
BAZEL_ROOT_PREFIX,
bazelPackage);
Preconditions.checkArgument(
bazelPackage.indexOf(':') <= 0,
"The bazel package is a valid name, but `%s` contain `:`",
bazelPackage);
String safeBazelPackage = bazelPackage.endsWith("/") ? bazelPackage : bazelPackage + "/";
return resolveInternal(safeBazelPackage, path);
}
/**
* Resolves the given path.
*
* @param safeBazelPackage Bazel package excluding the leading {@link #BAZEL_ROOT_PREFIX} and with
* a trailing "{@code /}".
* @param safePath Path not starting by "/".
* @return A PAth with "
*/
private static String resolveInternal(String safeBazelPackage, String safePath) {
if (BAZEL_RUNFILES) {
String osPath =
safeBazelPackage
.substring(BAZEL_ROOT_PREFIX.length())
.replace(BAZEL_SEP, File.separatorChar);
return osPath + File.separator + safePath;
} else {
return safePath;
}
}
public static File open(String bazelPackage, String path) throws FileNotFoundException {
File file = new File(resolvePath(bazelPackage, path));
if (!file.exists()) {
throw new FileNotFoundException(
String.format("Couldn't open %s in %s: %s", path, bazelPackage, file.getAbsolutePath()));
}
return file;
}
private TestFileUtils() {}
}