aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/unix/UnixFileSystem.java125
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystemWithCustomStat.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java342
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java86
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java97
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/LocalPath.java138
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/Path.java98
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/PathTrie.java82
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java47
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystemWithCustomStat.java26
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java153
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java208
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java51
-rw-r--r--src/test/java/com/google/devtools/build/lib/actions/DigestUtilsTest.java14
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/AnalysisWithIOExceptionsTest.java8
-rw-r--r--src/test/java/com/google/devtools/build/lib/exec/SingleBuildFileCacheTest.java35
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java3
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryTestBase.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java77
-rw-r--r--src/test/java/com/google/devtools/build/lib/pkgcache/IncrementalLoadingTest.java12
-rw-r--r--src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java19
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunctionTest.java7
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java7
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java3
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java37
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java13
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java35
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ParallelBuilderTest.java88
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTest.java2
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java8
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunctionTest.java9
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java3
-rw-r--r--src/test/java/com/google/devtools/build/lib/util/DependencySetWindowsTest.java40
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/FileSystemTest.java41
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/FileSystemUtilsTest.java16
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java21
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/PathTrieTest.java78
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/SearchPathTest.java2
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/SymlinkAwareFileSystemTest.java24
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/UnionFileSystemTest.java97
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java11
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java39
-rw-r--r--src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java17
48 files changed, 1172 insertions, 1105 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
index aaac32e758..dc52388d83 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
@@ -194,7 +194,7 @@ public final class BinTools {
}
private void linkTool(Path sourcePath, Path linkPath) throws ExecException {
- if (linkPath.getFileSystem().supportsSymbolicLinksNatively(linkPath.getLocalPath())) {
+ if (linkPath.getFileSystem().supportsSymbolicLinksNatively(linkPath)) {
try {
if (!linkPath.isSymbolicLink()) {
// ensureSymbolicLink() does not handle the case where there is already
diff --git a/src/main/java/com/google/devtools/build/lib/unix/UnixFileSystem.java b/src/main/java/com/google/devtools/build/lib/unix/UnixFileSystem.java
index 4a79ee12f6..7b82dcc06a 100644
--- a/src/main/java/com/google/devtools/build/lib/unix/UnixFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/unix/UnixFileSystem.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.unix;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Striped;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
@@ -25,19 +24,18 @@ import com.google.devtools.build.lib.unix.NativePosixFiles.ReadTypes;
import com.google.devtools.build.lib.vfs.AbstractFileSystemWithCustomStat;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
-import com.google.devtools.build.lib.vfs.LocalPath;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.concurrent.locks.Lock;
/**
* This class implements the FileSystem interface using direct calls to the UNIX filesystem.
*/
@ThreadSafe
public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
- private final Striped<Lock> pathLock = Striped.lock(64);
public UnixFileSystem() {
}
@@ -102,7 +100,7 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected Collection<String> getDirectoryEntries(LocalPath path) throws IOException {
+ protected Collection<String> getDirectoryEntries(Path path) throws IOException {
String name = path.getPathString();
String[] entries;
long startTime = Profiler.nanoTimeMaybe();
@@ -119,7 +117,7 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected String resolveOneLink(LocalPath path) throws IOException {
+ protected PathFragment resolveOneLink(Path path) throws IOException {
// Beware, this seemingly simple code belies the complex specification of
// FileSystem.resolveOneLink().
return stat(path, false).isSymbolicLink()
@@ -147,7 +145,7 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected Collection<Dirent> readdir(LocalPath path, boolean followSymlinks) throws IOException {
+ protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
String name = path.getPathString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -166,12 +164,12 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus stat(Path path, boolean followSymlinks) throws IOException {
return statInternal(path, followSymlinks);
}
@VisibleForTesting
- protected UnixFileStatus statInternal(LocalPath path, boolean followSymlinks) throws IOException {
+ protected UnixFileStatus statInternal(Path path, boolean followSymlinks) throws IOException {
String name = path.getPathString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -187,7 +185,7 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
// This is a performance optimization in the case where clients
// catch and don't re-throw.
@Override
- protected FileStatus statNullable(LocalPath path, boolean followSymlinks) {
+ protected FileStatus statNullable(Path path, boolean followSymlinks) {
String name = path.getPathString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -201,16 +199,16 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean exists(LocalPath path, boolean followSymlinks) {
+ protected boolean exists(Path path, boolean followSymlinks) {
return statNullable(path, followSymlinks) != null;
}
/**
- * Return true iff the {@code stat} of {@code path} resulted in an {@code ENOENT} or {@code
- * ENOTDIR} error.
+ * Return true iff the {@code stat} of {@code path} resulted in an {@code ENOENT}
+ * or {@code ENOTDIR} error.
*/
@Override
- protected FileStatus statIfFound(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
String name = path.getPathString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -236,29 +234,29 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean isReadable(LocalPath path) throws IOException {
+ protected boolean isReadable(Path path) throws IOException {
return (statInternal(path, true).getPermissions() & 0400) != 0;
}
@Override
- protected boolean isWritable(LocalPath path) throws IOException {
+ protected boolean isWritable(Path path) throws IOException {
return (statInternal(path, true).getPermissions() & 0200) != 0;
}
@Override
- protected boolean isExecutable(LocalPath path) throws IOException {
+ protected boolean isExecutable(Path path) throws IOException {
return (statInternal(path, true).getPermissions() & 0100) != 0;
}
/**
- * Adds or remove the bits specified in "permissionBits" to the permission mask of the file
- * specified by {@code path}. If the argument {@code add} is true, the specified permissions are
- * added, otherwise they are removed.
+ * Adds or remove the bits specified in "permissionBits" to the permission
+ * mask of the file specified by {@code path}. If the argument {@code add} is
+ * true, the specified permissions are added, otherwise they are removed.
*
* @throws IOException if there was an error writing the file's metadata
*/
- private void modifyPermissionBits(LocalPath path, int permissionBits, boolean add)
- throws IOException {
+ private void modifyPermissionBits(Path path, int permissionBits, boolean add)
+ throws IOException {
synchronized (path) {
int oldMode = statInternal(path, true).getPermissions();
int newMode = add ? (oldMode | permissionBits) : (oldMode & ~permissionBits);
@@ -267,39 +265,39 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
modifyPermissionBits(path, 0400, readable);
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
modifyPermissionBits(path, 0200, writable);
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) throws IOException {
+ protected void setExecutable(Path path, boolean executable) throws IOException {
modifyPermissionBits(path, 0111, executable);
}
@Override
- protected void chmod(LocalPath path, int mode) throws IOException {
+ protected void chmod(Path path, int mode) throws IOException {
synchronized (path) {
NativePosixFiles.chmod(path.toString(), mode);
}
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return true;
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return true;
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
return true;
}
@@ -309,10 +307,8 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
- Lock lock = getPathLock(path);
- lock.lock();
- try {
+ public boolean createDirectory(Path path) throws IOException {
+ synchronized (path) {
// Note: UNIX mkdir(2), FilesystemUtils.mkdir() and createDirectory all
// have different ways of representing failure!
if (NativePosixFiles.mkdir(path.toString(), 0777)) {
@@ -325,30 +321,25 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
} else {
throw new IOException(path + " (File exists)");
}
- } finally {
- lock.unlock();
}
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
- Lock lock = getPathLock(linkPath);
- lock.lock();
- try {
- NativePosixFiles.symlink(targetFragment, linkPath.toString());
- } finally {
- lock.unlock();
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment)
+ throws IOException {
+ synchronized (linkPath) {
+ NativePosixFiles.symlink(targetFragment.toString(), linkPath.toString());
}
}
@Override
- protected String readSymbolicLink(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLink(Path path) throws IOException {
// Note that the default implementation of readSymbolicLinkUnchecked calls this method and thus
// is optimal since we only make one system call in here.
String name = path.toString();
long startTime = Profiler.nanoTimeMaybe();
try {
- return NativePosixFiles.readlink(name);
+ return PathFragment.create(NativePosixFiles.readlink(name));
} catch (IOException e) {
// EINVAL => not a symbolic link. Anything else is a real error.
throw e.getMessage().endsWith("(Invalid argument)") ? new NotASymlinkException(path) : e;
@@ -358,45 +349,38 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
- Lock lock = getPathLock(sourcePath);
- lock.lock();
- try {
+ public void renameTo(Path sourcePath, Path targetPath) throws IOException {
+ synchronized (sourcePath) {
NativePosixFiles.rename(sourcePath.toString(), targetPath.toString());
- } finally {
- lock.unlock();
}
}
@Override
- protected long getFileSize(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getFileSize(Path path, boolean followSymlinks) throws IOException {
return stat(path, followSymlinks).getSize();
}
@Override
- public boolean delete(LocalPath path) throws IOException {
+ public boolean delete(Path path) throws IOException {
String name = path.toString();
long startTime = Profiler.nanoTimeMaybe();
- Lock lock = getPathLock(path);
- lock.lock();
- try {
- return NativePosixFiles.remove(name);
- } finally {
- lock.unlock();
- profiler.logSimpleTask(startTime, ProfilerTask.VFS_DELETE, name);
+ synchronized (path) {
+ try {
+ return NativePosixFiles.remove(name);
+ } finally {
+ profiler.logSimpleTask(startTime, ProfilerTask.VFS_DELETE, name);
+ }
}
}
@Override
- protected long getLastModifiedTime(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getLastModifiedTime(Path path, boolean followSymlinks) throws IOException {
return stat(path, followSymlinks).getLastModifiedTime();
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
- Lock lock = getPathLock(path);
- lock.lock();
- try {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
+ synchronized (path) {
if (newTime == -1L) { // "now"
NativePosixFiles.utime(path.toString(), true, 0);
} else {
@@ -404,13 +388,11 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
int unixTime = (int) (newTime / 1000);
NativePosixFiles.utime(path.toString(), false, unixTime);
}
- } finally {
- lock.unlock();
}
}
@Override
- public byte[] getxattr(LocalPath path, String name) throws IOException {
+ public byte[] getxattr(Path path, String name) throws IOException {
String pathName = path.toString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -425,7 +407,7 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hashFunction) throws IOException {
String name = path.toString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -439,13 +421,8 @@ public class UnixFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException {
NativePosixFiles.link(originalPath.toString(), linkPath.toString());
}
-
- /** Returns a per-path lock. The lock is re-entrant. */
- protected Lock getPathLock(LocalPath path) {
- return pathLock.get(path);
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java
index 8b9cd5376a..ef1946bb8e 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java
@@ -37,7 +37,7 @@ abstract class AbstractFileSystem extends FileSystem {
}
@Override
- protected InputStream getInputStream(LocalPath path) throws IOException {
+ protected InputStream getInputStream(Path path) throws IOException {
// This loop is a workaround for an apparent bug in FileInputStream.open, which delegates
// ultimately to JVM_Open in the Hotspot JVM. This call is not EINTR-safe, so we must do the
// retry here.
@@ -55,7 +55,7 @@ abstract class AbstractFileSystem extends FileSystem {
}
/** Returns either normal or profiled FileInputStream. */
- private InputStream createFileInputStream(LocalPath path) throws FileNotFoundException {
+ private InputStream createFileInputStream(Path path) throws FileNotFoundException {
final String name = path.toString();
if (profiler.isActive()
&& (profiler.isProfiling(ProfilerTask.VFS_READ)
@@ -77,7 +77,7 @@ abstract class AbstractFileSystem extends FileSystem {
* Returns either normal or profiled FileOutputStream. Should be used by subclasses to create
* default OutputStream instance.
*/
- protected OutputStream createFileOutputStream(LocalPath path, boolean append)
+ protected OutputStream createFileOutputStream(Path path, boolean append)
throws FileNotFoundException {
final String name = path.toString();
if (profiler.isActive()
@@ -95,7 +95,7 @@ abstract class AbstractFileSystem extends FileSystem {
}
@Override
- protected OutputStream getOutputStream(LocalPath path, boolean append) throws IOException {
+ protected OutputStream getOutputStream(Path path, boolean append) throws IOException {
synchronized (path) {
try {
return createFileOutputStream(path, append);
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystemWithCustomStat.java b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystemWithCustomStat.java
index b73aa0c4df..875df98bab 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystemWithCustomStat.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystemWithCustomStat.java
@@ -29,30 +29,30 @@ public abstract class AbstractFileSystemWithCustomStat extends AbstractFileSyste
}
@Override
- protected boolean isFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isFile(Path path, boolean followSymlinks) {
FileStatus stat = statNullable(path, followSymlinks);
return stat != null ? stat.isFile() : false;
}
@Override
- protected boolean isSpecialFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isSpecialFile(Path path, boolean followSymlinks) {
FileStatus stat = statNullable(path, followSymlinks);
return stat != null ? stat.isSpecialFile() : false;
}
@Override
- protected boolean isSymbolicLink(LocalPath path) {
+ protected boolean isSymbolicLink(Path path) {
FileStatus stat = statNullable(path, false);
return stat != null ? stat.isSymbolicLink() : false;
}
@Override
- protected boolean isDirectory(LocalPath path, boolean followSymlinks) {
+ protected boolean isDirectory(Path path, boolean followSymlinks) {
FileStatus stat = statNullable(path, followSymlinks);
return stat != null ? stat.isDirectory() : false;
}
@Override
- protected abstract FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException;
+ protected abstract FileStatus stat(Path path, boolean followSymlinks) throws IOException;
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
index 0e92b3dbac..fef88b892b 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
@@ -39,6 +39,7 @@ import java.util.List;
*/
@ThreadSafe
public abstract class FileSystem {
+
/** Type of hash function to use for digesting files. */
// The underlying HashFunctions are immutable and thread safe.
@SuppressWarnings("ImmutableEnumChecker")
@@ -99,15 +100,15 @@ public abstract class FileSystem {
public Path getCachedChildPathInternal(Path path, String childName) {
return Path.getCachedChildPathInternal(path, childName, /*cacheable=*/ true);
}
- }
+ };
}
/**
* An exception thrown when attempting to resolve an ordinary file as a symlink.
*/
protected static final class NotASymlinkException extends IOException {
- public NotASymlinkException(LocalPath path) {
- super(path.getPathString());
+ public NotASymlinkException(Path path) {
+ super(path.toString());
}
}
@@ -120,22 +121,24 @@ public abstract class FileSystem {
}
/**
- * Returns an absolute path instance, given an absolute path name, without double slashes, .., or
- * . segments. While this method will normalize the path representation by creating a
- * structured/parsed representation, it will not cause any IO. (e.g., it will not resolve symbolic
- * links if it's a Unix file system.
+ * Returns an absolute path instance, given an absolute path name, without
+ * double slashes, .., or . segments. While this method will normalize the
+ * path representation by creating a structured/parsed representation, it will
+ * not cause any IO. (e.g., it will not resolve symbolic links if it's a Unix
+ * file system.
*/
public Path getPath(String pathName) {
return getPath(PathFragment.create(pathName));
}
/**
- * Returns an absolute path instance, given an absolute path name, without double slashes, .., or
- * . segments. While this method will normalize the path representation by creating a
- * structured/parsed representation, it will not cause any IO. (e.g., it will not resolve symbolic
- * links if it's a Unix file system.
+ * Returns an absolute path instance, given an absolute path name, without
+ * double slashes, .., or . segments. While this method will normalize the
+ * path representation by creating a structured/parsed representation, it will
+ * not cause any IO. (e.g., it will not resolve symbolic links if it's a Unix
+ * file system.
*/
- public final Path getPath(PathFragment pathName) {
+ public Path getPath(PathFragment pathName) {
if (!pathName.isAbsolute()) {
throw new IllegalArgumentException(pathName.getPathString() + " (not an absolute path)");
}
@@ -162,14 +165,14 @@ public abstract class FileSystem {
* <p>Returns true if FileSystem supports the following:
*
* <ul>
- * <li>{@link #setWritable(LocalPath, boolean)}
- * <li>{@link #setExecutable(LocalPath, boolean)}
+ * <li>{@link #setWritable(Path, boolean)}
+ * <li>{@link #setExecutable(Path, boolean)}
* </ul>
*
* The above calls will result in an {@link UnsupportedOperationException} on a FileSystem where
* this method returns {@code false}.
*/
- public abstract boolean supportsModifications(LocalPath path);
+ public abstract boolean supportsModifications(Path path);
/**
* Returns whether or not the FileSystem supports symbolic links.
@@ -177,17 +180,17 @@ public abstract class FileSystem {
* <p>Returns true if FileSystem supports the following:
*
* <ul>
- * <li>{@link #createSymbolicLink(LocalPath, String)}
- * <li>{@link #getFileSize(LocalPath, boolean)} where {@code followSymlinks=false}
- * <li>{@link #getLastModifiedTime(LocalPath, boolean)} where {@code followSymlinks=false}
- * <li>{@link #readSymbolicLink(LocalPath)} where the link points to a non-existent file
+ * <li>{@link #createSymbolicLink(Path, PathFragment)}
+ * <li>{@link #getFileSize(Path, boolean)} where {@code followSymlinks=false}
+ * <li>{@link #getLastModifiedTime(Path, boolean)} where {@code followSymlinks=false}
+ * <li>{@link #readSymbolicLink(Path)} where the link points to a non-existent file
* </ul>
*
* The above calls may result in an {@link UnsupportedOperationException} on a FileSystem where
* this method returns {@code false}. The implementation can try to emulate these calls at its own
* discretion.
*/
- public abstract boolean supportsSymbolicLinksNatively(LocalPath path);
+ public abstract boolean supportsSymbolicLinksNatively(Path path);
/**
* Returns whether or not the FileSystem supports hard links.
@@ -195,14 +198,14 @@ public abstract class FileSystem {
* <p>Returns true if FileSystem supports the following:
*
* <ul>
- * <li>{@link #createFSDependentHardLink(LocalPath, LocalPath)}
+ * <li>{@link #createFSDependentHardLink(Path, Path)}
* </ul>
*
* The above calls may result in an {@link UnsupportedOperationException} on a FileSystem where
* this method returns {@code false}. The implementation can try to emulate these calls at its own
* discretion.
*/
- protected abstract boolean supportsHardLinksNatively(LocalPath path);
+ protected abstract boolean supportsHardLinksNatively(Path path);
/***
* Returns true if file path is case-sensitive on this file system. Default is true.
@@ -212,27 +215,28 @@ public abstract class FileSystem {
/**
* Returns the type of the file system path belongs to.
*
- * <p>The string returned is obtained directly from the operating system, so it's a best guess in
- * absence of a guaranteed api.
+ * <p>The string returned is obtained directly from the operating system, so
+ * it's a best guess in absence of a guaranteed api.
*
- * <p>This implementation uses <code>/proc/mounts</code> to determine the file system type.
+ * <p>This implementation uses <code>/proc/mounts</code> to determine the
+ * file system type.
*/
- public String getFileSystemType(LocalPath path) {
+ public String getFileSystemType(Path path) {
String fileSystem = "unknown";
int bestMountPointSegmentCount = -1;
try {
- LocalPath canonicalPath = resolveSymbolicLinks(path);
- LocalPath mountTable = path.getRelative("/proc/mounts");
- try (InputStreamReader reader =
- new InputStreamReader(getInputStream(mountTable), ISO_8859_1)) {
+ Path canonicalPath = path.resolveSymbolicLinks();
+ Path mountTable = path.getRelative("/proc/mounts");
+ try (InputStreamReader reader = new InputStreamReader(mountTable.getInputStream(),
+ ISO_8859_1)) {
for (String line : CharStreams.readLines(reader)) {
String[] words = line.split("\\s+");
if (words.length >= 3) {
if (!words[1].startsWith("/")) {
continue;
}
- LocalPath mountPoint = LocalPath.create(words[1]);
- int segmentCount = mountPoint.split().size();
+ Path mountPoint = path.getFileSystem().getPath(words[1]);
+ int segmentCount = mountPoint.asFragment().segmentCount();
if (canonicalPath.startsWith(mountPoint) && segmentCount > bestMountPointSegmentCount) {
bestMountPointSegmentCount = segmentCount;
fileSystem = words[2];
@@ -250,62 +254,62 @@ public abstract class FileSystem {
* Creates a directory with the name of the current path. See {@link Path#createDirectory} for
* specification.
*/
- public abstract boolean createDirectory(LocalPath path) throws IOException;
+ public abstract boolean createDirectory(Path path) throws IOException;
/**
* Returns the size in bytes of the file denoted by {@code path}. See {@link
* Path#getFileSize(Symlinks)} for specification.
*
- * <p>Note: for <@link FileSystem>s where {@link #supportsSymbolicLinksNatively(LocalPath)}
- * returns false, this method will throw an {@link UnsupportedOperationException} if {@code
+ * <p>Note: for <@link FileSystem>s where {@link #supportsSymbolicLinksNatively(Path)} returns
+ * false, this method will throw an {@link UnsupportedOperationException} if {@code
* followSymLinks=false}.
*/
- protected abstract long getFileSize(LocalPath path, boolean followSymlinks) throws IOException;
+ protected abstract long getFileSize(Path path, boolean followSymlinks) throws IOException;
/** Deletes the file denoted by {@code path}. See {@link Path#delete} for specification. */
- public abstract boolean delete(LocalPath path) throws IOException;
+ public abstract boolean delete(Path path) throws IOException;
/**
* Returns the last modification time of the file denoted by {@code path}. See {@link
* Path#getLastModifiedTime(Symlinks)} for specification.
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(LocalPath)}
- * returns false, this method will throw an {@link UnsupportedOperationException} if {@code
+ * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(Path)} returns
+ * false, this method will throw an {@link UnsupportedOperationException} if {@code
* followSymLinks=false}.
*/
- protected abstract long getLastModifiedTime(LocalPath path, boolean followSymlinks)
- throws IOException;
+ protected abstract long getLastModifiedTime(Path path, boolean followSymlinks) throws IOException;
/**
* Sets the last modification time of the file denoted by {@code path}. See {@link
* Path#setLastModifiedTime} for specification.
*/
- public abstract void setLastModifiedTime(LocalPath path, long newTime) throws IOException;
+ public abstract void setLastModifiedTime(Path path, long newTime) throws IOException;
/**
- * Returns value of the given extended attribute name or null if attribute does not exist or file
- * system does not support extended attributes. Follows symlinks.
- *
- * <p>Default implementation assumes that file system does not support extended attributes and
- * always returns null. Specific file system implementations should override this method if they
- * do provide support for extended attributes.
+ * Returns value of the given extended attribute name or null if attribute
+ * does not exist or file system does not support extended attributes. Follows symlinks.
+ * <p>Default implementation assumes that file system does not support
+ * extended attributes and always returns null. Specific file system
+ * implementations should override this method if they do provide support
+ * for extended attributes.
*
* @param path the file whose extended attribute is to be returned.
* @param name the name of the extended attribute key.
- * @return the value of the extended attribute associated with 'path', if any, or null if no such
- * attribute is defined (ENODATA) or file system does not support extended attributes at all.
+ * @return the value of the extended attribute associated with 'path', if
+ * any, or null if no such attribute is defined (ENODATA) or file
+ * system does not support extended attributes at all.
* @throws IOException if the call failed for any other reason.
*/
- public byte[] getxattr(LocalPath path, String name) throws IOException {
+ public byte[] getxattr(Path path, String name) throws IOException {
return null;
}
/**
- * Gets a fast digest for the given path and hash function type, or {@code null} if there isn't
- * one available or the filesystem doesn't support them. This digest should be suitable for
- * detecting changes to the file.
+ * Gets a fast digest for the given path and hash function type, or {@code null} if there
+ * isn't one available or the filesystem doesn't support them. This digest should be
+ * suitable for detecting changes to the file.
*/
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
return null;
}
@@ -314,7 +318,7 @@ public abstract class FileSystem {
* filesystem doesn't support them. This digest should be suitable for detecting changes to the
* file.
*/
- protected final byte[] getFastDigest(LocalPath path) throws IOException {
+ protected final byte[] getFastDigest(Path path) throws IOException {
return getFastDigest(path, digestFunction);
}
@@ -326,14 +330,15 @@ public abstract class FileSystem {
}
/**
- * Returns the digest of the file denoted by the path, following symbolic links, for the given
- * hash digest function.
+ * Returns the digest of the file denoted by the path, following
+ * symbolic links, for the given hash digest function.
*
* @return a new byte array containing the file's digest
* @throws IOException if the digest could not be computed for any reason
- * <p>Subclasses may (and do) optimize this computation for particular digest functions.
+ *
+ * Subclasses may (and do) optimize this computation for particular digest functions.
*/
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(final Path path, HashFunction hashFunction) throws IOException {
return new ByteSource() {
@Override
public InputStream openStream() throws IOException {
@@ -348,33 +353,34 @@ public abstract class FileSystem {
* @return a new byte array containing the file's digest
* @throws IOException if the digest could not be computed for any reason
*/
- protected final byte[] getDigest(LocalPath path) throws IOException {
+ protected final byte[] getDigest(final Path path) throws IOException {
return getDigest(path, digestFunction);
}
/**
- * Returns true if "path" denotes an existing symbolic link. See {@link Path#isSymbolicLink} for
- * specification.
+ * Returns true if "path" denotes an existing symbolic link. See
+ * {@link Path#isSymbolicLink} for specification.
*/
- protected abstract boolean isSymbolicLink(LocalPath path);
+ protected abstract boolean isSymbolicLink(Path path);
/**
- * Appends a single regular path segment 'child' to 'dir', recursively resolving symbolic links in
- * 'child'. 'dir' must be canonical. 'maxLinks' is the maximum number of symbolic links that may
- * be traversed before it gives up (the Linux kernel uses 32).
+ * Appends a single regular path segment 'child' to 'dir', recursively
+ * resolving symbolic links in 'child'. 'dir' must be canonical. 'maxLinks' is
+ * the maximum number of symbolic links that may be traversed before it gives
+ * up (the Linux kernel uses 32).
*
- * <p>(This method does not need to be synchronized; but the result may be stale in the case of
- * concurrent modification.)
+ * <p>(This method does not need to be synchronized; but the result may be
+ * stale in the case of concurrent modification.)
*
- * @throws IOException if 'dir' is not an existing directory; or if stat(child) fails for any
- * reason, or if 'child' is a symlink and readlink(child) fails for any reason (e.g. ENOENT,
- * EACCES), or if the chain of symbolic links exceeds 'maxLinks'.
+ * @throws IOException if 'dir' is not an existing directory; or if
+ * stat(child) fails for any reason, or if 'child' is a symlink and
+ * readlink(child) fails for any reason (e.g. ENOENT, EACCES), or if
+ * the chain of symbolic links exceeds 'maxLinks'.
*/
- protected final LocalPath appendSegment(LocalPath dir, String child, int maxLinks)
- throws IOException {
- LocalPath naive = dir.getRelative(child);
+ protected final Path appendSegment(Path dir, String child, int maxLinks) throws IOException {
+ Path naive = dir.getChild(child);
- String linkTarget = resolveOneLink(naive);
+ PathFragment linkTarget = resolveOneLink(naive);
if (linkTarget == null) {
return naive; // regular file or directory
}
@@ -382,15 +388,14 @@ public abstract class FileSystem {
if (maxLinks-- == 0) {
throw new IOException(naive + " (Too many levels of symbolic links)");
}
- LocalPath linkTargetPath = LocalPath.create(linkTarget);
- if (linkTargetPath.isAbsolute()) {
- dir = linkTargetPath.getDrive();
+ if (linkTarget.isAbsolute()) {
+ dir = getRootDirectory();
}
- for (String name : linkTargetPath.split()) {
+ for (String name : linkTarget.segments()) {
if (name.equals(".") || name.isEmpty()) {
// no-op
} else if (name.equals("..")) {
- LocalPath parent = dir.getParentDirectory();
+ Path parent = dir.getParentDirectory();
// root's parent is root, when canonicalizing, so this is a no-op.
if (parent != null) { dir = parent; }
} else {
@@ -401,19 +406,21 @@ public abstract class FileSystem {
}
/**
- * Helper method of {@link #resolveSymbolicLinks(LocalPath)}. This method encapsulates the I/O
- * component of a full canonicalization operation. Subclasses can (and do) provide more efficient
- * implementations.
+ * Helper method of {@link #resolveSymbolicLinks(Path)}. This method
+ * encapsulates the I/O component of a full canonicalization operation.
+ * Subclasses can (and do) provide more efficient implementations.
*
- * <p>(This method does not need to be synchronized; but the result may be stale in the case of
- * concurrent modification.)
+ * <p>(This method does not need to be synchronized; but the result may be
+ * stale in the case of concurrent modification.)
*
- * @param path a path, of which all but the last segment is guaranteed to be canonical
- * @return {@link #readSymbolicLink} iff path is a symlink or null iff path exists but is not a
- * symlink
- * @throws IOException if the file did not exist, or a parent directory could not be searched
+ * @param path a path, of which all but the last segment is guaranteed to be
+ * canonical
+ * @return {@link #readSymbolicLink} iff path is a symlink or null iff
+ * path exists but is not a symlink
+ * @throws IOException if the file did not exist, or a parent directory could
+ * not be searched
*/
- protected String resolveOneLink(LocalPath path) throws IOException {
+ protected PathFragment resolveOneLink(Path path) throws IOException {
try {
return readSymbolicLink(path);
} catch (NotASymlinkException e) {
@@ -433,25 +440,28 @@ public abstract class FileSystem {
}
/**
- * Returns the canonical path for the given path. See {@link Path#resolveSymbolicLinks} for
- * specification.
+ * Returns the canonical path for the given path. See
+ * {@link Path#resolveSymbolicLinks} for specification.
*/
- protected LocalPath resolveSymbolicLinks(LocalPath path) throws IOException {
- LocalPath parentNode = path.getParentDirectory();
+ protected Path resolveSymbolicLinks(Path path)
+ throws IOException {
+ Path parentNode = path.getParentDirectory();
return parentNode == null
? path // (root)
: appendSegment(resolveSymbolicLinks(parentNode), path.getBaseName(), 32);
}
/**
- * Returns the status of a file. See {@link Path#stat(Symlinks)} for specification.
+ * Returns the status of a file. See {@link Path#stat(Symlinks)} for
+ * specification.
*
- * <p>The default implementation of this method is a "lazy" one, based on other accessor methods
- * such as {@link #isFile}, etc. Subclasses may provide more efficient specializations. However,
- * we still try to follow Unix-like semantics of failing fast in case of non-existent files (or in
- * case of permission issues).
+ * <p>The default implementation of this method is a "lazy" one, based on
+ * other accessor methods such as {@link #isFile}, etc. Subclasses may provide
+ * more efficient specializations. However, we still try to follow Unix-like
+ * semantics of failing fast in case of non-existent files (or in case of
+ * permission issues).
*/
- protected FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus stat(final Path path, final boolean followSymlinks) throws IOException {
FileStatus status = new FileStatus() {
volatile Boolean isFile;
volatile Boolean isDirectory;
@@ -516,8 +526,10 @@ public abstract class FileSystem {
return status;
}
- /** Like stat(), but returns null on failures instead of throwing. */
- protected FileStatus statNullable(LocalPath path, boolean followSymlinks) {
+ /**
+ * Like stat(), but returns null on failures instead of throwing.
+ */
+ protected FileStatus statNullable(Path path, boolean followSymlinks) {
try {
return stat(path, followSymlinks);
} catch (IOException e) {
@@ -526,12 +538,12 @@ public abstract class FileSystem {
}
/**
- * Like {@link #stat}, but returns null if the file is not found (corresponding to {@code ENOENT}
- * or {@code ENOTDIR} in Unix's stat(2) function) instead of throwing. Note that this
- * implementation does <i>not</i> successfully catch {@code ENOTDIR} exceptions. If the
+ * Like {@link #stat}, but returns null if the file is not found (corresponding to
+ * {@code ENOENT} or {@code ENOTDIR} in Unix's stat(2) function) instead of throwing. Note that
+ * this implementation does <i>not</i> successfully catch {@code ENOTDIR} exceptions. If the
* instantiated filesystem can catch such errors, it should override this method to do so.
*/
- protected FileStatus statIfFound(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
try {
return stat(path, followSymlinks);
} catch (FileNotFoundException e) {
@@ -540,65 +552,65 @@ public abstract class FileSystem {
}
/**
- * Returns true iff {@code path} denotes an existing directory. See {@link
- * Path#isDirectory(Symlinks)} for specification.
+ * Returns true iff {@code path} denotes an existing directory. See
+ * {@link Path#isDirectory(Symlinks)} for specification.
*/
- protected abstract boolean isDirectory(LocalPath path, boolean followSymlinks);
+ protected abstract boolean isDirectory(Path path, boolean followSymlinks);
/**
- * Returns true iff {@code path} denotes an existing regular or special file. See {@link
- * Path#isFile(Symlinks)} for specification.
+ * Returns true iff {@code path} denotes an existing regular or special file.
+ * See {@link Path#isFile(Symlinks)} for specification.
*/
- protected abstract boolean isFile(LocalPath path, boolean followSymlinks);
+ protected abstract boolean isFile(Path path, boolean followSymlinks);
/**
- * Returns true iff {@code path} denotes a special file. See {@link Path#isSpecialFile(Symlinks)}
- * for specification.
+ * Returns true iff {@code path} denotes a special file.
+ * See {@link Path#isSpecialFile(Symlinks)} for specification.
*/
- protected abstract boolean isSpecialFile(LocalPath path, boolean followSymlinks);
+ protected abstract boolean isSpecialFile(Path path, boolean followSymlinks);
/**
* Creates a symbolic link. See {@link Path#createSymbolicLink(Path)} for specification.
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(LocalPath)}
- * returns false, this method will throw an {@link UnsupportedOperationException}
+ * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(Path)} returns
+ * false, this method will throw an {@link UnsupportedOperationException}
*/
- protected abstract void createSymbolicLink(LocalPath linkPath, String targetFragment)
+ protected abstract void createSymbolicLink(Path linkPath, PathFragment targetFragment)
throws IOException;
/**
* Returns the target of a symbolic link. See {@link Path#readSymbolicLink} for specification.
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(LocalPath)}
- * returns false, this method will throw an {@link UnsupportedOperationException} if the link
- * points to a non-existent file.
+ * <p>Note: for {@link FileSystem}s where {@link #supportsSymbolicLinksNatively(Path)} returns
+ * false, this method will throw an {@link UnsupportedOperationException} if the link points to a
+ * non-existent file.
*
* @throws NotASymlinkException if the current path is not a symbolic link
* @throws IOException if the contents of the link could not be read for any reason.
*/
- protected abstract String readSymbolicLink(LocalPath path) throws IOException;
+ protected abstract PathFragment readSymbolicLink(Path path) throws IOException;
/**
* Returns the target of a symbolic link, under the assumption that the given path is indeed a
- * symbolic link (this assumption permits efficient implementations). See {@link
- * Path#readSymbolicLinkUnchecked} for specification.
+ * symbolic link (this assumption permits efficient implementations). See
+ * {@link Path#readSymbolicLinkUnchecked} for specification.
*
* @throws IOException if the contents of the link could not be read for any reason.
*/
- protected String readSymbolicLinkUnchecked(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLinkUnchecked(Path path) throws IOException {
return readSymbolicLink(path);
}
/** Returns true iff this path denotes an existing file of any kind. Follows symbolic links. */
- public boolean exists(LocalPath path) {
+ public boolean exists(Path path) {
return exists(path, true);
}
/**
- * Returns true iff {@code path} denotes an existing file of any kind. See {@link
- * Path#exists(Symlinks)} for specification.
+ * Returns true iff {@code path} denotes an existing file of any kind. See
+ * {@link Path#exists(Symlinks)} for specification.
*/
- protected abstract boolean exists(LocalPath path, boolean followSymlinks);
+ protected abstract boolean exists(Path path, boolean followSymlinks);
/**
* Returns a collection containing the names of all entities within the directory denoted by the
@@ -606,7 +618,7 @@ public abstract class FileSystem {
*
* @throws IOException if there was an error reading the directory entries
*/
- protected abstract Collection<String> getDirectoryEntries(LocalPath path) throws IOException;
+ protected abstract Collection<String> getDirectoryEntries(Path path) throws IOException;
protected static Dirent.Type direntFromStat(FileStatus stat) {
if (stat == null) {
@@ -625,19 +637,19 @@ public abstract class FileSystem {
}
/**
- * Returns a Dirents structure, listing the names of all entries within the directory {@code
- * path}, plus their types (file, directory, other).
+ * Returns a Dirents structure, listing the names of all entries within the
+ * directory {@code path}, plus their types (file, directory, other).
*
- * @param followSymlinks whether to follow symlinks when determining the file types of individual
- * directory entries. No matter the value of this parameter, symlinks are followed when
- * resolving the directory whose entries are to be read.
+ * @param followSymlinks whether to follow symlinks when determining the file types of
+ * individual directory entries. No matter the value of this parameter, symlinks are
+ * followed when resolving the directory whose entries are to be read.
* @throws IOException if there was an error reading the directory entries
*/
- protected Collection<Dirent> readdir(LocalPath path, boolean followSymlinks) throws IOException {
+ protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
Collection<String> children = getDirectoryEntries(path);
List<Dirent> dirents = Lists.newArrayListWithCapacity(children.size());
for (String child : children) {
- LocalPath childPath = path.getRelative(child);
+ Path childPath = path.getChild(child);
Dirent.Type type = direntFromStat(statNullable(childPath, followSymlinks));
dirents.add(new Dirent(child, type));
}
@@ -649,54 +661,54 @@ public abstract class FileSystem {
*
* @throws IOException if there was an error reading the file's metadata
*/
- protected abstract boolean isReadable(LocalPath path) throws IOException;
+ protected abstract boolean isReadable(Path path) throws IOException;
/**
* Sets the file to readable (if the argument is true) or non-readable (if the argument is false)
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(LocalPath)} returns false
- * or which do not support unreadable files, this method will throw an {@link
+ * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(Path)} returns false or
+ * which do not support unreadable files, this method will throw an {@link
* UnsupportedOperationException}.
*
* @throws IOException if there was an error reading or writing the file's metadata
*/
- protected abstract void setReadable(LocalPath path, boolean readable) throws IOException;
+ protected abstract void setReadable(Path path, boolean readable) throws IOException;
/**
* Returns true iff the file represented by {@code path} is writable.
*
* @throws IOException if there was an error reading the file's metadata
*/
- protected abstract boolean isWritable(LocalPath path) throws IOException;
+ protected abstract boolean isWritable(Path path) throws IOException;
/**
* Sets the file to writable (if the argument is true) or non-writable (if the argument is false)
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(LocalPath)} returns false,
- * this method will throw an {@link UnsupportedOperationException}.
+ * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(Path)} returns false, this
+ * method will throw an {@link UnsupportedOperationException}.
*
* @throws IOException if there was an error reading or writing the file's metadata
*/
- public abstract void setWritable(LocalPath path, boolean writable) throws IOException;
+ public abstract void setWritable(Path path, boolean writable) throws IOException;
/**
* Returns true iff the file represented by the path is executable.
*
* @throws IOException if there was an error reading the file's metadata
*/
- protected abstract boolean isExecutable(LocalPath path) throws IOException;
+ protected abstract boolean isExecutable(Path path) throws IOException;
/**
* Sets the file to executable, if the argument is true. It is currently not supported to unset
* the executable status of a file, so {code executable=false} yields an {@link
* UnsupportedOperationException}.
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(LocalPath)} returns false,
- * this method will throw an {@link UnsupportedOperationException}.
+ * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(Path)} returns false, this
+ * method will throw an {@link UnsupportedOperationException}.
*
* @throws IOException if there was an error reading or writing the file's metadata
*/
- protected abstract void setExecutable(LocalPath path, boolean executable) throws IOException;
+ protected abstract void setExecutable(Path path, boolean executable) throws IOException;
/**
* Sets the file permissions. If permission changes on this {@link FileSystem} are slow (e.g. one
@@ -704,12 +716,12 @@ public abstract class FileSystem {
* individually. If this {@link FileSystem} does not support group or others permissions, those
* bits will be ignored.
*
- * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(LocalPath)} returns false,
- * this method will throw an {@link UnsupportedOperationException}.
+ * <p>Note: for {@link FileSystem}s where {@link #supportsModifications(Path)} returns false, this
+ * method will throw an {@link UnsupportedOperationException}.
*
* @throws IOException if there was an error reading or writing the file's metadata
*/
- protected void chmod(LocalPath path, int mode) throws IOException {
+ protected void chmod(Path path, int mode) throws IOException {
setReadable(path, (mode & 0400) != 0);
setWritable(path, (mode & 0200) != 0);
setExecutable(path, (mode & 0100) != 0);
@@ -720,14 +732,14 @@ public abstract class FileSystem {
*
* @throws IOException if there was an error opening the file for reading
*/
- protected abstract InputStream getInputStream(LocalPath path) throws IOException;
+ protected abstract InputStream getInputStream(Path path) throws IOException;
/**
* Creates an OutputStream accessing the file denoted by path.
*
* @throws IOException if there was an error opening the file for writing
*/
- protected final OutputStream getOutputStream(LocalPath path) throws IOException {
+ protected final OutputStream getOutputStream(Path path) throws IOException {
return getOutputStream(path, false);
}
@@ -737,14 +749,13 @@ public abstract class FileSystem {
* @param append whether to open the output stream in append mode
* @throws IOException if there was an error opening the file for writing
*/
- protected abstract OutputStream getOutputStream(LocalPath path, boolean append)
- throws IOException;
+ protected abstract OutputStream getOutputStream(Path path, boolean append) throws IOException;
/**
* Renames the file denoted by "sourceNode" to the location "targetNode". See {@link
* Path#renameTo} for specification.
*/
- public abstract void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException;
+ public abstract void renameTo(Path sourcePath, Path targetPath) throws IOException;
/**
* Create a new hard link file at "linkPath" for file at "originalPath".
@@ -753,9 +764,9 @@ public abstract class FileSystem {
* @param originalPath The path of the original file
* @throws IOException if the original file does not exist or the link file already exists
*/
- protected void createHardLink(LocalPath linkPath, LocalPath originalPath) throws IOException {
+ protected void createHardLink(Path linkPath, Path originalPath) throws IOException {
- if (!exists(originalPath, true)) {
+ if (!originalPath.exists()) {
throw new FileNotFoundException(
"File \""
+ originalPath.getBaseName()
@@ -764,7 +775,7 @@ public abstract class FileSystem {
+ "\" does not exist");
}
- if (exists(linkPath, true)) {
+ if (linkPath.exists()) {
throw new FileAlreadyExistsException(
"New link file \"" + linkPath.getBaseName() + "\" already exists");
}
@@ -779,13 +790,14 @@ public abstract class FileSystem {
* @param originalPath The path of the original file
* @throws IOException if there was an I/O error
*/
- protected abstract void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected abstract void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException;
/**
- * Prefetch all directories and symlinks within the package rooted at "path". Enter at most
- * "maxDirs" total directories. Specializations for high-latency remote filesystems may wish to
+ * Prefetch all directories and symlinks within the package
+ * rooted at "path". Enter at most "maxDirs" total directories.
+ * Specializations for high-latency remote filesystems may wish to
* implement this in order to warm the filesystem's internal caches.
*/
- protected void prefetchPackageAsync(LocalPath path, int maxDirs) {}
+ protected void prefetchPackageAsync(Path path, int maxDirs) { }
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java
index 930a8beb13..064e4b2e16 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java
@@ -378,37 +378,23 @@ public class FileSystemUtils {
}
public static ByteSource asByteSource(final Path path) {
- return asByteSource(path.getFileSystem(), path.getLocalPath());
- }
-
- public static ByteSink asByteSink(final Path path, final boolean append) {
- return asByteSink(path.getFileSystem(), path.getLocalPath(), append);
- }
-
- public static ByteSink asByteSink(final Path path) {
- return asByteSink(path, false);
- }
-
- public static ByteSource asByteSource(FileSystem fileSystem, LocalPath path) {
return new ByteSource() {
- @Override
- public InputStream openStream() throws IOException {
- return fileSystem.getInputStream(path);
+ @Override public InputStream openStream() throws IOException {
+ return path.getInputStream();
}
};
}
- public static ByteSink asByteSink(FileSystem fileSystem, LocalPath path, final boolean append) {
+ public static ByteSink asByteSink(final Path path, final boolean append) {
return new ByteSink() {
- @Override
- public OutputStream openStream() throws IOException {
- return fileSystem.getOutputStream(path, append);
+ @Override public OutputStream openStream() throws IOException {
+ return path.getOutputStream(append);
}
};
}
- public static ByteSink asByteSink(FileSystem fileSystem, LocalPath path) {
- return asByteSink(fileSystem, path, false);
+ public static ByteSink asByteSink(final Path path) {
+ return asByteSink(path, false);
}
/**
@@ -422,34 +408,18 @@ public class FileSystemUtils {
*/
@ThreadSafe // but not atomic
public static void copyFile(Path from, Path to) throws IOException {
- copyFile(from.getFileSystem(), from.getLocalPath(), to.getFileSystem(), to.getLocalPath());
- }
-
- /**
- * Copies the file from location "from" to location "to", while overwriting a potentially existing
- * "to". File's last modified time, executable and writable bits are also preserved.
- *
- * <p>If no error occurs, the method returns normally. If a parent directory does not exist, a
- * FileNotFoundException is thrown. An IOException is thrown when other erroneous situations
- * occur. (e.g. read errors)
- */
- @ThreadSafe // but not atomic
- public static void copyFile(
- FileSystem fromFileSystem, LocalPath from, FileSystem toFileSystem, LocalPath to)
- throws IOException {
try {
- toFileSystem.delete(to);
+ to.delete();
} catch (IOException e) {
throw new IOException("error copying file: "
+ "couldn't delete destination: " + e.getMessage());
}
- asByteSource(fromFileSystem, from).copyTo(asByteSink(toFileSystem, to));
- toFileSystem.setLastModifiedTime(
- to, fromFileSystem.getLastModifiedTime(from, true)); // Preserve mtime.
- if (!fromFileSystem.isWritable(from)) {
- toFileSystem.setWritable(to, false); // Make file read-only if original was read-only.
+ asByteSource(from).copyTo(asByteSink(to));
+ to.setLastModifiedTime(from.getLastModifiedTime()); // Preserve mtime.
+ if (!from.isWritable()) {
+ to.setWritable(false); // Make file read-only if original was read-only.
}
- toFileSystem.setExecutable(to, fromFileSystem.isExecutable(from)); // Copy executable bit.
+ to.setExecutable(from.isExecutable()); // Copy executable bit.
}
/**
@@ -695,7 +665,7 @@ public class FileSystemUtils {
if (filesystem instanceof UnionFileSystem) {
// If using UnionFS, make sure that we do not traverse filesystem boundaries when creating
// parent directories by rehoming the path on the most specific filesystem.
- FileSystem delegate = ((UnionFileSystem) filesystem).getDelegate(dir.getLocalPath());
+ FileSystem delegate = ((UnionFileSystem) filesystem).getDelegate(dir);
dir = delegate.getPath(dir.asFragment());
}
@@ -787,18 +757,7 @@ public class FileSystemUtils {
* @throws IOException if there was an error
*/
public static void writeContentAsLatin1(Path outputFile, String content) throws IOException {
- writeContentAsLatin1(outputFile.getFileSystem(), outputFile.getLocalPath(), content);
- }
-
- /**
- * Writes the specified String as ISO-8859-1 (latin1) encoded bytes to the file. Follows symbolic
- * links.
- *
- * @throws IOException if there was an error
- */
- public static void writeContentAsLatin1(
- FileSystem fileSystem, LocalPath outputFile, String content) throws IOException {
- writeContent(fileSystem, outputFile, ISO_8859_1, content);
+ writeContent(outputFile, ISO_8859_1, content);
}
/**
@@ -809,18 +768,7 @@ public class FileSystemUtils {
*/
public static void writeContent(Path outputFile, Charset charset, String content)
throws IOException {
- writeContent(outputFile.getFileSystem(), outputFile.getLocalPath(), charset, content);
- }
-
- /**
- * Writes the specified String using the specified encoding to the file. Follows symbolic links.
- *
- * @throws IOException if there was an error
- */
- public static void writeContent(
- FileSystem fileSystem, LocalPath outputFile, Charset charset, String content)
- throws IOException {
- asByteSink(fileSystem, outputFile).asCharSink(charset).write(content);
+ asByteSink(outputFile).asCharSink(charset).write(content);
}
/**
@@ -1029,7 +977,7 @@ public class FileSystemUtils {
* Returns the type of the file system path belongs to.
*/
public static String getFileSystem(Path path) {
- return path.getFileSystem().getFileSystemType(path.getLocalPath());
+ return path.getFileSystem().getFileSystemType(path);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java
index 13813882c5..dca8b95906 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.vfs;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.util.concurrent.Striped;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
@@ -29,7 +28,6 @@ import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.concurrent.locks.Lock;
/**
* A FileSystem that does not use any JNI and hence, does not require a shared library be present at
@@ -41,7 +39,6 @@ import java.util.concurrent.locks.Lock;
*/
@ThreadSafe
public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
- private final Striped<Lock> pathLock = Striped.lock(64);
private static final LinkOption[] NO_LINK_OPTION = new LinkOption[0];
// This isn't generally safe; we rely on the file system APIs not modifying the array.
private static final LinkOption[] NOFOLLOW_LINKS_OPTION =
@@ -69,7 +66,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
this.clock = clock;
}
- protected File getIoFile(LocalPath path) {
+ protected File getIoFile(Path path) {
return new File(path.toString());
}
@@ -81,7 +78,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
* avoids extra allocations and does not lose track of the underlying Java filesystem, which is
* useful for some in-memory filesystem implementations like JimFS.
*/
- protected java.nio.file.Path getNioPath(LocalPath path) {
+ protected java.nio.file.Path getNioPath(Path path) {
return Paths.get(path.toString());
}
@@ -90,7 +87,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected Collection<String> getDirectoryEntries(LocalPath path) throws IOException {
+ protected Collection<String> getDirectoryEntries(Path path) throws IOException {
File file = getIoFile(path);
String[] entries = null;
long startTime = Profiler.nanoTimeMaybe();
@@ -116,7 +113,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean exists(LocalPath path, boolean followSymlinks) {
+ protected boolean exists(Path path, boolean followSymlinks) {
java.nio.file.Path nioPath = getNioPath(path);
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -127,7 +124,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean isReadable(LocalPath path) throws IOException {
+ protected boolean isReadable(Path path) throws IOException {
File file = getIoFile(path);
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -141,7 +138,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean isWritable(LocalPath path) throws IOException {
+ protected boolean isWritable(Path path) throws IOException {
File file = getIoFile(path);
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -159,7 +156,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected boolean isExecutable(LocalPath path) throws IOException {
+ protected boolean isExecutable(Path path) throws IOException {
File file = getIoFile(path);
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -173,7 +170,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
File file = getIoFile(path);
if (!file.exists()) {
throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
@@ -182,7 +179,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
File file = getIoFile(path);
if (!file.exists()) {
throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
@@ -191,7 +188,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) throws IOException {
+ protected void setExecutable(Path path, boolean executable) throws IOException {
File file = getIoFile(path);
if (!file.exists()) {
throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
@@ -200,17 +197,17 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return true;
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return true;
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
return true;
}
@@ -220,26 +217,22 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
+ public boolean createDirectory(Path path) throws IOException {
// We always synchronize on the current path before doing it on the parent path and file system
// path structure ensures that this locking order will never be reversed.
// When refactoring, check that subclasses still work as expected and there can be no
// deadlocks.
- Lock lock = getPathLock(path);
- lock.lock();
- try {
+ synchronized (path) {
File file = getIoFile(path);
if (file.mkdir()) {
return true;
}
// We will be checking the state of the parent path as well. Synchronize on it before
- // attempting anything. The striped lock used is re-entrant so this is safe.
- LocalPath parentDirectory = path.getParentDirectory();
- Lock parentLock = getPathLock(parentDirectory);
- parentLock.lock();
- try {
+ // attempting anything.
+ Path parentDirectory = path.getParentDirectory();
+ synchronized (parentDirectory) {
if (fileIsSymbolicLink(file)) {
throw new IOException(path + ERR_FILE_EXISTS);
}
@@ -261,11 +254,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
// Parent exists, is writable, yet we can't create our directory.
throw new FileNotFoundException(path.getParentDirectory() + ERR_NOT_A_DIRECTORY);
}
- } finally {
- parentLock.unlock();
}
- } finally {
- lock.unlock();
}
}
@@ -288,10 +277,11 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment)
+ throws IOException {
java.nio.file.Path nioPath = getNioPath(linkPath);
try {
- Files.createSymbolicLink(nioPath, Paths.get(targetFragment));
+ Files.createSymbolicLink(nioPath, Paths.get(targetFragment.getPathString()));
} catch (java.nio.file.FileAlreadyExistsException e) {
throw new IOException(linkPath + ERR_FILE_EXISTS);
} catch (java.nio.file.AccessDeniedException e) {
@@ -302,12 +292,12 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected String readSymbolicLink(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLink(Path path) throws IOException {
java.nio.file.Path nioPath = getNioPath(path);
long startTime = Profiler.nanoTimeMaybe();
try {
String link = Files.readSymbolicLink(nioPath).toString();
- return link;
+ return PathFragment.create(link);
} catch (java.nio.file.NotLinkException e) {
throw new NotASymlinkException(path);
} catch (java.nio.file.NoSuchFileException e) {
@@ -318,10 +308,8 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
- Lock lock = getPathLock(sourcePath);
- lock.lock();
- try {
+ public void renameTo(Path sourcePath, Path targetPath) throws IOException {
+ synchronized (sourcePath) {
File sourceFile = getIoFile(sourcePath);
File targetFile = getIoFile(targetPath);
if (!sourceFile.renameTo(targetFile)) {
@@ -342,13 +330,11 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
throw new FileAccessException(sourcePath + " -> " + targetPath + ERR_PERMISSION_DENIED);
}
}
- } finally {
- lock.unlock();
}
}
@Override
- protected long getFileSize(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getFileSize(Path path, boolean followSymlinks) throws IOException {
long startTime = Profiler.nanoTimeMaybe();
try {
return stat(path, followSymlinks).getSize();
@@ -358,7 +344,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public boolean delete(LocalPath path) throws IOException {
+ public boolean delete(Path path) throws IOException {
File file = getIoFile(path);
long startTime = Profiler.nanoTimeMaybe();
synchronized (path) {
@@ -381,7 +367,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected long getLastModifiedTime(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getLastModifiedTime(Path path, boolean followSymlinks) throws IOException {
File file = getIoFile(path);
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -396,7 +382,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
File file = getIoFile(path);
if (!file.setLastModified(newTime == -1L ? clock.currentTimeMillis() : newTime)) {
if (!file.exists()) {
@@ -410,7 +396,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hashFunction) throws IOException {
String name = path.toString();
long startTime = Profiler.nanoTimeMaybe();
try {
@@ -421,15 +407,17 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
/**
- * Returns the status of a file. See {@link Path#stat(Symlinks)} for specification.
+ * Returns the status of a file. See {@link Path#stat(Symlinks)} for
+ * specification.
*
- * <p>The default implementation of this method is a "lazy" one, based on other accessor methods
- * such as {@link #isFile}, etc. Subclasses may provide more efficient specializations. However,
- * we still try to follow Unix-like semantics of failing fast in case of non-existent files (or in
- * case of permission issues).
+ * <p>The default implementation of this method is a "lazy" one, based on
+ * other accessor methods such as {@link #isFile}, etc. Subclasses may provide
+ * more efficient specializations. However, we still try to follow Unix-like
+ * semantics of failing fast in case of non-existent files (or in case of
+ * permission issues).
*/
@Override
- protected FileStatus stat(LocalPath path, final boolean followSymlinks) throws IOException {
+ protected FileStatus stat(final Path path, final boolean followSymlinks) throws IOException {
java.nio.file.Path nioPath = getNioPath(path);
final BasicFileAttributes attributes;
try {
@@ -486,7 +474,7 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected FileStatus statIfFound(LocalPath path, boolean followSymlinks) {
+ protected FileStatus statIfFound(Path path, boolean followSymlinks) {
try {
return stat(path, followSymlinks);
} catch (FileNotFoundException e) {
@@ -503,15 +491,10 @@ public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException {
Files.createLink(
java.nio.file.Paths.get(linkPath.toString()),
java.nio.file.Paths.get(originalPath.toString()));
}
-
- /** Returns a per-path lock. The lock is re-entrant. */
- protected Lock getPathLock(LocalPath path) {
- return pathLock.get(path);
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/LocalPath.java b/src/main/java/com/google/devtools/build/lib/vfs/LocalPath.java
index b05c89f7bf..a32a4e356c 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/LocalPath.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/LocalPath.java
@@ -15,14 +15,12 @@ package com.google.devtools.build.lib.vfs;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.windows.WindowsShortPath;
import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import java.io.IOException;
-import java.util.List;
-import java.util.regex.Pattern;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
/**
@@ -52,8 +50,6 @@ public final class LocalPath implements Comparable<LocalPath> {
public static final LocalPath EMPTY = create("");
- private static final Splitter PATH_SPLITTER = Splitter.on('/').omitEmptyStrings();
-
private final String path;
private final int driveStrLength; // 0 for relative paths, 1 on Unix, 3 on Windows
private final OsPathPolicy os;
@@ -232,33 +228,19 @@ public final class LocalPath implements Comparable<LocalPath> {
* Splits a path into its constituent parts. The root is not included. This is an inefficient
* operation and should be avoided.
*/
- public List<String> split() {
- List<String> segments = PATH_SPLITTER.splitToList(path);
- if (driveStrLength > 1) {
- return segments.subList(1, segments.size());
+ public String[] split() {
+ String[] segments = path.split("/");
+ if (driveStrLength > 0) {
+ // String#split("/") for some reason returns a zero-length array
+ // String#split("/hello") returns a 2-length array, so this makes little sense
+ if (segments.length == 0) {
+ return segments;
+ }
+ return Arrays.copyOfRange(segments, 1, segments.length);
}
return segments;
}
- /** Returns the drive of this local path, eg. "/" on Unix or "C:/" on Windows. */
- public LocalPath getDrive() {
- if (driveStrLength == 0) {
- throw new IllegalArgumentException("Cannot get mount of non-absolute path.");
- }
- return new LocalPath(path.substring(0, driveStrLength), driveStrLength, os);
- }
-
- /**
- * Returns whether this is the root of the entire file system.
- *
- * <p>Please avoid this method. On Unix, this corresponds to the '/' mount point. Windows drives
- * (C:/) do not have a parent and are not the root of the entire file system, so do not return
- * true.
- */
- public boolean isRoot() {
- return os.isRoot(this);
- }
-
/**
* Returns whether this path is an ancestor of another path.
*
@@ -357,14 +339,10 @@ public final class LocalPath implements Comparable<LocalPath> {
char getSeparator();
boolean isCaseSensitive();
-
- boolean isRoot(LocalPath localPath);
}
@VisibleForTesting
static class UnixOsPathPolicy implements OsPathPolicy {
- private static Splitter UNIX_PATH_SPLITTER =
- Splitter.on(Pattern.compile("/+")).omitEmptyStrings();
@Override
public int needsToNormalize(String path) {
@@ -384,7 +362,7 @@ public final class LocalPath implements Comparable<LocalPath> {
dotCount = c == '.' ? dotCount + 1 : 0;
prevChar = c;
}
- if ((n > 1 && prevChar == '/') || dotCount == 1 || dotCount == 2) {
+ if (prevChar == '/' || dotCount == 1 || dotCount == 2) {
return NEEDS_NORMALIZE;
}
return NORMALIZED;
@@ -399,8 +377,8 @@ public final class LocalPath implements Comparable<LocalPath> {
return path;
}
boolean isAbsolute = path.charAt(0) == '/';
- String[] segments = Iterables.toArray(UNIX_PATH_SPLITTER.split(path), String.class);
- int segmentCount = removeRelativePaths(segments, 0);
+ String[] segments = path.split("/+");
+ int segmentCount = removeRelativePaths(segments, isAbsolute ? 1 : 0);
StringBuilder sb = new StringBuilder(path.length());
if (isAbsolute) {
sb.append('/');
@@ -447,11 +425,6 @@ public final class LocalPath implements Comparable<LocalPath> {
public boolean isCaseSensitive() {
return true;
}
-
- @Override
- public boolean isRoot(LocalPath localPath) {
- return localPath.path.equals("/");
- }
}
/** Mac is a unix file system that is case insensitive. */
@@ -478,9 +451,8 @@ public final class LocalPath implements Comparable<LocalPath> {
private static final int NEEDS_SHORT_PATH_NORMALIZATION = NEEDS_NORMALIZE + 1;
- private static Splitter WINDOWS_PATH_SPLITTER =
- Splitter.on(Pattern.compile("[\\\\/]+")).omitEmptyStrings();
-
+ // msys root, used to resolve paths from msys starting with "/"
+ private static final AtomicReference<String> UNIX_ROOT = new AtomicReference<>(null);
private final ShortPathResolver shortPathResolver;
interface ShortPathResolver {
@@ -510,6 +482,10 @@ public final class LocalPath implements Comparable<LocalPath> {
public int needsToNormalize(String path) {
int n = path.length();
int normalizationLevel = 0;
+ // Check for unix path
+ if (n > 0 && path.charAt(0) == '/') {
+ normalizationLevel = Math.max(normalizationLevel, NEEDS_NORMALIZE);
+ }
int dotCount = 0;
char prevChar = 0;
int segmentBeginIndex = 0; // The start index of the current path index
@@ -541,7 +517,7 @@ public final class LocalPath implements Comparable<LocalPath> {
dotCount = c == '.' ? dotCount + 1 : 0;
prevChar = c;
}
- if ((n > 1 && prevChar == '/') || dotCount == 1 || dotCount == 2) {
+ if (prevChar == '/' || dotCount == 1 || dotCount == 2) {
normalizationLevel = Math.max(normalizationLevel, NEEDS_NORMALIZE);
}
return normalizationLevel;
@@ -558,19 +534,26 @@ public final class LocalPath implements Comparable<LocalPath> {
path = resolvedPath;
}
}
- String[] segments = Iterables.toArray(WINDOWS_PATH_SPLITTER.splitToList(path), String.class);
+ String[] segments = path.split("[\\\\/]+");
int driveStrLength = getDriveStrLength(path);
boolean isAbsolute = driveStrLength > 0;
- int segmentSkipCount = isAbsolute && driveStrLength > 1 ? 1 : 0;
+ int segmentSkipCount = isAbsolute ? 1 : 0;
StringBuilder sb = new StringBuilder(path.length());
if (isAbsolute) {
- char c = path.charAt(0);
- if (c == '/') {
- sb.append('/');
- } else {
- sb.append(Character.toUpperCase(c));
+ char driveLetter = path.charAt(0);
+ sb.append(Character.toUpperCase(driveLetter));
+ sb.append(":/");
+ }
+ // unix path support
+ if (!path.isEmpty() && path.charAt(0) == '/') {
+ if (path.length() == 2 || (path.length() > 2 && path.charAt(2) == '/')) {
+ sb.append(Character.toUpperCase(path.charAt(1)));
sb.append(":/");
+ segmentSkipCount = 2;
+ } else {
+ String unixRoot = getUnixRoot();
+ sb.append(unixRoot);
}
}
int segmentCount = removeRelativePaths(segments, segmentSkipCount);
@@ -587,12 +570,6 @@ public final class LocalPath implements Comparable<LocalPath> {
@Override
public int getDriveStrLength(String path) {
int n = path.length();
- if (n == 0) {
- return 0;
- }
- if (path.charAt(0) == '/') {
- return 1;
- }
if (n < 3) {
return 0;
}
@@ -645,10 +622,44 @@ public final class LocalPath implements Comparable<LocalPath> {
return false;
}
- @Override
- public boolean isRoot(LocalPath localPath) {
- // Return true for Unix paths for testing
- return localPath.path.equals("/");
+ private String getUnixRoot() {
+ String value = UNIX_ROOT.get();
+ if (value == null) {
+ String jvmFlag = "bazel.windows_unix_root";
+ value = determineUnixRoot(jvmFlag);
+ if (value == null) {
+ throw new IllegalStateException(
+ String.format(
+ "\"%1$s\" JVM flag is not set. Use the --host_jvm_args flag or export the "
+ + "BAZEL_SH environment variable. For example "
+ + "\"--host_jvm_args=-D%1$s=c:/tools/msys64\" or "
+ + "\"set BAZEL_SH=c:/tools/msys64/usr/bin/bash.exe\".",
+ jvmFlag));
+ }
+ if (getDriveStrLength(value) != 3) {
+ throw new IllegalStateException(
+ String.format("\"%s\" must be an absolute path, got: \"%s\"", jvmFlag, value));
+ }
+ value = value.replace('\\', '/');
+ if (value.length() > 3 && value.endsWith("/")) {
+ value = value.substring(0, value.length() - 1);
+ }
+ UNIX_ROOT.set(value);
+ }
+ return value;
+ }
+
+ private String determineUnixRoot(String jvmArgName) {
+ // Get the path from a JVM flag, if specified.
+ String path = System.getProperty(jvmArgName);
+ if (path == null) {
+ return null;
+ }
+ path = path.trim();
+ if (path.isEmpty()) {
+ return null;
+ }
+ return path;
}
}
@@ -674,8 +685,7 @@ public final class LocalPath implements Comparable<LocalPath> {
private static int removeRelativePaths(String[] segments, int starti) {
int segmentCount = 0;
int shift = starti;
- int n = segments.length;
- for (int i = starti; i < n; ++i) {
+ for (int i = starti; i < segments.length; ++i) {
String segment = segments[i];
switch (segment) {
case ".":
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/Path.java b/src/main/java/com/google/devtools/build/lib/vfs/Path.java
index b09b713cd1..1d3947dcdc 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/Path.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/Path.java
@@ -39,11 +39,7 @@ import java.util.IdentityHashMap;
import java.util.Objects;
/**
- * NOTE: This class is superseded by {@link LocalPath}. You should prefer storing simple strings /
- * path fragments, then converting to a {@link LocalPath} only when you need to do local file system
- * access. A migration is underway.
- *
- * <p>Instances of this class represent pathnames, forming a tree structure to implement sharing of
+ * Instances of this class represent pathnames, forming a tree structure to implement sharing of
* common prefixes (parent directory names). A node in these trees is something like foo, bar, ..,
* ., or /. If the instance is not a root path, it will have a parent path. A path can also have
* children, which are indexed by name in a map.
@@ -427,10 +423,6 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
return builder.toString();
}
- public LocalPath getLocalPath() {
- return LocalPath.create(getPathString());
- }
-
@Override
public void repr(SkylarkPrinter printer) {
printer.append(getPathString());
@@ -508,7 +500,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public boolean exists(FileSystem fileSystem) {
- return fileSystem.exists(this.getLocalPath(), true);
+ return fileSystem.exists(this, true);
}
/** Prefer to use {@link #exists(FileSystem, Symlinks)}. */
@@ -527,7 +519,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* link is dereferenced until a file other than a symbolic link is found
*/
public boolean exists(FileSystem fileSystem, Symlinks followSymlinks) {
- return fileSystem.exists(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.exists(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #getDirectoryEntries(FileSystem)}. */
@@ -548,7 +540,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public Collection<Path> getDirectoryEntries(FileSystem fileSystem)
throws IOException, FileNotFoundException {
- Collection<String> entries = fileSystem.getDirectoryEntries(this.getLocalPath());
+ Collection<String> entries = fileSystem.getDirectoryEntries(this);
Collection<Path> result = new ArrayList<>(entries.size());
for (String entry : entries) {
result.add(getChild(entry));
@@ -576,7 +568,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public Collection<Dirent> readdir(FileSystem fileSystem, Symlinks followSymlinks)
throws IOException {
- return fileSystem.readdir(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.readdir(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #stat(FileSystem)}. */
@@ -596,7 +588,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* {@code FileStatus} are called.
*/
public FileStatus stat(FileSystem fileSystem) throws IOException {
- return fileSystem.stat(this.getLocalPath(), true);
+ return fileSystem.stat(this, true);
}
/** Prefer to use {@link #statNullable(FileSystem)}. */
@@ -628,7 +620,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public FileStatus statNullable(FileSystem fileSystem, Symlinks symlinks) {
- return fileSystem.statNullable(this.getLocalPath(), symlinks.toBoolean());
+ return fileSystem.statNullable(this, symlinks.toBoolean());
}
/** Prefer to use {@link #stat(FileSystem, Symlinks)}. */
@@ -650,7 +642,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* {@code FileStatus} are called
*/
public FileStatus stat(FileSystem fileSystem, Symlinks followSymlinks) throws IOException {
- return fileSystem.stat(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.stat(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #statIfFound(FileSystem)}. */
@@ -668,7 +660,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public FileStatus statIfFound(FileSystem fileSystem) throws IOException {
- return fileSystem.statIfFound(this.getLocalPath(), true);
+ return fileSystem.statIfFound(this, true);
}
/** Prefer to use {@link #statIfFound(FileSystem, Symlinks)}. */
@@ -688,7 +680,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* link is dereferenced until a file other than a symbolic link is found
*/
public FileStatus statIfFound(FileSystem fileSystem, Symlinks followSymlinks) throws IOException {
- return fileSystem.statIfFound(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.statIfFound(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #isDirectory()} (FileSystem)}. */
@@ -704,7 +696,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public boolean isDirectory(FileSystem fileSystem) {
- return fileSystem.isDirectory(this.getLocalPath(), true);
+ return fileSystem.isDirectory(this, true);
}
/** Prefer to use {@link #isDirectory(FileSystem, Symlinks)}. */
@@ -723,7 +715,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* link is dereferenced until a file other than a symbolic link is found
*/
public boolean isDirectory(FileSystem fileSystem, Symlinks followSymlinks) {
- return fileSystem.isDirectory(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.isDirectory(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #isFile(FileSystem)}. */
@@ -742,7 +734,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* it excludes symbolic links and directories.
*/
public boolean isFile(FileSystem fileSystem) {
- return fileSystem.isFile(this.getLocalPath(), true);
+ return fileSystem.isFile(this, true);
}
/** Prefer to use {@link #isFile(FileSystem, Symlinks)}. */
@@ -764,7 +756,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* link is dereferenced until a file other than a symbolic link is found.
*/
public boolean isFile(FileSystem fileSystem, Symlinks followSymlinks) {
- return fileSystem.isFile(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.isFile(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #isSpecialFile(FileSystem)}. */
@@ -781,7 +773,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public boolean isSpecialFile(FileSystem fileSystem) {
- return fileSystem.isSpecialFile(this.getLocalPath(), true);
+ return fileSystem.isSpecialFile(this, true);
}
/** Prefer to use {@link #isSpecialFile(FileSystem, Symlinks)}. */
@@ -800,7 +792,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* link is dereferenced until a path other than a symbolic link is found.
*/
public boolean isSpecialFile(FileSystem fileSystem, Symlinks followSymlinks) {
- return fileSystem.isSpecialFile(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.isSpecialFile(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #isSymbolicLink(FileSystem)}. */
@@ -816,7 +808,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public boolean isSymbolicLink(FileSystem fileSystem) {
- return fileSystem.isSymbolicLink(this.getLocalPath());
+ return fileSystem.isSymbolicLink(this);
}
/**
@@ -1010,7 +1002,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public OutputStream getOutputStream(FileSystem fileSystem, boolean append)
throws IOException, FileNotFoundException {
- return fileSystem.getOutputStream(this.getLocalPath(), append);
+ return fileSystem.getOutputStream(this, append);
}
/** Prefer to use {@link #createDirectory(FileSystem)}. */
@@ -1031,7 +1023,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the directory creation failed for any reason
*/
public boolean createDirectory(FileSystem fileSystem) throws IOException {
- return fileSystem.createDirectory(this.getLocalPath());
+ return fileSystem.createDirectory(this);
}
/** Prefer to use {@link #createSymbolicLink(FileSystem, Path)}. */
@@ -1052,7 +1044,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public void createSymbolicLink(FileSystem fileSystem, Path target) throws IOException {
checkSameFilesystem(target);
- fileSystem.createSymbolicLink(this.getLocalPath(), target.asFragment().getPathString());
+ fileSystem.createSymbolicLink(this, target.asFragment());
}
/** Prefer to use {@link #createSymbolicLink(FileSystem, PathFragment)}. */
@@ -1072,7 +1064,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the creation of the symbolic link was unsuccessful for any reason
*/
public void createSymbolicLink(FileSystem fileSystem, PathFragment target) throws IOException {
- fileSystem.createSymbolicLink(this.getLocalPath(), target.getPathString());
+ fileSystem.createSymbolicLink(this, target);
}
/** Prefer to use {@link #readSymbolicLink(FileSystem)}. */
@@ -1097,7 +1089,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* could not be read for any reason
*/
public PathFragment readSymbolicLink(FileSystem fileSystem) throws IOException {
- return PathFragment.create(fileSystem.readSymbolicLink(this.getLocalPath()));
+ return fileSystem.readSymbolicLink(this);
}
/** Prefer to use {@link #readSymbolicLinkUnchecked(FileSystem)}. */
@@ -1118,7 +1110,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* could not be read for any reason
*/
public PathFragment readSymbolicLinkUnchecked(FileSystem fileSystem) throws IOException {
- return PathFragment.create(fileSystem.readSymbolicLinkUnchecked(this.getLocalPath()));
+ return fileSystem.readSymbolicLinkUnchecked(this);
}
/** Prefer to use {@link #createHardLink(FileSystem, Path)}. */
@@ -1137,7 +1129,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if there was an error executing {@link FileSystem#createHardLink}
*/
public void createHardLink(FileSystem fileSystem, Path link) throws IOException {
- fileSystem.createHardLink(link.getLocalPath(), this.getLocalPath());
+ fileSystem.createHardLink(link, this);
}
/** Prefer to use {@link #resolveSymbolicLinks(FileSystem)}. */
@@ -1158,7 +1150,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* example, the path does not exist)
*/
public Path resolveSymbolicLinks(FileSystem fileSystem) throws IOException {
- return fileSystem.getPath(fileSystem.resolveSymbolicLinks(this.getLocalPath()).getPathString());
+ return fileSystem.resolveSymbolicLinks(this);
}
/** Prefer to use {@link #renameTo(FileSystem, Path)}. */
@@ -1181,7 +1173,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public void renameTo(FileSystem fileSystem, Path target) throws IOException {
checkSameFilesystem(target);
- fileSystem.renameTo(this.getLocalPath(), target.getLocalPath());
+ fileSystem.renameTo(this, target);
}
/** Prefer to use {@link #getFileSize(FileSystem)}. */
@@ -1202,7 +1194,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the file's metadata could not be read, or some other error occurred
*/
public long getFileSize(FileSystem fileSystem) throws IOException, FileNotFoundException {
- return fileSystem.getFileSize(this.getLocalPath(), true);
+ return fileSystem.getFileSize(this, true);
}
/** Prefer to use {@link #getFileSize(FileSystem, Symlinks)}. */
@@ -1227,7 +1219,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public long getFileSize(FileSystem fileSystem, Symlinks followSymlinks)
throws IOException, FileNotFoundException {
- return fileSystem.getFileSize(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.getFileSize(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #delete(FileSystem)}. */
@@ -1248,7 +1240,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the deletion failed but the file was present prior to the call
*/
public boolean delete(FileSystem fileSystem) throws IOException {
- return fileSystem.delete(this.getLocalPath());
+ return fileSystem.delete(this);
}
/** Prefer to use {@link #getLastModifiedTime(FileSystem)}. */
@@ -1270,7 +1262,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the operation failed for any reason
*/
public long getLastModifiedTime(FileSystem fileSystem) throws IOException {
- return fileSystem.getLastModifiedTime(this.getLocalPath(), true);
+ return fileSystem.getLastModifiedTime(this, true);
}
/** Prefer to use {@link #getLastModifiedTime(FileSystem, Symlinks)}. */
@@ -1295,7 +1287,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public long getLastModifiedTime(FileSystem fileSystem, Symlinks followSymlinks)
throws IOException {
- return fileSystem.getLastModifiedTime(this.getLocalPath(), followSymlinks.toBoolean());
+ return fileSystem.getLastModifiedTime(this, followSymlinks.toBoolean());
}
/** Prefer to use {@link #setLastModifiedTime(FileSystem, long)}. */
@@ -1320,7 +1312,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the modification time for the file could not be set for any reason
*/
public void setLastModifiedTime(FileSystem fileSystem, long newTime) throws IOException {
- fileSystem.setLastModifiedTime(this.getLocalPath(), newTime);
+ fileSystem.setLastModifiedTime(this, newTime);
}
/** Prefer to use {@link #getxattr(FileSystem, String)}. */
@@ -1337,7 +1329,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public byte[] getxattr(FileSystem fileSystem, String name) throws IOException {
- return fileSystem.getxattr(this.getLocalPath(), name);
+ return fileSystem.getxattr(this, name);
}
/** Prefer to use {@link #getFastDigest(FileSystem)}. */
@@ -1354,7 +1346,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* Path.
*/
public byte[] getFastDigest(FileSystem fileSystem) throws IOException {
- return fileSystem.getFastDigest(this.getLocalPath());
+ return fileSystem.getFastDigest(this);
}
/** Prefer to use {@link #isValidDigest(FileSystem, byte[])}. */
@@ -1389,7 +1381,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the digest could not be computed for any reason
*/
public byte[] getDigest(FileSystem fileSystem) throws IOException {
- return fileSystem.getDigest(this.getLocalPath());
+ return fileSystem.getDigest(this);
}
/** Prefer to use {@link #getDigest(FileSystem, HashFunction)}. */
@@ -1409,7 +1401,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the digest could not be computed for any reason
*/
public byte[] getDigest(FileSystem fileSystem, HashFunction hashFunction) throws IOException {
- return fileSystem.getDigest(this.getLocalPath(), hashFunction);
+ return fileSystem.getDigest(this, hashFunction);
}
/** Prefer to use {@link #getInputStream(FileSystem)}. */
@@ -1428,7 +1420,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the file was not found or could not be opened for reading
*/
public InputStream getInputStream(FileSystem fileSystem) throws IOException {
- return fileSystem.getInputStream(this.getLocalPath());
+ return fileSystem.getInputStream(this);
}
/**
@@ -1458,7 +1450,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* encountered, or the file's metadata could not be read
*/
public boolean isWritable(FileSystem fileSystem) throws IOException, FileNotFoundException {
- return fileSystem.isWritable(this.getLocalPath());
+ return fileSystem.isWritable(this);
}
/** Prefer to use {@link #setReadable(FileSystem, boolean)}. */
@@ -1480,7 +1472,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public void setReadable(FileSystem fileSystem, boolean readable)
throws IOException, FileNotFoundException {
- fileSystem.setReadable(this.getLocalPath(), readable);
+ fileSystem.setReadable(this, readable);
}
/** Prefer to use {@link #setWritable(FileSystem, boolean)}. */
@@ -1504,7 +1496,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public void setWritable(FileSystem fileSystem, boolean writable)
throws IOException, FileNotFoundException {
- fileSystem.setWritable(this.getLocalPath(), writable);
+ fileSystem.setWritable(this, writable);
}
/** Prefer to use {@link #isExecutable(FileSystem)}. */
@@ -1525,7 +1517,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if some other I/O error occurred
*/
public boolean isExecutable(FileSystem fileSystem) throws IOException, FileNotFoundException {
- return fileSystem.isExecutable(this.getLocalPath());
+ return fileSystem.isExecutable(this);
}
/** Prefer to use {@link #isReadable(FileSystem)}. */
@@ -1546,7 +1538,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if some other I/O error occurred
*/
public boolean isReadable(FileSystem fileSystem) throws IOException, FileNotFoundException {
- return fileSystem.isReadable(this.getLocalPath());
+ return fileSystem.isReadable(this);
}
/** Prefer to use {@link #setExecutable(FileSystem, boolean)}. */
@@ -1568,7 +1560,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
*/
public void setExecutable(FileSystem fileSystem, boolean executable)
throws IOException, FileNotFoundException {
- fileSystem.setExecutable(this.getLocalPath(), executable);
+ fileSystem.setExecutable(this, executable);
}
/** Prefer to use {@link #chmod(FileSystem, int)}. */
@@ -1591,7 +1583,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
* @throws IOException if the metadata change failed, for example because of permissions
*/
public void chmod(FileSystem fileSystem, int mode) throws IOException {
- fileSystem.chmod(this.getLocalPath(), mode);
+ fileSystem.chmod(this, mode);
}
/** Prefer to use {@link #prefetchPackageAsync(FileSystem, int)}. */
@@ -1601,7 +1593,7 @@ public class Path implements Comparable<Path>, Serializable, SkylarkPrintable {
}
public void prefetchPackageAsync(FileSystem fileSystem, int maxDirs) {
- fileSystem.prefetchPackageAsync(this.getLocalPath(), maxDirs);
+ fileSystem.prefetchPackageAsync(this, maxDirs);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/PathTrie.java b/src/main/java/com/google/devtools/build/lib/vfs/PathTrie.java
new file mode 100644
index 0000000000..fd783c5929
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/vfs/PathTrie.java
@@ -0,0 +1,82 @@
+// Copyright 2014 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 com.google.devtools.build.lib.vfs;
+
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A trie that operates on path segments.
+ *
+ * @param <T> the type of the values.
+ */
+@ThreadCompatible
+public class PathTrie<T> {
+ @SuppressWarnings("unchecked")
+ private static class Node<T> {
+ private Node() {
+ children = new HashMap<>();
+ }
+
+ private T value;
+ private Map<String, Node<T>> children;
+ }
+
+ private final Node<T> root;
+
+ public PathTrie() {
+ root = new Node<T>();
+ }
+
+ /**
+ * Puts a value in the trie.
+ *
+ * @param key must be an absolute path.
+ */
+ public void put(PathFragment key, T value) {
+ Preconditions.checkArgument(key.isAbsolute(), "PathTrie only accepts absolute paths as keys.");
+ Node<T> current = root;
+ for (String segment : key.getSegments()) {
+ current.children.putIfAbsent(segment, new Node<T>());
+ current = current.children.get(segment);
+ }
+ current.value = value;
+ }
+
+ /**
+ * Gets a value from the trie. If there is an entry with the same key, that will be returned,
+ * otherwise, the value corresponding to the key that matches the longest prefix of the input.
+ */
+ public T get(PathFragment key) {
+ Node<T> current = root;
+ T lastValue = current.value;
+
+ for (String segment : key.getSegments()) {
+ if (current.children.containsKey(segment)) {
+ current = current.children.get(segment);
+ // Track the values of increasing matching prefixes.
+ if (current.value != null) {
+ lastValue = current.value;
+ }
+ } else {
+ // We've reached the longest prefix, no further to go.
+ break;
+ }
+ }
+
+ return lastValue;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java
index 0eab17c93f..bfcc4f97e0 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java
@@ -17,21 +17,20 @@ import java.io.IOException;
import java.io.OutputStream;
/**
- * An abstract partial implementation of FileSystem for read-only implementations.
+ * An abstract partial implementation of FileSystem for read-only
+ * implementations.
*
* <p>Any ReadonlyFileSystem does not support the following:
- *
* <ul>
- * <li>{@link #createDirectory(LocalPath)}
- * <li>{@link #createSymbolicLink(LocalPath, String)}
- * <li>{@link #delete(LocalPath)}
- * <li>{@link #getOutputStream(LocalPath)}
- * <li>{@link #renameTo(LocalPath, LocalPath)}
- * <li>{@link #setExecutable(LocalPath, boolean)}
- * <li>{@link #setLastModifiedTime(LocalPath, long)}
- * <li>{@link #setWritable(LocalPath, boolean)}
+ * <li>{@link #createDirectory(Path)}</li>
+ * <li>{@link #createSymbolicLink(Path, PathFragment)}</li>
+ * <li>{@link #delete(Path)}</li>
+ * <li>{@link #getOutputStream(Path)}</li>
+ * <li>{@link #renameTo(Path, Path)}</li>
+ * <li>{@link #setExecutable(Path, boolean)}</li>
+ * <li>{@link #setLastModifiedTime(Path, long)}</li>
+ * <li>{@link #setWritable(Path, boolean)}</li>
* </ul>
- *
* The above calls will always result in an {@link IOException}.
*/
public abstract class ReadonlyFileSystem extends AbstractFileSystem {
@@ -47,37 +46,37 @@ public abstract class ReadonlyFileSystem extends AbstractFileSystem {
}
@Override
- protected OutputStream getOutputStream(LocalPath path, boolean append) throws IOException {
+ protected OutputStream getOutputStream(Path path, boolean append) throws IOException {
throw modificationException();
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
throw modificationException();
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
throw modificationException();
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) {
+ protected void setExecutable(Path path, boolean executable) {
throw new UnsupportedOperationException("setExecutable");
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return false;
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return false;
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
return false;
}
@@ -87,32 +86,32 @@ public abstract class ReadonlyFileSystem extends AbstractFileSystem {
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
+ public boolean createDirectory(Path path) throws IOException {
throw modificationException();
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
throw modificationException();
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
+ public void renameTo(Path sourcePath, Path targetPath) throws IOException {
throw modificationException();
}
@Override
- public boolean delete(LocalPath path) throws IOException {
+ public boolean delete(Path path) throws IOException {
throw modificationException();
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
throw modificationException();
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException {
throw modificationException();
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystemWithCustomStat.java b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystemWithCustomStat.java
index 46e058cb67..de5daca181 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystemWithCustomStat.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystemWithCustomStat.java
@@ -31,37 +31,37 @@ public abstract class ReadonlyFileSystemWithCustomStat extends AbstractFileSyste
}
@Override
- protected OutputStream getOutputStream(LocalPath path, boolean append) throws IOException {
+ protected OutputStream getOutputStream(Path path, boolean append) throws IOException {
throw modificationException();
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
throw modificationException();
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
throw modificationException();
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) {
+ protected void setExecutable(Path path, boolean executable) {
throw new UnsupportedOperationException("setExecutable");
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return false;
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return false;
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
return false;
}
@@ -71,33 +71,33 @@ public abstract class ReadonlyFileSystemWithCustomStat extends AbstractFileSyste
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
+ public boolean createDirectory(Path path) throws IOException {
throw modificationException();
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
throw modificationException();
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException {
throw modificationException();
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
+ public void renameTo(Path sourcePath, Path targetPath) throws IOException {
throw modificationException();
}
@Override
- public boolean delete(LocalPath path) throws IOException {
+ public boolean delete(Path path) throws IOException {
throw modificationException();
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
throw modificationException();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java
index 504aa93700..824e71dc69 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java
@@ -15,14 +15,12 @@
package com.google.devtools.build.lib.vfs;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import com.google.devtools.build.lib.concurrent.ThreadSafety;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -44,21 +42,12 @@ import javax.annotation.Nullable;
* are not currently supported.
*/
@ThreadSafety.ThreadSafe
-public final class UnionFileSystem extends FileSystem {
+public class UnionFileSystem extends FileSystem {
- private static class FileSystemAndPrefix {
- final LocalPath prefix;
- final FileSystem fileSystem;
-
- public FileSystemAndPrefix(LocalPath prefix, FileSystem fileSystem) {
- this.prefix = prefix;
- this.fileSystem = fileSystem;
- }
- }
-
- // List of file systems and their mappings, sorted by prefix length descending.
- private final List<FileSystemAndPrefix> fileSystems;
- private final FileSystem rootFileSystem;
+ // Prefix trie index, allowing children to easily inherit prefix mappings
+ // of their parents.
+ // This does not currently handle unicode filenames.
+ private final PathTrie<FileSystem> pathDelegate;
// True if the file path is case-sensitive on all the FileSystem
// or False if they are all case-insensitive, otherwise error.
@@ -70,35 +59,30 @@ public final class UnionFileSystem extends FileSystem {
* @param prefixMapping map of path prefixes to {@link FileSystem}s
* @param rootFileSystem root for default requests; i.e. mapping of "/"
*/
- public UnionFileSystem(Map<LocalPath, FileSystem> prefixMapping, FileSystem rootFileSystem) {
+ public UnionFileSystem(Map<PathFragment, FileSystem> prefixMapping, FileSystem rootFileSystem) {
super();
Preconditions.checkNotNull(prefixMapping);
Preconditions.checkNotNull(rootFileSystem);
Preconditions.checkArgument(rootFileSystem != this, "Circular root filesystem.");
Preconditions.checkArgument(
- !prefixMapping.containsKey(LocalPath.EMPTY),
+ !prefixMapping.containsKey(PathFragment.EMPTY_FRAGMENT),
"Attempted to specify an explicit root prefix mapping; "
+ "please use the rootFileSystem argument instead.");
- this.fileSystems = new ArrayList<>();
- this.rootFileSystem = rootFileSystem;
+ this.pathDelegate = new PathTrie<>();
this.isCaseSensitive = rootFileSystem.isFilePathCaseSensitive();
- for (Map.Entry<LocalPath, FileSystem> prefix : prefixMapping.entrySet()) {
+ for (Map.Entry<PathFragment, FileSystem> prefix : prefixMapping.entrySet()) {
FileSystem delegate = prefix.getValue();
Preconditions.checkArgument(
delegate.isFilePathCaseSensitive() == this.isCaseSensitive,
"The case sensitiveness of FileSystem are different in UnionFileSystem");
- LocalPath prefixPath = prefix.getKey();
+ PathFragment prefixPath = prefix.getKey();
// Extra slash prevents within-directory mappings, which Path can't handle.
- fileSystems.add(new FileSystemAndPrefix(prefixPath, delegate));
+ pathDelegate.put(prefixPath, delegate);
}
- // Order by length descending. This ensures that more specific mapping takes precedence
- // when we try to find the file system of a given path.
- Comparator<FileSystemAndPrefix> comparator =
- Comparator.comparing(f -> f.prefix.getPathString().length());
- fileSystems.sort(comparator.reversed());
+ pathDelegate.put(PathFragment.ROOT_FRAGMENT, rootFileSystem);
}
/**
@@ -108,24 +92,19 @@ public final class UnionFileSystem extends FileSystem {
* @param path the {@link Path} to map to a filesystem
* @throws IllegalArgumentException if no delegate exists for the path
*/
- FileSystem getDelegate(LocalPath path) {
+ protected FileSystem getDelegate(Path path) {
Preconditions.checkNotNull(path);
- FileSystem delegate = null;
- // Linearly iterate over each mapped file system and find the one that handles this path.
- // For small number of mappings, this will be more efficient than using a trie
- for (FileSystemAndPrefix fileSystemAndPrefix : this.fileSystems) {
- if (path.startsWith(fileSystemAndPrefix.prefix)) {
- delegate = fileSystemAndPrefix.fileSystem;
- break;
- }
- }
- return delegate != null ? delegate : rootFileSystem;
+ FileSystem immediateDelegate = pathDelegate.get(path.asFragment());
+
+ // Should never actually happen if the root delegate is present.
+ Preconditions.checkNotNull(immediateDelegate, "No delegate filesystem exists for %s", path);
+ return immediateDelegate;
}
// Associates the path with the root of the given delegate filesystem.
// Necessary to avoid null pointer problems inside of the delegates.
- LocalPath adjustPath(LocalPath path, FileSystem delegate) {
- return path;
+ protected Path adjustPath(Path path, FileSystem delegate) {
+ return delegate.getPath(path.asFragment());
}
/**
@@ -135,20 +114,20 @@ public final class UnionFileSystem extends FileSystem {
* @param path {@link Path} to the symbolic link
*/
@Override
- protected String readSymbolicLink(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLink(Path path) throws IOException {
Preconditions.checkNotNull(path);
FileSystem delegate = getDelegate(path);
return delegate.readSymbolicLink(adjustPath(path, delegate));
}
@Override
- protected String resolveOneLink(LocalPath path) throws IOException {
+ protected PathFragment resolveOneLink(Path path) throws IOException {
Preconditions.checkNotNull(path);
FileSystem delegate = getDelegate(path);
return delegate.resolveOneLink(adjustPath(path, delegate));
}
- private void checkModifiable(LocalPath path) {
+ private void checkModifiable(Path path) {
if (!supportsModifications(path)) {
throw new UnsupportedOperationException(
String.format("Modifications to this %s are disabled.", getClass().getSimpleName()));
@@ -156,21 +135,21 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
FileSystem delegate = getDelegate(path);
path = adjustPath(path, delegate);
return delegate.supportsModifications(path);
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
FileSystem delegate = getDelegate(path);
path = adjustPath(path, delegate);
return delegate.supportsSymbolicLinksNatively(path);
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
FileSystem delegate = getDelegate(path);
path = adjustPath(path, delegate);
return delegate.supportsHardLinksNatively(path);
@@ -182,7 +161,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- public String getFileSystemType(LocalPath path) {
+ public String getFileSystemType(Path path) {
try {
path = internalResolveSymlink(path);
} catch (IOException e) {
@@ -193,14 +172,14 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hashFunction) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.getDigest(adjustPath(path, delegate), hashFunction);
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
+ public boolean createDirectory(Path path) throws IOException {
checkModifiable(path);
// When creating the exact directory that is mapped,
// create it on both the parent's delegate and the path's delegate.
@@ -213,7 +192,7 @@ public final class UnionFileSystem extends FileSystem {
// ls / ("foo" would be missing if not created on the parent)
// ls /foo (would fail if foo weren't also present on the child)
FileSystem delegate = getDelegate(path);
- LocalPath parent = path.getParentDirectory();
+ Path parent = path.getParentDirectory();
if (parent != null) {
parent = internalResolveSymlink(parent);
FileSystem parentDelegate = getDelegate(parent);
@@ -227,28 +206,28 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected long getFileSize(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getFileSize(Path path, boolean followSymlinks) throws IOException {
path = followSymlinks ? internalResolveSymlink(path) : path;
FileSystem delegate = getDelegate(path);
return delegate.getFileSize(adjustPath(path, delegate), false);
}
@Override
- public boolean delete(LocalPath path) throws IOException {
+ public boolean delete(Path path) throws IOException {
checkModifiable(path);
FileSystem delegate = getDelegate(path);
return delegate.delete(adjustPath(path, delegate));
}
@Override
- protected long getLastModifiedTime(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getLastModifiedTime(Path path, boolean followSymlinks) throws IOException {
path = followSymlinks ? internalResolveSymlink(path) : path;
FileSystem delegate = getDelegate(path);
return delegate.getLastModifiedTime(adjustPath(path, delegate), false);
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
path = internalResolveSymlink(path);
checkModifiable(path);
FileSystem delegate = getDelegate(path);
@@ -256,14 +235,14 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean isSymbolicLink(LocalPath path) {
+ protected boolean isSymbolicLink(Path path) {
FileSystem delegate = getDelegate(path);
path = adjustPath(path, delegate);
return delegate.isSymbolicLink(path);
}
@Override
- protected boolean isDirectory(LocalPath path, boolean followSymlinks) {
+ protected boolean isDirectory(Path path, boolean followSymlinks) {
try {
path = followSymlinks ? internalResolveSymlink(path) : path;
} catch (IOException e) {
@@ -274,7 +253,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean isFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isFile(Path path, boolean followSymlinks) {
try {
path = followSymlinks ? internalResolveSymlink(path) : path;
} catch (IOException e) {
@@ -285,7 +264,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean isSpecialFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isSpecialFile(Path path, boolean followSymlinks) {
try {
path = followSymlinks ? internalResolveSymlink(path) : path;
} catch (IOException e) {
@@ -296,7 +275,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
checkModifiable(linkPath);
if (!supportsSymbolicLinksNatively(linkPath)) {
throw new UnsupportedOperationException(
@@ -308,7 +287,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean exists(LocalPath path, boolean followSymlinks) {
+ protected boolean exists(Path path, boolean followSymlinks) {
try {
path = followSymlinks ? internalResolveSymlink(path) : path;
} catch (IOException e) {
@@ -319,7 +298,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus stat(Path path, boolean followSymlinks) throws IOException {
path = followSymlinks ? internalResolveSymlink(path) : path;
FileSystem delegate = getDelegate(path);
return delegate.stat(adjustPath(path, delegate), false);
@@ -329,7 +308,7 @@ public final class UnionFileSystem extends FileSystem {
// UnixFileSystem implements statNullable and stat as separate codepaths.
// More generally, we wish to delegate all filesystem operations.
@Override
- protected FileStatus statNullable(LocalPath path, boolean followSymlinks) {
+ protected FileStatus statNullable(Path path, boolean followSymlinks) {
try {
path = followSymlinks ? internalResolveSymlink(path) : path;
} catch (IOException e) {
@@ -341,7 +320,7 @@ public final class UnionFileSystem extends FileSystem {
@Override
@Nullable
- protected FileStatus statIfFound(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
path = followSymlinks ? internalResolveSymlink(path) : path;
FileSystem delegate = getDelegate(path);
return delegate.statIfFound(adjustPath(path, delegate), false);
@@ -354,30 +333,35 @@ public final class UnionFileSystem extends FileSystem {
* @param path the {@link Path} whose children are to be retrieved
*/
@Override
- protected Collection<String> getDirectoryEntries(LocalPath path) throws IOException {
+ protected Collection<String> getDirectoryEntries(Path path) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
- LocalPath resolvedPath = adjustPath(path, delegate);
- return delegate.getDirectoryEntries(resolvedPath);
+ Path resolvedPath = adjustPath(path, delegate);
+ Collection<Path> entries = resolvedPath.getDirectoryEntries();
+ Collection<String> result = Lists.newArrayListWithCapacity(entries.size());
+ for (Path entry : entries) {
+ result.add(entry.getBaseName());
+ }
+ return result;
}
// No need for the more complex logic of getDirectoryEntries; it calls it implicitly.
@Override
- protected Collection<Dirent> readdir(LocalPath path, boolean followSymlinks) throws IOException {
+ protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
path = followSymlinks ? internalResolveSymlink(path) : path;
FileSystem delegate = getDelegate(path);
return delegate.readdir(adjustPath(path, delegate), false);
}
@Override
- protected boolean isReadable(LocalPath path) throws IOException {
+ protected boolean isReadable(Path path) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.isReadable(adjustPath(path, delegate));
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
path = internalResolveSymlink(path);
checkModifiable(path);
FileSystem delegate = getDelegate(path);
@@ -385,7 +369,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean isWritable(LocalPath path) throws IOException {
+ protected boolean isWritable(Path path) throws IOException {
if (!supportsModifications(path)) {
return false;
}
@@ -395,7 +379,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
checkModifiable(path);
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
@@ -403,14 +387,14 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected boolean isExecutable(LocalPath path) throws IOException {
+ protected boolean isExecutable(Path path) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.isExecutable(adjustPath(path, delegate));
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) throws IOException {
+ protected void setExecutable(Path path, boolean executable) throws IOException {
path = internalResolveSymlink(path);
checkModifiable(path);
FileSystem delegate = getDelegate(path);
@@ -418,28 +402,28 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.getFastDigest(adjustPath(path, delegate), hashFunction);
}
@Override
- public byte[] getxattr(LocalPath path, String name) throws IOException {
+ public byte[] getxattr(Path path, String name) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.getxattr(adjustPath(path, delegate), name);
}
@Override
- protected InputStream getInputStream(LocalPath path) throws IOException {
+ protected InputStream getInputStream(Path path) throws IOException {
path = internalResolveSymlink(path);
FileSystem delegate = getDelegate(path);
return delegate.getInputStream(adjustPath(path, delegate));
}
@Override
- protected OutputStream getOutputStream(LocalPath path, boolean append) throws IOException {
+ protected OutputStream getOutputStream(Path path, boolean append) throws IOException {
path = internalResolveSymlink(path);
checkModifiable(path);
FileSystem delegate = getDelegate(path);
@@ -447,7 +431,7 @@ public final class UnionFileSystem extends FileSystem {
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
+ public void renameTo(Path sourcePath, Path targetPath) throws IOException {
sourcePath = internalResolveSymlink(sourcePath);
FileSystem sourceDelegate = getDelegate(sourcePath);
if (!sourceDelegate.supportsModifications(sourcePath)) {
@@ -474,14 +458,13 @@ public final class UnionFileSystem extends FileSystem {
} else {
// Copy across filesystems, then delete.
// copyFile throws on failure, so delete will never be reached if it fails.
- FileSystemUtils.copyFile(sourceDelegate, sourcePath, targetDelegate, targetPath);
+ FileSystemUtils.copyFile(sourcePath, targetPath);
sourceDelegate.delete(sourcePath);
}
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
- throws IOException {
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath) throws IOException {
checkModifiable(linkPath);
originalPath = internalResolveSymlink(originalPath);
@@ -497,9 +480,9 @@ public final class UnionFileSystem extends FileSystem {
adjustPath(linkPath, linkDelegate), adjustPath(originalPath, originalDelegate));
}
- private LocalPath internalResolveSymlink(LocalPath path) throws IOException {
+ private Path internalResolveSymlink(Path path) throws IOException {
while (isSymbolicLink(path)) {
- String pathFragment = resolveOneLink(path);
+ PathFragment pathFragment = resolveOneLink(path);
path = path.getRelative(pathFragment);
}
return path;
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java
index 333c3bb1e3..93c4eb294c 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java
@@ -17,7 +17,7 @@ import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.vfs.FileStatus;
-import com.google.devtools.build.lib.vfs.LocalPath;
+import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
/**
@@ -201,5 +201,6 @@ public abstract class InMemoryContentInfo implements FileStatus {
* @param targetPath where the inode is relocated.
* @throws IOException
*/
- protected void movedTo(LocalPath targetPath) throws IOException {}
+ protected void movedTo(Path targetPath) throws IOException {
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
index 0d3594263a..ff6d88a387 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
@@ -21,7 +21,6 @@ import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileAccessException;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.ByteArrayInputStream;
@@ -49,8 +48,7 @@ import javax.annotation.Nullable;
@ThreadSafe
public class InMemoryFileSystem extends FileSystem {
- private final LocalPath scopeRoot;
- private final int scopeSegmentCount;
+ private final PathFragment scopeRoot;
private final Clock clock;
// The root inode (a directory).
@@ -84,7 +82,6 @@ public class InMemoryFileSystem extends FileSystem {
this.clock = clock;
this.rootInode = newRootInode(clock);
this.scopeRoot = null;
- this.scopeSegmentCount = 0;
}
/**
@@ -92,8 +89,7 @@ public class InMemoryFileSystem extends FileSystem {
* not below scopeRoot is considered to be out of scope.
*/
public InMemoryFileSystem(Clock clock, PathFragment scopeRoot) {
- this.scopeRoot = scopeRoot != null ? LocalPath.create(scopeRoot.getPathString()) : null;
- this.scopeSegmentCount = scopeRoot != null ? scopeRoot.segmentCount() : 0;
+ this.scopeRoot = scopeRoot;
this.clock = clock;
this.rootInode = newRootInode(clock);
}
@@ -113,7 +109,7 @@ public class InMemoryFileSystem extends FileSystem {
* @param normalizedPath input path, expected to be normalized such that all ".." and "." segments
* are removed (with the exception of a possible prefix sequence of contiguous ".." segments)
*/
- private boolean inScope(int parentDepth, LocalPath normalizedPath) {
+ private boolean inScope(int parentDepth, PathFragment normalizedPath) {
if (scopeRoot == null) {
return true;
} else if (normalizedPath.isAbsolute()) {
@@ -124,7 +120,7 @@ public class InMemoryFileSystem extends FileSystem {
// unnecessary re-delegation back into the same FS. we're choosing to forgo that
// optimization under the assumption that such scenarios are rare and unimportant to
// overall performance. We can always enhance this if needed.
- return parentDepth - leadingParentReferences(normalizedPath) >= scopeSegmentCount;
+ return parentDepth - leadingParentReferences(normalizedPath) >= scopeRoot.segmentCount();
}
}
@@ -135,14 +131,12 @@ public class InMemoryFileSystem extends FileSystem {
* <p>Example allowed inputs: "/absolute/path", "relative/path", "../../relative/path". Example
* disallowed inputs: "/absolute/path/../path2", "relative/../path", "../relative/../p".
*/
- private int leadingParentReferences(LocalPath normalizedPath) {
+ private int leadingParentReferences(PathFragment normalizedPath) {
int leadingParentReferences = 0;
- for (String segment : normalizedPath.split()) {
- if (segment.equals("..")) {
- ++leadingParentReferences;
- } else {
- break;
- }
+ for (int i = 0;
+ i < normalizedPath.segmentCount() && normalizedPath.getSegment(i).equals("..");
+ i++) {
+ leadingParentReferences++;
}
return leadingParentReferences;
}
@@ -251,10 +245,11 @@ public class InMemoryFileSystem extends FileSystem {
}
/**
- * Returns a new IOException for the error. The exception message contains 'path', and is
- * consistent with the messages returned by c.g.common.unix.FilesystemUtils.
+ * Returns a new IOException for the error. The exception message
+ * contains 'path', and is consistent with the messages returned by
+ * c.g.common.unix.FilesystemUtils.
*/
- public IOException exception(LocalPath path) throws IOException {
+ public IOException exception(Path path) throws IOException {
String m = path + " (" + message + ")";
if (this == EACCES) {
throw new FileAccessExceptionWithError(m, this);
@@ -272,44 +267,48 @@ public class InMemoryFileSystem extends FileSystem {
* <p>If <code>/proc/mounts</code> does not exist return {@code "inmemoryfs"}.
*/
@Override
- public String getFileSystemType(LocalPath path) {
- return exists(path.getRelative("/proc/mounts")) ? super.getFileSystemType(path) : "inmemoryfs";
+ public String getFileSystemType(Path path) {
+ return path.getRelative("/proc/mounts").exists() ? super.getFileSystemType(path) : "inmemoryfs";
}
- /**
- * ************************************************************************** "Kernel" primitives:
- * basic directory lookup primitives, in topological order.
+ /****************************************************************************
+ * "Kernel" primitives: basic directory lookup primitives, in topological
+ * order.
*/
/**
- * Unlinks the entry 'child' from its existing parent directory 'dir'. Dual to insert. This
- * succeeds even if 'child' names a non-empty directory; we need that for renameTo. 'child' must
- * be a member of its parent directory, however. Fails if the directory was read-only.
+ * Unlinks the entry 'child' from its existing parent directory 'dir'. Dual to
+ * insert. This succeeds even if 'child' names a non-empty directory; we need
+ * that for renameTo. 'child' must be a member of its parent directory,
+ * however. Fails if the directory was read-only.
*/
- private void unlink(InMemoryDirectoryInfo dir, String child, LocalPath errorPath)
+ private void unlink(InMemoryDirectoryInfo dir, String child, Path errorPath)
throws IOException {
if (!dir.isWritable()) { throw Error.EACCES.exception(errorPath); }
dir.removeChild(child);
}
/**
- * Inserts inode 'childInode' into the existing directory 'dir' under the specified 'name'. Dual
- * to unlink. Fails if the directory was read-only.
+ * Inserts inode 'childInode' into the existing directory 'dir' under the
+ * specified 'name'. Dual to unlink. Fails if the directory was read-only.
*/
- private void insert(
- InMemoryDirectoryInfo dir, String child, InMemoryContentInfo childInode, LocalPath errorPath)
+ private void insert(InMemoryDirectoryInfo dir, String child,
+ InMemoryContentInfo childInode, Path errorPath)
throws IOException {
if (!dir.isWritable()) { throw Error.EACCES.exception(errorPath); }
dir.addChild(child, childInode);
}
/**
- * Given an existing directory 'dir', looks up 'name' within it and returns its inode. Assumes the
- * file exists, unless 'create', in which case it will try to create it. May fail with ENOTDIR,
- * EACCES, ENOENT. Error messages will be reported against file 'path'.
+ * Given an existing directory 'dir', looks up 'name' within it and returns
+ * its inode. Assumes the file exists, unless 'create', in which case it will
+ * try to create it. May fail with ENOTDIR, EACCES, ENOENT. Error messages
+ * will be reported against file 'path'.
*/
- private InMemoryContentInfo directoryLookup(
- InMemoryContentInfo dir, String name, boolean create, LocalPath path) throws IOException {
+ private InMemoryContentInfo directoryLookup(InMemoryContentInfo dir,
+ String name,
+ boolean create,
+ Path path) throws IOException {
if (!dir.isDirectory()) { throw Error.ENOTDIR.exception(path); }
InMemoryDirectoryInfo imdi = (InMemoryDirectoryInfo) dir;
if (!imdi.isExecutable()) { throw Error.EACCES.exception(path); }
@@ -337,8 +336,7 @@ public class InMemoryFileSystem extends FileSystem {
*
* <p>May fail with ENOTDIR, ENOENT, EACCES, ELOOP.
*/
- private synchronized InMemoryContentInfo pathWalk(LocalPath path, boolean create)
- throws IOException {
+ private synchronized InMemoryContentInfo pathWalk(Path path, boolean create) throws IOException {
// Implementation note: This is where we check for out-of-scope symlinks and
// trigger re-delegation to another file system accordingly. This code handles
// both absolute and relative symlinks. Some assumptions we make: First, only
@@ -350,7 +348,8 @@ public class InMemoryFileSystem extends FileSystem {
// and it may only appear as part of a contiguous prefix sequence.
Stack<String> stack = new Stack<>();
- for (LocalPath p = path; p != null && !p.isRoot(); p = p.getParentDirectory()) {
+ PathFragment rootPathFragment = getRootDirectory().asFragment();
+ for (Path p = path; !p.asFragment().equals(rootPathFragment); p = p.getParentDirectory()) {
stack.push(p.getBaseName());
}
@@ -367,7 +366,7 @@ public class InMemoryFileSystem extends FileSystem {
// ENOENT on last segment with 'create' => create a new file.
InMemoryContentInfo child = directoryLookup(inode, name, create && stack.isEmpty(), path);
if (child.isSymbolicLink()) {
- LocalPath linkTarget = ((InMemoryLinkInfo) child).getNormalizedLinkContent();
+ PathFragment linkTarget = ((InMemoryLinkInfo) child).getNormalizedLinkContent();
if (!inScope(parentDepth, linkTarget)) {
throw Error.ENOENT.exception(path);
}
@@ -378,9 +377,8 @@ public class InMemoryFileSystem extends FileSystem {
if (traversals > MAX_TRAVERSALS) {
throw Error.ELOOP.exception(path);
}
- List<String> linkSegments = linkTarget.split();
- for (int ii = linkSegments.size() - 1; ii >= 0; --ii) {
- stack.push(linkSegments.get(ii)); // Note this may include ".." segments.
+ for (int ii = linkTarget.segmentCount() - 1; ii >= 0; --ii) {
+ stack.push(linkTarget.getSegment(ii)); // Note this may include ".." segments.
}
} else {
inode = child;
@@ -390,11 +388,12 @@ public class InMemoryFileSystem extends FileSystem {
}
/**
- * Given 'path', returns the existing directory inode it designates, following symbolic links.
+ * Given 'path', returns the existing directory inode it designates,
+ * following symbolic links.
*
* <p>May fail with ENOTDIR, or any exception from pathWalk.
*/
- private InMemoryDirectoryInfo getDirectory(LocalPath path) throws IOException {
+ private InMemoryDirectoryInfo getDirectory(Path path) throws IOException {
InMemoryContentInfo dirInfo = pathWalk(path, false);
if (!dirInfo.isDirectory()) {
throw Error.ENOTDIR.exception(path);
@@ -404,28 +403,28 @@ public class InMemoryFileSystem extends FileSystem {
}
/**
- * Helper method for stat, scopeLimitedStat: lock the internal state and return the path's (no
- * symlink-followed) stat if the path's parent directory is within scope, else return an "out of
- * scope" reference to the path's parent directory (which will presumably be re-delegated to
- * another FS).
+ * Helper method for stat, scopeLimitedStat: lock the internal state and return the
+ * path's (no symlink-followed) stat if the path's parent directory is within scope,
+ * else return an "out of scope" reference to the path's parent directory (which will
+ * presumably be re-delegated to another FS).
*/
- private synchronized InMemoryContentInfo getNoFollowStatOrOutOfScopeParent(LocalPath path)
- throws IOException {
+ private synchronized InMemoryContentInfo getNoFollowStatOrOutOfScopeParent(Path path)
+ throws IOException {
InMemoryDirectoryInfo dirInfo = getDirectory(path.getParentDirectory());
return directoryLookup(dirInfo, path.getBaseName(), /*create=*/ false, path);
}
/**
- * Given 'path', returns the existing inode it designates, optionally following symbolic links.
- * Analogous to UNIX stat(2)/lstat(2), except that it returns a mutable inode we can modify
- * directly.
+ * Given 'path', returns the existing inode it designates, optionally
+ * following symbolic links. Analogous to UNIX stat(2)/lstat(2), except that
+ * it returns a mutable inode we can modify directly.
*/
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (followSymlinks) {
return scopeLimitedStat(path, true);
} else {
- if (path.isRoot()) {
+ if (path.equals(getRootDirectory())) {
return rootInode;
} else {
return getNoFollowStatOrOutOfScopeParent(path);
@@ -435,7 +434,7 @@ public class InMemoryFileSystem extends FileSystem {
@Override
@Nullable
- public FileStatus statIfFound(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
try {
return stat(path, followSymlinks);
} catch (IOException e) {
@@ -453,12 +452,12 @@ public class InMemoryFileSystem extends FileSystem {
* Version of stat that returns an inode if the input path stays entirely within this file
* system's scope, otherwise throws.
*/
- private InMemoryContentInfo scopeLimitedStat(LocalPath path, boolean followSymlinks)
+ private InMemoryContentInfo scopeLimitedStat(Path path, boolean followSymlinks)
throws IOException {
if (followSymlinks) {
return pathWalk(path, false);
} else {
- if (path.isRoot()) {
+ if (path.equals(getRootDirectory())) {
return rootInode;
} else {
return getNoFollowStatOrOutOfScopeParent(path);
@@ -466,20 +465,21 @@ public class InMemoryFileSystem extends FileSystem {
}
}
- /**
- * ************************************************************************** FileSystem methods
+ /****************************************************************************
+ * FileSystem methods
*/
/**
- * This is a helper routing for {@link #resolveSymbolicLinks(LocalPath)}, i.e. the "user-mode"
- * routing for canonicalising paths. It is analogous to the code in glibc's realpath(3).
+ * This is a helper routing for {@link #resolveSymbolicLinks(Path)}, i.e.
+ * the "user-mode" routing for canonicalising paths. It is analogous to the
+ * code in glibc's realpath(3).
*
- * <p>Just like realpath, resolveSymbolicLinks requires a quadratic number of directory lookups: n
- * path segments are statted, and each stat requires a linear amount of work in the "kernel"
- * routine.
+ * <p>Just like realpath, resolveSymbolicLinks requires a quadratic number of
+ * directory lookups: n path segments are statted, and each stat requires a
+ * linear amount of work in the "kernel" routine.
*/
@Override
- protected String resolveOneLink(LocalPath path) throws IOException {
+ protected PathFragment resolveOneLink(Path path) throws IOException {
// Beware, this seemingly simple code belies the complex specification of
// FileSystem.resolveOneLink().
InMemoryContentInfo status = scopeLimitedStat(path, false);
@@ -487,7 +487,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isDirectory(LocalPath path, boolean followSymlinks) {
+ protected boolean isDirectory(Path path, boolean followSymlinks) {
try {
return stat(path, followSymlinks).isDirectory();
} catch (IOException e) {
@@ -496,7 +496,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isFile(Path path, boolean followSymlinks) {
try {
return stat(path, followSymlinks).isFile();
} catch (IOException e) {
@@ -505,7 +505,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isSpecialFile(LocalPath path, boolean followSymlinks) {
+ protected boolean isSpecialFile(Path path, boolean followSymlinks) {
try {
return stat(path, followSymlinks).isSpecialFile();
} catch (IOException e) {
@@ -514,7 +514,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isSymbolicLink(LocalPath path) {
+ protected boolean isSymbolicLink(Path path) {
try {
return stat(path, false).isSymbolicLink();
} catch (IOException e) {
@@ -523,7 +523,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean exists(LocalPath path, boolean followSymlinks) {
+ protected boolean exists(Path path, boolean followSymlinks) {
try {
stat(path, followSymlinks);
return true;
@@ -533,13 +533,13 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isReadable(LocalPath path) throws IOException {
+ protected boolean isReadable(Path path) throws IOException {
InMemoryContentInfo status = scopeLimitedStat(path, true);
return status.isReadable();
}
@Override
- protected void setReadable(LocalPath path, boolean readable) throws IOException {
+ protected void setReadable(Path path, boolean readable) throws IOException {
synchronized (this) {
InMemoryContentInfo status = scopeLimitedStat(path, true);
status.setReadable(readable);
@@ -547,13 +547,13 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isWritable(LocalPath path) throws IOException {
+ protected boolean isWritable(Path path) throws IOException {
InMemoryContentInfo status = scopeLimitedStat(path, true);
return status.isWritable();
}
@Override
- public void setWritable(LocalPath path, boolean writable) throws IOException {
+ public void setWritable(Path path, boolean writable) throws IOException {
InMemoryContentInfo status;
synchronized (this) {
status = scopeLimitedStat(path, true);
@@ -562,13 +562,14 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected boolean isExecutable(LocalPath path) throws IOException {
+ protected boolean isExecutable(Path path) throws IOException {
InMemoryContentInfo status = scopeLimitedStat(path, true);
return status.isExecutable();
}
@Override
- protected void setExecutable(LocalPath path, boolean executable) throws IOException {
+ protected void setExecutable(Path path, boolean executable)
+ throws IOException {
synchronized (this) {
InMemoryContentInfo status = scopeLimitedStat(path, true);
status.setExecutable(executable);
@@ -576,17 +577,17 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return true;
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return true;
}
@Override
- public boolean supportsHardLinksNatively(LocalPath path) {
+ public boolean supportsHardLinksNatively(Path path) {
return true;
}
@@ -596,8 +597,8 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- public boolean createDirectory(LocalPath path) throws IOException {
- if (path.isRoot()) {
+ public boolean createDirectory(Path path) throws IOException {
+ if (path.equals(getRootDirectory())) {
throw Error.EACCES.exception(path);
}
@@ -623,8 +624,9 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected void createSymbolicLink(LocalPath path, String targetFragment) throws IOException {
- if (path.isRoot()) {
+ protected void createSymbolicLink(Path path, PathFragment targetFragment)
+ throws IOException {
+ if (path.equals(getRootDirectory())) {
throw Error.EACCES.exception(path);
}
@@ -638,7 +640,7 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected String readSymbolicLink(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLink(Path path) throws IOException {
InMemoryContentInfo status = scopeLimitedStat(path, false);
if (status.isSymbolicLink()) {
Preconditions.checkState(status instanceof InMemoryLinkInfo);
@@ -649,12 +651,13 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected long getFileSize(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getFileSize(Path path, boolean followSymlinks)
+ throws IOException {
return stat(path, followSymlinks).getSize();
}
@Override
- protected Collection<String> getDirectoryEntries(LocalPath path) throws IOException {
+ protected Collection<String> getDirectoryEntries(Path path) throws IOException {
synchronized (this) {
InMemoryDirectoryInfo dirInfo = getDirectory(path);
FileStatus status = stat(path, false);
@@ -675,8 +678,8 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- public boolean delete(LocalPath path) throws IOException {
- if (path.isRoot()) {
+ public boolean delete(Path path) throws IOException {
+ if (path.equals(getRootDirectory())) {
throw Error.EBUSY.exception(path);
}
if (!exists(path, false)) { return false; }
@@ -693,12 +696,13 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected long getLastModifiedTime(LocalPath path, boolean followSymlinks) throws IOException {
+ protected long getLastModifiedTime(Path path, boolean followSymlinks)
+ throws IOException {
return stat(path, followSymlinks).getLastModifiedTime();
}
@Override
- public void setLastModifiedTime(LocalPath path, long newTime) throws IOException {
+ public void setLastModifiedTime(Path path, long newTime) throws IOException {
synchronized (this) {
InMemoryContentInfo status = scopeLimitedStat(path, true);
status.setLastModifiedTime(newTime == -1L ? clock.currentTimeMillis() : newTime);
@@ -706,13 +710,13 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected InputStream getInputStream(LocalPath path) throws IOException {
+ protected InputStream getInputStream(Path path) throws IOException {
synchronized (this) {
InMemoryContentInfo status = scopeLimitedStat(path, true);
if (status.isDirectory()) {
throw Error.EISDIR.exception(path);
}
- if (!isReadable(path)) {
+ if (!path.isReadable()) {
throw Error.EACCES.exception(path);
}
Preconditions.checkState(status instanceof FileInfo);
@@ -721,7 +725,7 @@ public class InMemoryFileSystem extends FileSystem {
}
/** Creates a new file at the given path and returns its inode. */
- private InMemoryContentInfo getOrCreateWritableInode(LocalPath path) throws IOException {
+ private InMemoryContentInfo getOrCreateWritableInode(Path path) throws IOException {
// open(WR_ONLY) of a dangling link writes through the link. That means
// that the usual path lookup operations have to behave differently when
// resolving a path with the intent to create it: instead of failing with
@@ -738,7 +742,8 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected OutputStream getOutputStream(LocalPath path, boolean append) throws IOException {
+ protected OutputStream getOutputStream(Path path, boolean append)
+ throws IOException {
synchronized (this) {
InMemoryContentInfo status = getOrCreateWritableInode(path);
return ((FileInfo) status).getOutputStream(append);
@@ -746,11 +751,12 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- public void renameTo(LocalPath sourcePath, LocalPath targetPath) throws IOException {
- if (sourcePath.isRoot()) {
+ public void renameTo(Path sourcePath, Path targetPath)
+ throws IOException {
+ if (sourcePath.equals(getRootDirectory())) {
throw Error.EACCES.exception(sourcePath);
}
- if (targetPath.isRoot()) {
+ if (targetPath.equals(getRootDirectory())) {
throw Error.EACCES.exception(targetPath);
}
synchronized (this) {
@@ -794,11 +800,11 @@ public class InMemoryFileSystem extends FileSystem {
}
@Override
- protected void createFSDependentHardLink(LocalPath linkPath, LocalPath originalPath)
+ protected void createFSDependentHardLink(Path linkPath, Path originalPath)
throws IOException {
// Same check used when creating a symbolic link
- if (originalPath.isRoot()) {
+ if (originalPath.equals(getRootDirectory())) {
throw Error.EACCES.exception(originalPath);
}
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java
index cee3ebd6be..107f319115 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java
@@ -16,7 +16,7 @@ package com.google.devtools.build.lib.vfs.inmemoryfs;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
-import com.google.devtools.build.lib.vfs.LocalPath;
+import com.google.devtools.build.lib.vfs.PathFragment;
/**
* This interface represents a symbolic link to an absolute or relative path,
@@ -25,13 +25,13 @@ import com.google.devtools.build.lib.vfs.LocalPath;
@ThreadSafe @Immutable
class InMemoryLinkInfo extends InMemoryContentInfo {
- private final String linkContent;
- private final LocalPath normalizedLinkContent;
+ private final PathFragment linkContent;
+ private final PathFragment normalizedLinkContent;
- InMemoryLinkInfo(Clock clock, String linkContent) {
+ InMemoryLinkInfo(Clock clock, PathFragment linkContent) {
super(clock);
this.linkContent = linkContent;
- this.normalizedLinkContent = LocalPath.create(linkContent);
+ this.normalizedLinkContent = linkContent.normalize();
}
@Override
@@ -59,16 +59,18 @@ class InMemoryLinkInfo extends InMemoryContentInfo {
return linkContent.toString().length();
}
- /** Returns the content of the symbolic link. */
- String getLinkContent() {
+ /**
+ * Returns the content of the symbolic link.
+ */
+ PathFragment getLinkContent() {
return linkContent;
}
/**
- * Returns the content of the symbolic link, with ".." and "." removed (except for the possibility
- * of necessary ".." segments at the beginning).
+ * Returns the content of the symbolic link, with ".." and "." removed
+ * (except for the possibility of necessary ".." segments at the beginning).
*/
- LocalPath getNormalizedLinkContent() {
+ PathFragment getNormalizedLinkContent() {
return normalizedLinkContent;
}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index c98a6c1f15..af97e27d3d 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -21,7 +21,6 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Path.PathFactory;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -33,11 +32,41 @@ import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.attribute.DosFileAttributes;
import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.annotation.Nullable;
/** File system implementation for Windows. */
@ThreadSafe
public class WindowsFileSystem extends JavaIoFileSystem {
+ // Properties of 8dot3 (DOS-style) short file names:
+ // - they are at most 11 characters long
+ // - they have a prefix (before "~") that is {1..6} characters long, may contain numbers, letters,
+ // "_", even "~", and maybe even more
+ // - they have a "~" after the prefix
+ // - have {1..6} numbers after "~" (according to [1] this is only one digit, but MSDN doesn't
+ // clarify this), the combined length up till this point is at most 8
+ // - they have an optional "." afterwards, and another {0..3} more characters
+ // - just because a path looks like a short name it isn't necessarily one; the user may create
+ // such names and they'd resolve to themselves
+ // [1] https://en.wikipedia.org/wiki/8.3_filename#VFAT_and_Computer-generated_8.3_filenames
+ // bullet point (3) (on 2016-12-05)
+ @VisibleForTesting
+ static final Predicate<String> SHORT_NAME_MATCHER =
+ new Predicate<String>() {
+ private final Pattern pattern = Pattern.compile("^(.{1,6})~([0-9]{1,6})(\\..{0,3}){0,1}");
+
+ @Override
+ public boolean apply(@Nullable String input) {
+ Matcher m = pattern.matcher(input);
+ return input.length() <= 12
+ && m.matches()
+ && m.groupCount() >= 2
+ && (m.group(1).length() + m.group(2).length()) < 8; // the "~" makes it at most 8
+ }
+ };
+
/** Resolves DOS-style, shortened path names, returning the last segment's long form. */
private static final Function<String, String> WINDOWS_SHORT_PATH_RESOLVER =
path -> {
@@ -85,7 +114,7 @@ public class WindowsFileSystem extends JavaIoFileSystem {
}
String resolvedChild = child;
- if (parent != null && !parent.isRootDirectory() && WindowsShortPath.isShortPath(child)) {
+ if (parent != null && !parent.isRootDirectory() && SHORT_NAME_MATCHER.apply(child)) {
String pathString = parent.getPathString();
if (!pathString.endsWith("/")) {
pathString += "/";
@@ -257,18 +286,18 @@ public class WindowsFileSystem extends JavaIoFileSystem {
}
@Override
- public String getFileSystemType(LocalPath path) {
+ public String getFileSystemType(Path path) {
// TODO(laszlocsomor): implement this properly, i.e. actually query this information from
// somewhere (java.nio.Filesystem? System.getProperty? implement JNI method and use WinAPI?).
return "ntfs";
}
@Override
- protected void createSymbolicLink(LocalPath linkPath, String targetFragment) throws IOException {
- LocalPath targetPath = LocalPath.create(targetFragment);
- if (!targetPath.isAbsolute()) {
- targetPath = linkPath.getParentDirectory().getRelative(targetPath);
- }
+ protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
+ Path targetPath =
+ targetFragment.isAbsolute()
+ ? getPath(targetFragment)
+ : linkPath.getParentDirectory().getRelative(targetFragment);
try {
java.nio.file.Path link = getIoFile(linkPath).toPath();
java.nio.file.Path target = getIoFile(targetPath).toPath();
@@ -288,7 +317,7 @@ public class WindowsFileSystem extends JavaIoFileSystem {
}
@Override
- public boolean supportsSymbolicLinksNatively(LocalPath path) {
+ public boolean supportsSymbolicLinksNatively(Path path) {
return false;
}
@@ -314,7 +343,7 @@ public class WindowsFileSystem extends JavaIoFileSystem {
}
@Override
- protected FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ protected FileStatus stat(Path path, boolean followSymlinks) throws IOException {
File file = getIoFile(path);
final DosFileAttributes attributes;
try {
@@ -373,7 +402,7 @@ public class WindowsFileSystem extends JavaIoFileSystem {
}
@Override
- protected boolean isDirectory(LocalPath path, boolean followSymlinks) {
+ protected boolean isDirectory(Path path, boolean followSymlinks) {
if (!followSymlinks) {
try {
if (isJunction(getIoFile(path))) {
diff --git a/src/test/java/com/google/devtools/build/lib/actions/DigestUtilsTest.java b/src/test/java/com/google/devtools/build/lib/actions/DigestUtilsTest.java
index 6fee2c1061..259e0f2088 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/DigestUtilsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/DigestUtilsTest.java
@@ -25,7 +25,6 @@ import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystem.HashFunction;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.IOException;
@@ -59,7 +58,7 @@ public class DigestUtilsTest {
FileSystem myfs =
new InMemoryFileSystem(BlazeClock.instance(), hf) {
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hashFunction) throws IOException {
try {
barrierLatch.countDown();
readyLatch.countDown();
@@ -73,8 +72,7 @@ public class DigestUtilsTest {
}
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction)
- throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
return fastDigest ? super.getDigest(path, hashFunction) : null;
}
};
@@ -133,7 +131,7 @@ public class DigestUtilsTest {
FileSystem myFS =
new InMemoryFileSystem(BlazeClock.instance(), hf) {
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction)
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction)
throws IOException {
// Digest functions have more than 3 bytes, usually at least 16.
return malformed;
@@ -141,7 +139,6 @@ public class DigestUtilsTest {
};
Path path = myFS.getPath("/file");
FileSystemUtils.writeContentAsLatin1(path, "a");
-
byte[] result = DigestUtils.getDigestOrFail(path, 1);
assertThat(result).isEqualTo(path.getDigest());
assertThat(result).isNotSameAs(malformed);
@@ -224,14 +221,13 @@ public class DigestUtilsTest {
FileSystem tracingFileSystem =
new InMemoryFileSystem(BlazeClock.instance()) {
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction)
- throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
getFastDigestCounter.incrementAndGet();
return null;
}
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hashFunction) throws IOException {
getDigestCounter.incrementAndGet();
return super.getDigest(path, hashFunction);
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisWithIOExceptionsTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisWithIOExceptionsTest.java
index b7711aaa8d..67d9b6254a 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisWithIOExceptionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisWithIOExceptionsTest.java
@@ -19,7 +19,7 @@ import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
+import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.IOException;
import java.util.function.Function;
@@ -30,15 +30,15 @@ import org.junit.runners.JUnit4;
/** {@link AnalysisTestCase} with custom filesystem that can throw on stat if desired. */
@RunWith(JUnit4.class)
public class AnalysisWithIOExceptionsTest extends AnalysisTestCase {
- private static final Function<LocalPath, String> NULL_FUNCTION = (path) -> null;
+ private static final Function<Path, String> NULL_FUNCTION = (path) -> null;
- private Function<LocalPath, String> crashMessage = NULL_FUNCTION;
+ private Function<Path, String> crashMessage = NULL_FUNCTION;
@Override
protected FileSystem createFileSystem() {
return new InMemoryFileSystem(BlazeClock.instance()) {
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
String crash = crashMessage.apply(path);
if (crash != null) {
throw new IOException(crash);
diff --git a/src/test/java/com/google/devtools/build/lib/exec/SingleBuildFileCacheTest.java b/src/test/java/com/google/devtools/build/lib/exec/SingleBuildFileCacheTest.java
index 023b41e57c..f9d0372e0a 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/SingleBuildFileCacheTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/SingleBuildFileCacheTest.java
@@ -24,7 +24,6 @@ import com.google.devtools.build.lib.actions.DigestOfDirectoryException;
import com.google.devtools.build.lib.testutil.Suite;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.protobuf.ByteString;
@@ -55,23 +54,23 @@ public class SingleBuildFileCacheTest {
public final void setUp() throws Exception {
calls = new HashMap<>();
md5Overrides = new HashMap<>();
- fs =
- new InMemoryFileSystem() {
- @Override
- protected InputStream getInputStream(LocalPath path) throws IOException {
- int c = calls.containsKey(path.toString()) ? calls.get(path.toString()) : 0;
- c++;
- calls.put(path.toString(), c);
- return super.getInputStream(path);
- }
-
- @Override
- protected byte[] getDigest(LocalPath path, HashFunction hf) throws IOException {
- assertThat(hf).isEqualTo(HashFunction.MD5);
- byte[] override = md5Overrides.get(path.getPathString());
- return override != null ? override : super.getDigest(path, hf);
- }
- };
+ fs = new InMemoryFileSystem() {
+ @Override
+ protected InputStream getInputStream(Path path) throws IOException {
+ int c = calls.containsKey(path.toString())
+ ? calls.get(path.toString()) : 0;
+ c++;
+ calls.put(path.toString(), c);
+ return super.getInputStream(path);
+ }
+
+ @Override
+ protected byte[] getDigest(Path path, HashFunction hf) throws IOException {
+ assertThat(hf).isEqualTo(HashFunction.MD5);
+ byte[] override = md5Overrides.get(path.getPathString());
+ return override != null ? override : super.getDigest(path, hf);
+ }
+ };
underTest = new SingleBuildFileCache("/", fs);
Path root = fs.getRootDirectory();
Path file = root.getChild("empty");
diff --git a/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
index 7f1f342d5e..bbb8be7e82 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
@@ -28,7 +28,6 @@ import com.google.devtools.build.lib.packages.util.PackageFactoryApparatus;
import com.google.devtools.build.lib.packages.util.PackageFactoryTestBase;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.testutil.TestUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
@@ -1000,7 +999,7 @@ public class PackageFactoryTest extends PackageFactoryTestBase {
scratch.file("/e/BUILD", "sh_library(name = 'e', data = glob(['*.txt']))");
Path parentDir = buildFile.getParentDirectory();
scratch.file("/e/data.txt");
- throwOnReaddir = LocalPath.create(parentDir.getPathString());
+ throwOnReaddir = parentDir;
try {
packages.createPackage("e", buildFile);
} catch (NoSuchPackageException expected) {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryTestBase.java b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryTestBase.java
index fa5e7605ac..eb614fc49c 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryTestBase.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryTestBase.java
@@ -39,7 +39,6 @@ import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.FileNotFoundException;
@@ -81,7 +80,7 @@ public abstract class PackageFactoryTestBase {
protected abstract PackageFactoryApparatus createPackageFactoryApparatus();
- protected LocalPath throwOnReaddir = null;
+ protected Path throwOnReaddir = null;
protected static AttributeMap attributes(Rule rule) {
return RawAttributeMapper.of(rule);
@@ -123,8 +122,7 @@ public abstract class PackageFactoryTestBase {
FileSystem fs =
new InMemoryFileSystem() {
@Override
- public Collection<Dirent> readdir(LocalPath path, boolean followSymlinks)
- throws IOException {
+ public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
if (path.equals(throwOnReaddir)) {
throw new FileNotFoundException(path.getPathString());
}
diff --git a/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java b/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
index 9f84f73a57..184f22201b 100644
--- a/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
@@ -25,7 +25,6 @@ import com.google.devtools.build.lib.skyframe.TransitiveTargetKey;
import com.google.devtools.build.lib.skyframe.TransitiveTargetValue;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -49,16 +48,15 @@ public class IOExceptionsTest extends PackageLoadingTestCase {
private static final String FS_ROOT = "/fsg";
- private static final Function<LocalPath, String> NULL_FUNCTION =
- new Function<LocalPath, String>() {
- @Override
- @Nullable
- public String apply(LocalPath path) {
- return null;
- }
- };
+ private static final Function<Path, String> NULL_FUNCTION = new Function<Path, String>() {
+ @Override
+ @Nullable
+ public String apply(Path path) {
+ return null;
+ }
+ };
- private Function<LocalPath, String> crashMessage = NULL_FUNCTION;
+ private Function<Path, String> crashMessage = NULL_FUNCTION;
@Before
public final void initializeVisitor() throws Exception {
@@ -84,7 +82,7 @@ public class IOExceptionsTest extends PackageLoadingTestCase {
protected FileSystem createFileSystem() {
return new InMemoryFileSystem(BlazeClock.instance(), PathFragment.create(FS_ROOT)) {
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
String crash = crashMessage.apply(path);
if (crash != null) {
throw new IOException(crash);
@@ -99,16 +97,15 @@ public class IOExceptionsTest extends PackageLoadingTestCase {
reporter.removeHandler(failFastHandler); // expect errors
final Path buildPath = scratch.file("pkg/BUILD",
"sh_library(name = 'x')");
- crashMessage =
- new Function<LocalPath, String>() {
- @Override
- public String apply(LocalPath path) {
- if (buildPath.getLocalPath().equals(path)) {
- return "custom crash: " + buildPath;
- }
- return null;
- }
- };
+ crashMessage = new Function<Path, String>() {
+ @Override
+ public String apply(Path path) {
+ if (buildPath.equals(path)) {
+ return "custom crash: " + buildPath;
+ }
+ return null;
+ }
+ };
assertThat(visitTransitively(Label.parseAbsolute("//pkg:x"))).isFalse();
scratch.overwriteFile("pkg/BUILD",
"# another comment to force reload",
@@ -129,16 +126,15 @@ public class IOExceptionsTest extends PackageLoadingTestCase {
"sh_library(name = 'top', deps = ['//pkg:x'])");
final Path buildPath = scratch.file("pkg/BUILD",
"sh_library(name = 'x')");
- crashMessage =
- new Function<LocalPath, String>() {
- @Override
- public String apply(LocalPath path) {
- if (buildPath.getLocalPath().equals(path)) {
- return "custom crash: " + buildPath;
- }
- return null;
- }
- };
+ crashMessage = new Function<Path, String>() {
+ @Override
+ public String apply(Path path) {
+ if (buildPath.equals(path)) {
+ return "custom crash: " + buildPath;
+ }
+ return null;
+ }
+ };
assertThat(visitTransitively(Label.parseAbsolute("//top:top"))).isFalse();
assertContainsEvent("no such package 'pkg'");
// The traditional label visitor does not propagate the original IOException message.
@@ -163,16 +159,15 @@ public class IOExceptionsTest extends PackageLoadingTestCase {
final Path buildPath = scratch.file("top/BUILD",
"sh_library(name = 'x')");
buildPath.getParentDirectory().getRelative("pkg").createDirectory();
- crashMessage =
- new Function<LocalPath, String>() {
- @Override
- public String apply(LocalPath path) {
- if (buildPath.getLocalPath().equals(path)) {
- return "custom crash: " + buildPath;
- }
- return null;
- }
- };
+ crashMessage = new Function<Path, String>() {
+ @Override
+ public String apply(Path path) {
+ if (buildPath.equals(path)) {
+ return "custom crash: " + buildPath;
+ }
+ return null;
+ }
+ };
assertThat(visitTransitively(Label.parseAbsolute("//top/pkg:x"))).isFalse();
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/pkgcache/IncrementalLoadingTest.java b/src/test/java/com/google/devtools/build/lib/pkgcache/IncrementalLoadingTest.java
index 04e41a3c79..6e83bbedca 100644
--- a/src/test/java/com/google/devtools/build/lib/pkgcache/IncrementalLoadingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/pkgcache/IncrementalLoadingTest.java
@@ -48,7 +48,6 @@ import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -77,8 +76,8 @@ import org.junit.runners.JUnit4;
public class IncrementalLoadingTest {
protected PackageCacheTester tester;
- private LocalPath throwOnReaddir = null;
- private LocalPath throwOnStat = null;
+ private Path throwOnReaddir = null;
+ private Path throwOnStat = null;
@Before
public final void createTester() throws Exception {
@@ -86,8 +85,7 @@ public class IncrementalLoadingTest {
FileSystem fs =
new InMemoryFileSystem(clock) {
@Override
- public Collection<Dirent> readdir(LocalPath path, boolean followSymlinks)
- throws IOException {
+ public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
if (path.equals(throwOnReaddir)) {
throw new FileNotFoundException(path.getPathString());
}
@@ -96,7 +94,7 @@ public class IncrementalLoadingTest {
@Nullable
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (path.equals(throwOnStat)) {
throw new IOException("bork " + path.getPathString());
}
@@ -339,7 +337,7 @@ public class IncrementalLoadingTest {
Path buildFile = tester.addFile("e/BUILD", "sh_library(name = 'e', data = glob(['*.txt']))");
Path parentDir = buildFile.getParentDirectory();
tester.addFile("e/data.txt");
- throwOnReaddir = parentDir.getLocalPath();
+ throwOnReaddir = parentDir;
tester.sync();
try {
tester.getTarget("//e:e");
diff --git a/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java b/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
index 1eb87496a4..37a992d405 100644
--- a/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
+++ b/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
@@ -21,7 +21,6 @@ import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryContentInfo;
@@ -42,15 +41,14 @@ public class TargetPatternEvaluatorIOTest extends AbstractTargetPatternEvaluator
private static class Transformer {
@SuppressWarnings("unused")
@Nullable
- public FileStatus stat(FileStatus stat, LocalPath path, boolean followSymlinks)
- throws IOException {
+ public FileStatus stat(FileStatus stat, Path path, boolean followSymlinks) throws IOException {
return stat;
}
@SuppressWarnings("unused")
@Nullable
- public Collection<Dirent> readdir(
- Collection<Dirent> readdir, LocalPath path, boolean followSymlinks) throws IOException {
+ public Collection<Dirent> readdir(Collection<Dirent> readdir, Path path, boolean followSymlinks)
+ throws IOException {
return readdir;
}
}
@@ -61,14 +59,13 @@ public class TargetPatternEvaluatorIOTest extends AbstractTargetPatternEvaluator
protected FileSystem createFileSystem() {
return new InMemoryFileSystem(BlazeClock.instance(), PathFragment.create(FS_ROOT)) {
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
FileStatus defaultResult = super.stat(path, followSymlinks);
return transformer.stat(defaultResult, path, followSymlinks);
}
@Override
- protected Collection<Dirent> readdir(LocalPath path, boolean followSymlinks)
- throws IOException {
+ protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
Collection<Dirent> defaultResult = super.readdir(path, followSymlinks);
return transformer.readdir(defaultResult, path, followSymlinks);
}
@@ -136,7 +133,7 @@ public class TargetPatternEvaluatorIOTest extends AbstractTargetPatternEvaluator
return new Transformer() {
@Nullable
@Override
- public FileStatus stat(FileStatus stat, LocalPath path, boolean followSymlinks)
+ public FileStatus stat(final FileStatus stat, Path path, boolean followSymlinks)
throws IOException {
if (path.getPathString().endsWith(badPathSuffix)) {
return new InMemoryContentInfo(BlazeClock.instance()) {
@@ -203,8 +200,8 @@ public class TargetPatternEvaluatorIOTest extends AbstractTargetPatternEvaluator
return new Transformer() {
@Nullable
@Override
- public Collection<Dirent> readdir(
- Collection<Dirent> readdir, LocalPath path, boolean followSymlinks) throws IOException {
+ public Collection<Dirent> readdir(Collection<Dirent> readdir, Path path,
+ boolean followSymlinks) throws IOException {
if (path.getPathString().endsWith(badPathSuffix)) {
throw new IOException("Path ended in " + badPathSuffix + ", so readdir failed.");
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunctionTest.java
index 289b420eac..68437dbdb3 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunctionTest.java
@@ -26,7 +26,7 @@ import com.google.devtools.build.lib.syntax.SkylarkImport;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
+import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationResult;
@@ -47,9 +47,10 @@ public class ASTFileLookupFunctionTest extends BuildViewTestCase {
boolean statThrowsIoException;
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (statThrowsIoException
- && path.getPathString()
+ && path.asFragment()
+ .getPathString()
.equals("/workspace/tools/build_rules/prelude_" + TestConstants.PRODUCT_NAME)) {
throw new IOException("bork");
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
index de9a9ab594..4004e85b8f 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
@@ -40,7 +40,6 @@ import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.EvaluationResult;
@@ -102,7 +101,7 @@ public class ArtifactFunctionTest extends ArtifactFunctionTestCase {
setupRoot(
new CustomInMemoryFs() {
@Override
- public byte[] getDigest(LocalPath path, HashFunction hf) throws IOException {
+ public byte[] getDigest(Path path, HashFunction hf) throws IOException {
return path.getBaseName().equals("unreadable")
? expectedDigest
: super.getDigest(path, hf);
@@ -159,7 +158,7 @@ public class ArtifactFunctionTest extends ArtifactFunctionTestCase {
setupRoot(
new CustomInMemoryFs() {
@Override
- public byte[] getDigest(LocalPath path, HashFunction hf) throws IOException {
+ public byte[] getDigest(Path path, HashFunction hf) throws IOException {
throw exception;
}
});
@@ -183,7 +182,7 @@ public class ArtifactFunctionTest extends ArtifactFunctionTestCase {
setupRoot(
new CustomInMemoryFs() {
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (path.getBaseName().equals("bad")) {
throw exception;
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
index 6fd4837e1e..ff83c4a4dd 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
@@ -29,7 +29,6 @@ import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
@@ -172,7 +171,7 @@ abstract class ArtifactFunctionTestCase {
/** InMemoryFileSystem that can pretend to do a fast digest. */
protected class CustomInMemoryFs extends InMemoryFileSystem {
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
return fastDigest ? getDigest(path, hashFunction) : null;
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
index ee0f01976d..e28fef3774 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
@@ -52,7 +52,6 @@ import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
@@ -445,7 +444,7 @@ public class FileFunctionTest {
createFsAndRoot(
new CustomInMemoryFs(manualClock) {
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hf) throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hf) throws IOException {
return digest;
}
});
@@ -486,7 +485,7 @@ public class FileFunctionTest {
createFsAndRoot(
new CustomInMemoryFs(manualClock) {
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hf) {
+ protected byte[] getFastDigest(Path path, HashFunction hf) {
return path.getBaseName().equals("unreadable") ? expectedDigest : null;
}
});
@@ -831,7 +830,7 @@ public class FileFunctionTest {
fs =
new CustomInMemoryFs(manualClock) {
@Override
- protected byte[] getDigest(LocalPath path, HashFunction hf) throws IOException {
+ protected byte[] getDigest(Path path, HashFunction hf) throws IOException {
digestCalls.incrementAndGet();
return super.getDigest(path, hf);
}
@@ -896,8 +895,8 @@ public class FileFunctionTest {
// Our custom filesystem says "a" does not exist, so FileFunction shouldn't bother trying to
// think about "a/b". Test for this by having a stat of "a/b" fail with an io error, and
// observing that we don't encounter the error.
- fs.stubStat(path("a").getLocalPath(), null);
- fs.stubStatError(path("a/b").getLocalPath(), new IOException("ouch!"));
+ fs.stubStat(path("a"), null);
+ fs.stubStatError(path("a/b"), new IOException("ouch!"));
assertThat(valueForPath(path("a/b")).exists()).isFalse();
}
@@ -947,7 +946,7 @@ public class FileFunctionTest {
return 0;
}
};
- fs.stubStat(path("a").getLocalPath(), inconsistentParentFileStatus);
+ fs.stubStat(path("a"), inconsistentParentFileStatus);
// Disable fast-path md5 so that we don't try try to md5 the "a" (since it actually physically
// is a directory).
fastDigest = false;
@@ -968,7 +967,7 @@ public class FileFunctionTest {
public void testFilesystemInconsistencies_GetFastDigest() throws Exception {
file("a");
// Our custom filesystem says "a/b" exists but "a" does not exist.
- fs.stubFastDigestError(path("a").getLocalPath(), new IOException("nope"));
+ fs.stubFastDigestError(path("a"), new IOException("nope"));
SequentialBuildDriver driver = makeDriver();
SkyKey skyKey = skyKey("a");
EvaluationResult<FileValue> result =
@@ -986,7 +985,7 @@ public class FileFunctionTest {
createFsAndRoot(
new CustomInMemoryFs(manualClock) {
@Override
- protected boolean isReadable(LocalPath path) throws IOException {
+ protected boolean isReadable(Path path) throws IOException {
if (path.getBaseName().equals("unreadable")) {
throw new IOException("isReadable failed");
}
@@ -1292,7 +1291,7 @@ public class FileFunctionTest {
public void testInjectionOverIOException() throws Exception {
Path foo = file("foo");
SkyKey fooKey = skyKey("foo");
- fs.stubStatError(foo.getLocalPath(), new IOException("bork"));
+ fs.stubStatError(foo, new IOException("bork"));
BuildDriver driver = makeDriver();
EvaluationResult<FileValue> result =
driver.evaluate(
@@ -1307,7 +1306,7 @@ public class FileFunctionTest {
.hasExceptionThat()
.hasMessageThat()
.isEqualTo("bork");
- fs.stubbedStatErrors.remove(foo.getLocalPath());
+ fs.stubbedStatErrors.remove(foo);
differencer.inject(
fileStateSkyKey("foo"),
FileStateValue.create(
@@ -1677,36 +1676,36 @@ public class FileFunctionTest {
private class CustomInMemoryFs extends InMemoryFileSystem {
- private final Map<LocalPath, FileStatus> stubbedStats = Maps.newHashMap();
- private final Map<LocalPath, IOException> stubbedStatErrors = Maps.newHashMap();
- private final Map<LocalPath, IOException> stubbedFastDigestErrors = Maps.newHashMap();
+ private final Map<Path, FileStatus> stubbedStats = Maps.newHashMap();
+ private final Map<Path, IOException> stubbedStatErrors = Maps.newHashMap();
+ private final Map<Path, IOException> stubbedFastDigestErrors = Maps.newHashMap();
public CustomInMemoryFs(ManualClock manualClock) {
super(manualClock);
}
- public void stubFastDigestError(LocalPath path, IOException error) {
+ public void stubFastDigestError(Path path, IOException error) {
stubbedFastDigestErrors.put(path, error);
}
@Override
- protected byte[] getFastDigest(LocalPath path, HashFunction hashFunction) throws IOException {
+ protected byte[] getFastDigest(Path path, HashFunction hashFunction) throws IOException {
if (stubbedFastDigestErrors.containsKey(path)) {
throw stubbedFastDigestErrors.get(path);
}
return fastDigest ? getDigest(path) : null;
}
- public void stubStat(LocalPath path, @Nullable FileStatus stubbedResult) {
+ public void stubStat(Path path, @Nullable FileStatus stubbedResult) {
stubbedStats.put(path, stubbedResult);
}
- public void stubStatError(LocalPath path, IOException error) {
+ public void stubStatError(Path path, IOException error) {
stubbedStatErrors.put(path, error);
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (stubbedStatErrors.containsKey(path)) {
throw stubbedStatErrors.get(path);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
index a57f39526f..eb2d141b1c 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
@@ -48,7 +48,6 @@ import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileStatusWithDigest;
import com.google.devtools.build.lib.vfs.FileStatusWithDigestAdapter;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -808,7 +807,7 @@ public class FilesystemValueCheckerTest {
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (statThrowsRuntimeException) {
throw new RuntimeException("bork");
}
@@ -816,7 +815,7 @@ public class FilesystemValueCheckerTest {
}
@Override
- protected String readSymbolicLink(LocalPath path) throws IOException {
+ protected PathFragment readSymbolicLink(Path path) throws IOException {
if (readlinkThrowsIoException) {
throw new IOException("readlink failed");
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
index 3ac3dc49a6..13acf704e9 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
@@ -43,7 +43,6 @@ import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
@@ -630,7 +629,7 @@ public abstract class GlobFunctionTest {
@Test
public void testResilienceToFilesystemInconsistencies_DirectoryExistence() throws Exception {
// Our custom filesystem says "pkgPath/BUILD" exists but "pkgPath" does not exist.
- fs.stubStat(pkgPath.getLocalPath(), null);
+ fs.stubStat(pkgPath, null);
RootedPath pkgRootedPath = RootedPath.toRootedPath(root, pkgPath);
FileStateValue pkgDirFileStateValue = FileStateValue.create(pkgRootedPath, null);
FileValue pkgDirValue =
@@ -655,7 +654,7 @@ public abstract class GlobFunctionTest {
// Our custom filesystem says directory "pkgPath/foo/bar" contains a subdirectory "wiz" but a
// direct stat on "pkgPath/foo/bar/wiz" says it does not exist.
Path fooBarDir = pkgPath.getRelative("foo/bar");
- fs.stubStat(fooBarDir.getRelative("wiz").getLocalPath(), null);
+ fs.stubStat(fooBarDir.getRelative("wiz"), null);
RootedPath fooBarDirRootedPath = RootedPath.toRootedPath(root, fooBarDir);
SkyValue fooBarDirListingValue =
DirectoryListingStateValue.create(
@@ -684,7 +683,7 @@ public abstract class GlobFunctionTest {
RootedPath.toRootedPath(root, pkgPath.getRelative("foo/bar/wiz/file"));
final FileStatus realStat = fileRootedPath.asPath().stat();
fs.stubStat(
- fileRootedPath.asPath().getLocalPath(),
+ fileRootedPath.asPath(),
new FileStatus() {
@Override
@@ -761,18 +760,18 @@ public abstract class GlobFunctionTest {
private static final class CustomInMemoryFs extends InMemoryFileSystem {
- private Map<LocalPath, FileStatus> stubbedStats = Maps.newHashMap();
+ private Map<Path, FileStatus> stubbedStats = Maps.newHashMap();
public CustomInMemoryFs(ManualClock manualClock) {
super(manualClock);
}
- public void stubStat(LocalPath path, @Nullable FileStatus stubbedResult) {
+ public void stubStat(Path path, @Nullable FileStatus stubbedResult) {
stubbedStats.put(path, stubbedResult);
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (stubbedStats.containsKey(path)) {
return stubbedStats.get(path);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
index 54f23f430d..8773d54825 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
@@ -39,7 +39,6 @@ import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -165,7 +164,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
return 0;
}
};
- fs.stubStat(fooDir.getLocalPath(), inconsistentParentFileStatus);
+ fs.stubStat(fooDir, inconsistentParentFileStatus);
RootedPath pkgRootedPath = RootedPath.toRootedPath(pkgRoot, fooDir);
SkyValue fooDirValue = FileStateValue.create(pkgRootedPath, tsgm);
differencer.inject(ImmutableMap.of(FileStateValue.key(pkgRootedPath), fooDirValue));
@@ -197,7 +196,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
// Our custom filesystem says "foo/bar/baz" does not exist but it also says that "foo/bar"
// has a child directory "baz".
- fs.stubStat(bazDir.getLocalPath(), null);
+ fs.stubStat(bazDir, null);
RootedPath barDirRootedPath = RootedPath.toRootedPath(pkgRoot, barDir);
FileStateValue barDirFileStateValue = FileStateValue.create(barDirRootedPath, tsgm);
FileValue barDirFileValue = FileValue.value(barDirRootedPath, barDirFileStateValue,
@@ -226,7 +225,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
Path fooDir = fooBuildFile.getParentDirectory();
Path barDir = fooDir.getRelative("bar");
scratch.file("foo/bar/baz.sh");
- fs.scheduleMakeUnreadableAfterReaddir(barDir.getLocalPath());
+ fs.scheduleMakeUnreadableAfterReaddir(barDir);
SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
String expectedMessage = "Encountered error 'Directory is not readable'";
@@ -537,7 +536,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
scratch.file("foo/BUILD",
"sh_library(name = 'foo', srcs = ['bar/baz.sh'])");
Path barBuildFile = scratch.file("foo/bar/BUILD");
- fs.stubStatError(barBuildFile.getLocalPath(), new IOException("nope"));
+ fs.stubStatError(barBuildFile, new IOException("nope"));
SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
EvaluationResult<PackageValue> result = SkyframeExecutorTestUtils.evaluate(
getSkyframeExecutor(), skyKey, /*keepGoing=*/false, reporter);
@@ -675,7 +674,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
public void testPackageLoadingErrorOnIOExceptionReadingBuildFile() throws Exception {
Path fooBuildFilePath = scratch.file("foo/BUILD");
IOException exn = new IOException("nope");
- fs.throwExceptionOnGetInputStream(fooBuildFilePath.getLocalPath(), exn);
+ fs.throwExceptionOnGetInputStream(fooBuildFilePath, exn);
SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
EvaluationResult<PackageValue> result = SkyframeExecutorTestUtils.evaluate(
@@ -693,7 +692,7 @@ public class PackageFunctionTest extends BuildViewTestCase {
scratch.file("foo/BUILD", "load('//foo:bzl.bzl', 'x')");
Path fooBzlFilePath = scratch.file("foo/bzl.bzl");
IOException exn = new IOException("nope");
- fs.throwExceptionOnGetInputStream(fooBzlFilePath.getLocalPath(), exn);
+ fs.throwExceptionOnGetInputStream(fooBzlFilePath, exn);
SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
EvaluationResult<PackageValue> result = SkyframeExecutorTestUtils.evaluate(
@@ -740,49 +739,49 @@ public class PackageFunctionTest extends BuildViewTestCase {
}
}
- private final Map<LocalPath, FileStatusOrException> stubbedStats = Maps.newHashMap();
- private final Set<LocalPath> makeUnreadableAfterReaddir = Sets.newHashSet();
- private final Map<LocalPath, IOException> pathsToErrorOnGetInputStream = Maps.newHashMap();
+ private final Map<Path, FileStatusOrException> stubbedStats = Maps.newHashMap();
+ private final Set<Path> makeUnreadableAfterReaddir = Sets.newHashSet();
+ private final Map<Path, IOException> pathsToErrorOnGetInputStream = Maps.newHashMap();
public CustomInMemoryFs(ManualClock manualClock) {
super(manualClock);
}
- public void stubStat(LocalPath path, @Nullable FileStatus stubbedResult) {
+ public void stubStat(Path path, @Nullable FileStatus stubbedResult) {
stubbedStats.put(path, new FileStatusOrException.FileStatusImpl(stubbedResult));
}
- public void stubStatError(LocalPath path, IOException stubbedResult) {
+ public void stubStatError(Path path, IOException stubbedResult) {
stubbedStats.put(path, new FileStatusOrException.ExceptionImpl(stubbedResult));
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (stubbedStats.containsKey(path)) {
return stubbedStats.get(path).get();
}
return super.stat(path, followSymlinks);
}
- public void scheduleMakeUnreadableAfterReaddir(LocalPath path) {
+ public void scheduleMakeUnreadableAfterReaddir(Path path) {
makeUnreadableAfterReaddir.add(path);
}
@Override
- public Collection<Dirent> readdir(LocalPath path, boolean followSymlinks) throws IOException {
+ public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
Collection<Dirent> result = super.readdir(path, followSymlinks);
if (makeUnreadableAfterReaddir.contains(path)) {
- setReadable(path, false);
+ path.setReadable(false);
}
return result;
}
- public void throwExceptionOnGetInputStream(LocalPath path, IOException exn) {
+ public void throwExceptionOnGetInputStream(Path path, IOException exn) {
pathsToErrorOnGetInputStream.put(path, exn);
}
@Override
- protected InputStream getInputStream(LocalPath path) throws IOException {
+ protected InputStream getInputStream(Path path) throws IOException {
IOException exnToThrow = pathsToErrorOnGetInputStream.get(path);
if (exnToThrow != null) {
throw exnToThrow;
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ParallelBuilderTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ParallelBuilderTest.java
index 13f5fa2df3..e271d90237 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ParallelBuilderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ParallelBuilderTest.java
@@ -45,7 +45,6 @@ import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.FileNotFoundException;
@@ -242,59 +241,58 @@ public class ParallelBuilderTest extends TimestampBuilderTestCase {
@Test
public void testUpdateCacheError() throws Exception {
- FileSystem fs =
- new InMemoryFileSystem() {
- @Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
- final FileStatus stat = super.stat(path, followSymlinks);
- if (path.toString().endsWith("/out/foo")) {
- return new FileStatus() {
- private final FileStatus original = stat;
+ FileSystem fs = new InMemoryFileSystem() {
+ @Override
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
+ final FileStatus stat = super.stat(path, followSymlinks);
+ if (path.toString().endsWith("/out/foo")) {
+ return new FileStatus() {
+ private final FileStatus original = stat;
- @Override
- public boolean isSymbolicLink() {
- return original.isSymbolicLink();
- }
+ @Override
+ public boolean isSymbolicLink() {
+ return original.isSymbolicLink();
+ }
- @Override
- public boolean isFile() {
- return original.isFile();
- }
+ @Override
+ public boolean isFile() {
+ return original.isFile();
+ }
- @Override
- public boolean isDirectory() {
- return original.isDirectory();
- }
+ @Override
+ public boolean isDirectory() {
+ return original.isDirectory();
+ }
- @Override
- public boolean isSpecialFile() {
- return original.isSpecialFile();
- }
+ @Override
+ public boolean isSpecialFile() {
+ return original.isSpecialFile();
+ }
- @Override
- public long getSize() throws IOException {
- return original.getSize();
- }
+ @Override
+ public long getSize() throws IOException {
+ return original.getSize();
+ }
- @Override
- public long getNodeId() throws IOException {
- return original.getNodeId();
- }
+ @Override
+ public long getNodeId() throws IOException {
+ return original.getNodeId();
+ }
- @Override
- public long getLastModifiedTime() throws IOException {
- throw new IOException();
- }
+ @Override
+ public long getLastModifiedTime() throws IOException {
+ throw new IOException();
+ }
- @Override
- public long getLastChangeTime() throws IOException {
- return original.getLastChangeTime();
- }
- };
+ @Override
+ public long getLastChangeTime() throws IOException {
+ return original.getLastChangeTime();
}
- return stat;
- }
- };
+ };
+ }
+ return stat;
+ }
+ };
Artifact foo = createDerivedArtifact(fs, "foo");
registerAction(new TestAction(TestAction.NO_EFFECT, emptySet, ImmutableList.of(foo)));
reporter.removeHandler(failFastHandler);
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTest.java
index 8bca6bd55c..63e900f344 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTest.java
@@ -490,7 +490,7 @@ public class SkyframeLabelVisitorTest extends SkyframeLabelVisitorTestCase {
return 0;
}
};
- fs.stubStat(bazDir.getLocalPath(), inconsistentParentFileStatus);
+ fs.stubStat(bazDir, inconsistentParentFileStatus);
Set<Label> labels = ImmutableSet.of(Label.parseAbsolute("//foo:foo"));
getSkyframeExecutor()
.getPackageManager()
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java
index e3c54a55a2..f20cea8a51 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java
@@ -36,8 +36,8 @@ import com.google.devtools.build.lib.pkgcache.TransitivePackageLoader;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
+import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.DelegatingWalkableGraph;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
@@ -240,18 +240,18 @@ abstract public class SkyframeLabelVisitorTestCase extends PackageLoadingTestCas
protected static class CustomInMemoryFs extends InMemoryFileSystem {
- private Map<LocalPath, FileStatus> stubbedStats = Maps.newHashMap();
+ private Map<Path, FileStatus> stubbedStats = Maps.newHashMap();
public CustomInMemoryFs(ManualClock manualClock) {
super(manualClock);
}
- public void stubStat(LocalPath path, @Nullable FileStatus stubbedResult) {
+ public void stubStat(Path path, @Nullable FileStatus stubbedResult) {
stubbedStats.put(path, stubbedResult);
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (stubbedStats.containsKey(path)) {
return stubbedStats.get(path);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunctionTest.java
index 986c5a5038..1e944d22cb 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunctionTest.java
@@ -26,7 +26,6 @@ import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -133,7 +132,7 @@ public class TargetMarkerFunctionTest extends BuildViewTestCase {
reporter.removeHandler(failFastHandler);
scratch.file("a/BUILD", "sh_library(name = 'b/c')");
Path subpackageBuildFile = scratch.file("a/b/BUILD", "sh_library(name = 'c')");
- fs.stubStatIOException(subpackageBuildFile.getLocalPath(), new IOException("nope"));
+ fs.stubStatIOException(subpackageBuildFile, new IOException("nope"));
BuildFileNotFoundException exn =
(BuildFileNotFoundException) getErrorFromTargetValue("//a:b/c");
assertThat(exn).hasMessageThat().contains("nope");
@@ -141,18 +140,18 @@ public class TargetMarkerFunctionTest extends BuildViewTestCase {
private static class CustomInMemoryFs extends InMemoryFileSystem {
- private Map<LocalPath, IOException> stubbedStatExceptions = Maps.newHashMap();
+ private Map<Path, IOException> stubbedStatExceptions = Maps.newHashMap();
public CustomInMemoryFs() {
super(BlazeClock.instance());
}
- public void stubStatIOException(LocalPath path, IOException stubbedResult) {
+ public void stubStatIOException(Path path, IOException stubbedResult) {
stubbedStatExceptions.put(path, stubbedResult);
}
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (stubbedStatExceptions.containsKey(path)) {
throw stubbedStatExceptions.get(path);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
index 1e52a54ec5..3e156beaec 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
@@ -40,7 +40,6 @@ import com.google.devtools.build.lib.actions.util.TestAction.DummyAction;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
-import com.google.devtools.build.lib.vfs.LocalPath;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.EvaluationResult;
@@ -181,7 +180,7 @@ public class TreeArtifactMetadataTest extends ArtifactFunctionTestCase {
setupRoot(
new CustomInMemoryFs() {
@Override
- public FileStatus stat(LocalPath path, boolean followSymlinks) throws IOException {
+ public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (path.getBaseName().equals("one")) {
throw exception;
}
diff --git a/src/test/java/com/google/devtools/build/lib/util/DependencySetWindowsTest.java b/src/test/java/com/google/devtools/build/lib/util/DependencySetWindowsTest.java
index be410fdf6f..d4a079db94 100644
--- a/src/test/java/com/google/devtools/build/lib/util/DependencySetWindowsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/util/DependencySetWindowsTest.java
@@ -38,13 +38,11 @@ public class DependencySetWindowsTest {
@Test
public void dotDParser_windowsPaths() throws Exception {
- Path dotd =
- scratch.file(
- "C:/tmp/foo.d",
- "bazel-out/hello-lib/cpp/hello-lib.o: \\",
- " cpp/hello-lib.cc cpp/hello-lib.h c:\\mingw\\include\\stdio.h \\",
- " c:\\mingw\\include\\_mingw.h \\",
- " c:\\mingw\\lib\\gcc\\mingw32\\4.8.1\\include\\stdarg.h");
+ Path dotd = scratch.file("/tmp/foo.d",
+ "bazel-out/hello-lib/cpp/hello-lib.o: \\",
+ " cpp/hello-lib.cc cpp/hello-lib.h c:\\mingw\\include\\stdio.h \\",
+ " c:\\mingw\\include\\_mingw.h \\",
+ " c:\\mingw\\lib\\gcc\\mingw32\\4.8.1\\include\\stdarg.h");
Set<Path> expected = Sets.newHashSet(
root.getRelative("cpp/hello-lib.cc"),
@@ -58,11 +56,9 @@ public class DependencySetWindowsTest {
@Test
public void dotDParser_windowsPathsWithSpaces() throws Exception {
- Path dotd =
- scratch.file(
- "C:/tmp/foo.d",
- "bazel-out/hello-lib/cpp/hello-lib.o: \\",
- "C:\\Program\\ Files\\ (x86)\\LLVM\\stddef.h");
+ Path dotd = scratch.file("/tmp/foo.d",
+ "bazel-out/hello-lib/cpp/hello-lib.o: \\",
+ "C:\\Program\\ Files\\ (x86)\\LLVM\\stddef.h");
assertThat(newDependencySet().read(dotd).getDependencies())
.containsExactlyElementsIn(
Sets.newHashSet(fileSystem.getPath("C:/Program Files (x86)/LLVM/stddef.h")));
@@ -73,14 +69,12 @@ public class DependencySetWindowsTest {
// This is (slightly simplified) actual output from clang. Yes, clang will happily mix
// forward slashes and backslashes in a single path, not to mention using backslashes as
// separators next to backslashes as escape characters.
- Path dotd =
- scratch.file(
- "C:/tmp/foo.d",
- "bazel-out/hello-lib/cpp/hello-lib.o: \\",
- "cpp/hello-lib.cc cpp/hello-lib.h /mingw/include\\stdio.h \\",
- "/mingw/include\\_mingw.h \\",
- "C:\\Program\\ Files\\ (x86)\\LLVM\\bin\\..\\lib\\clang\\3.5.0\\include\\stddef.h \\",
- "C:\\Program\\ Files\\ (x86)\\LLVM\\bin\\..\\lib\\clang\\3.5.0\\include\\stdarg.h");
+ Path dotd = scratch.file("/tmp/foo.d",
+ "bazel-out/hello-lib/cpp/hello-lib.o: \\",
+ "cpp/hello-lib.cc cpp/hello-lib.h /mingw/include\\stdio.h \\",
+ "/mingw/include\\_mingw.h \\",
+ "C:\\Program\\ Files\\ (x86)\\LLVM\\bin\\..\\lib\\clang\\3.5.0\\include\\stddef.h \\",
+ "C:\\Program\\ Files\\ (x86)\\LLVM\\bin\\..\\lib\\clang\\3.5.0\\include\\stdarg.h");
Set<Path> expected = Sets.newHashSet(
root.getRelative("cpp/hello-lib.cc"),
@@ -99,8 +93,10 @@ public class DependencySetWindowsTest {
Path file2 = fileSystem.getPath("C:/blah/blah/genhello/hello.h");
Path file2DiffCase = fileSystem.getPath("C:/Blah/blah/Genhello/hello.h");
String filename = "hello.o";
- Path dotd =
- scratch.file("C:/tmp/foo.d", filename + ": \\", " " + file1 + " \\", " " + file2 + " ");
+ Path dotd = scratch.file("/tmp/foo.d",
+ filename + ": \\",
+ " " + file1 + " \\",
+ " " + file2 + " ");
assertThat(newDependencySet().read(dotd).getDependencies())
.containsExactly(file1, file2DiffCase);
}
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/FileSystemTest.java b/src/test/java/com/google/devtools/build/lib/vfs/FileSystemTest.java
index 09ac79eec6..278a288dda 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/FileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/FileSystemTest.java
@@ -379,7 +379,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicFileLinkExists() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xFile);
assertThat(someLink.exists()).isTrue();
assertThat(someLink.statIfFound()).isNotNull();
@@ -389,7 +389,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicFileLinkIsSymbolicLink() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xFile);
assertThat(someLink.isSymbolicLink()).isTrue();
}
@@ -398,7 +398,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicFileLinkIsFile() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xFile);
assertThat(someLink.isFile()).isTrue();
}
@@ -407,7 +407,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicFileLinkIsNotDirectory() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xFile);
assertThat(someLink.isDirectory()).isFalse();
}
@@ -416,7 +416,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicDirLinkExists() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xEmptyDirectory);
assertThat(someLink.exists()).isTrue();
assertThat(someLink.statIfFound()).isNotNull();
@@ -426,7 +426,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicDirLinkIsSymbolicLink() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xEmptyDirectory);
assertThat(someLink.isSymbolicLink()).isTrue();
}
@@ -435,7 +435,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicDirLinkIsDirectory() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xEmptyDirectory);
assertThat(someLink.isDirectory()).isTrue();
}
@@ -444,7 +444,7 @@ public abstract class FileSystemTest {
@Test
public void testSymbolicDirLinkIsNotFile() throws Exception {
Path someLink = absolutize("some-link");
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
someLink.createSymbolicLink(xEmptyDirectory);
assertThat(someLink.isFile()).isFalse();
}
@@ -1287,7 +1287,7 @@ public abstract class FileSystemTest {
Path xNonEmptyDirectoryBar = xNonEmptyDirectory.getChild("bar");
xNonEmptyDirectory.setWritable(false);
- if (testFS.supportsSymbolicLinksNatively(xNonEmptyDirectoryBar.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xNonEmptyDirectoryBar)) {
try {
createSymbolicLink(xNonEmptyDirectoryBar, xNonEmptyDirectoryFoo);
fail("No exception thrown.");
@@ -1335,19 +1335,19 @@ public abstract class FileSystemTest {
@Test
public void testResolveSymlinks() throws Exception {
- if (testFS.supportsSymbolicLinksNatively(xLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xLink)) {
createSymbolicLink(xLink, xFile);
FileSystemUtils.createEmptyFile(xFile);
- assertThat(testFS.resolveOneLink(xLink.getLocalPath())).isEqualTo(xFile.getPathString());
+ assertThat(testFS.resolveOneLink(xLink)).isEqualTo(xFile.asFragment());
assertThat(xLink.resolveSymbolicLinks()).isEqualTo(xFile);
}
}
@Test
public void testResolveDanglingSymlinks() throws Exception {
- if (testFS.supportsSymbolicLinksNatively(xLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xLink)) {
createSymbolicLink(xLink, xNothing);
- assertThat(testFS.resolveOneLink(xLink.getLocalPath())).isEqualTo(xNothing.getPathString());
+ assertThat(testFS.resolveOneLink(xLink)).isEqualTo(xNothing.asFragment());
try {
xLink.resolveSymbolicLinks();
fail();
@@ -1358,15 +1358,15 @@ public abstract class FileSystemTest {
@Test
public void testResolveNonSymlinks() throws Exception {
- if (testFS.supportsSymbolicLinksNatively(xFile.getLocalPath())) {
- assertThat(testFS.resolveOneLink(xFile.getLocalPath())).isNull();
+ if (testFS.supportsSymbolicLinksNatively(xFile)) {
+ assertThat(testFS.resolveOneLink(xFile)).isNull();
assertThat(xFile.resolveSymbolicLinks()).isEqualTo(xFile);
}
}
@Test
public void testCreateHardLink_Success() throws Exception {
- if (!testFS.supportsHardLinksNatively(xFile.getLocalPath())) {
+ if (!testFS.supportsHardLinksNatively(xFile)) {
return;
}
xFile.createHardLink(xLink);
@@ -1379,7 +1379,7 @@ public abstract class FileSystemTest {
@Test
public void testCreateHardLink_NeitherOriginalNorLinkExists() throws Exception {
- if (!testFS.supportsHardLinksNatively(xFile.getLocalPath())) {
+ if (!testFS.supportsHardLinksNatively(xFile)) {
return;
}
@@ -1398,7 +1398,7 @@ public abstract class FileSystemTest {
@Test
public void testCreateHardLink_OriginalDoesNotExistAndLinkExists() throws Exception {
- if (!testFS.supportsHardLinksNatively(xFile.getLocalPath())) {
+ if (!testFS.supportsHardLinksNatively(xFile)) {
return;
}
@@ -1419,7 +1419,7 @@ public abstract class FileSystemTest {
@Test
public void testCreateHardLink_BothOriginalAndLinkExist() throws Exception {
- if (!testFS.supportsHardLinksNatively(xFile.getLocalPath())) {
+ if (!testFS.supportsHardLinksNatively(xFile)) {
return;
}
/* Both original file and link file exist */
@@ -1437,7 +1437,6 @@ public abstract class FileSystemTest {
}
protected boolean isHardLinked(Path a, Path b) throws IOException {
- return testFS.stat(a.getLocalPath(), false).getNodeId()
- == testFS.stat(b.getLocalPath(), false).getNodeId();
+ return testFS.stat(a, false).getNodeId() == testFS.stat(b, false).getNodeId();
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/FileSystemUtilsTest.java b/src/test/java/com/google/devtools/build/lib/vfs/FileSystemUtilsTest.java
index 3b9a2dc76d..0e9b74ed3b 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/FileSystemUtilsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/FileSystemUtilsTest.java
@@ -851,8 +851,8 @@ public class FileSystemUtilsTest {
FileSystemUtils.createHardLink(linkPath, originalPath);
assertThat(originalPath.exists()).isTrue();
assertThat(linkPath.exists()).isTrue();
- assertThat(fileSystem.stat(linkPath.getLocalPath(), false).getNodeId())
- .isEqualTo(fileSystem.stat(originalPath.getLocalPath(), false).getNodeId());
+ assertThat(fileSystem.stat(linkPath, false).getNodeId())
+ .isEqualTo(fileSystem.stat(originalPath, false).getNodeId());
}
@Test
@@ -892,11 +892,11 @@ public class FileSystemUtilsTest {
assertThat(linkPath1.exists()).isTrue();
assertThat(linkPath2.exists()).isTrue();
assertThat(linkPath3.exists()).isTrue();
- assertThat(fileSystem.stat(linkPath1.getLocalPath(), false).getNodeId())
- .isEqualTo(fileSystem.stat(originalPath1.getLocalPath(), false).getNodeId());
- assertThat(fileSystem.stat(linkPath2.getLocalPath(), false).getNodeId())
- .isEqualTo(fileSystem.stat(originalPath2.getLocalPath(), false).getNodeId());
- assertThat(fileSystem.stat(linkPath3.getLocalPath(), false).getNodeId())
- .isEqualTo(fileSystem.stat(originalPath3.getLocalPath(), false).getNodeId());
+ assertThat(fileSystem.stat(linkPath1, false).getNodeId())
+ .isEqualTo(fileSystem.stat(originalPath1, false).getNodeId());
+ assertThat(fileSystem.stat(linkPath2, false).getNodeId())
+ .isEqualTo(fileSystem.stat(originalPath2, false).getNodeId());
+ assertThat(fileSystem.stat(linkPath3, false).getNodeId())
+ .isEqualTo(fileSystem.stat(originalPath3, false).getNodeId());
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
index 70fc86dc48..5b0958fae1 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
@@ -54,18 +54,15 @@ public class GlobTest {
@Before
public final void initializeFileSystem() throws Exception {
- fs =
- new InMemoryFileSystem() {
- @Override
- public Collection<Dirent> readdir(LocalPath path, boolean followSymlinks)
- throws IOException {
- if (throwOnReaddir != null
- && path.getPathString().equals(throwOnReaddir.getPathString())) {
- throw new FileNotFoundException(path.getPathString());
- }
- return super.readdir(path, followSymlinks);
- }
- };
+ fs = new InMemoryFileSystem() {
+ @Override
+ public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
+ if (path.equals(throwOnReaddir)) {
+ throw new FileNotFoundException(path.getPathString());
+ }
+ return super.readdir(path, followSymlinks);
+ }
+ };
tmpPath = fs.getPath("/globtmp");
for (String dir : ImmutableList.of("foo/bar/wiz",
"foo/barnacle/wiz",
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/PathTrieTest.java b/src/test/java/com/google/devtools/build/lib/vfs/PathTrieTest.java
new file mode 100644
index 0000000000..0807b4aa5d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/vfs/PathTrieTest.java
@@ -0,0 +1,78 @@
+// Copyright 2014 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 com.google.devtools.build.lib.vfs;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link PathTrie}. */
+@RunWith(JUnit4.class)
+public class PathTrieTest {
+ @Test
+ public void empty() {
+ PathTrie<Integer> pathTrie = new PathTrie<>();
+ assertThat(pathTrie.get(PathFragment.EMPTY_FRAGMENT)).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/x"))).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/x/y"))).isNull();
+ }
+
+ @Test
+ public void simpleBranches() {
+ PathTrie<Integer> pathTrie = new PathTrie<>();
+ pathTrie.put(PathFragment.create("/a"), 1);
+ pathTrie.put(PathFragment.create("/b"), 2);
+
+ assertThat(pathTrie.get(PathFragment.EMPTY_FRAGMENT)).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/a"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/a/b"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/a/b/c"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/b"))).isEqualTo(2);
+ assertThat(pathTrie.get(PathFragment.create("/b/c"))).isEqualTo(2);
+ }
+
+ @Test
+ public void nestedDirectories() {
+ PathTrie<Integer> pathTrie = new PathTrie<>();
+ pathTrie.put(PathFragment.create("/a/b/c"), 3);
+ assertThat(pathTrie.get(PathFragment.EMPTY_FRAGMENT)).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/a"))).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/a/b"))).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/a/b/c"))).isEqualTo(3);
+ assertThat(pathTrie.get(PathFragment.create("/a/b/c/d"))).isEqualTo(3);
+
+ pathTrie.put(PathFragment.create("/a"), 1);
+ assertThat(pathTrie.get(PathFragment.EMPTY_FRAGMENT)).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/b"))).isNull();
+ assertThat(pathTrie.get(PathFragment.create("/a"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/a/b"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/a/b/c"))).isEqualTo(3);
+ assertThat(pathTrie.get(PathFragment.create("/a/b/c/d"))).isEqualTo(3);
+
+ pathTrie.put(PathFragment.ROOT_FRAGMENT, 0);
+ assertThat(pathTrie.get(PathFragment.EMPTY_FRAGMENT)).isEqualTo(0);
+ assertThat(pathTrie.get(PathFragment.create("/b"))).isEqualTo(0);
+ assertThat(pathTrie.get(PathFragment.create("/a"))).isEqualTo(1);
+ assertThat(pathTrie.get(PathFragment.create("/a/b"))).isEqualTo(1);
+ }
+
+ @Test
+ public void unrootedDirectoriesError() {
+ PathTrie<Integer> pathTrie = new PathTrie<>();
+ assertThrows(IllegalArgumentException.class, () -> pathTrie.put(PathFragment.create("a"), 1));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/SearchPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/SearchPathTest.java
index b49af40df9..6c545ac790 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/SearchPathTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/SearchPathTest.java
@@ -38,7 +38,7 @@ public class SearchPathTest {
assertThat(SearchPath.parse(fs, "/:/bin")).isEqualTo(searchPath);
assertThat(SearchPath.parse(fs, ".:/:/bin")).isEqualTo(searchPath);
- fs.getOutputStream(fs.getPath("/bin/exe").getLocalPath()).write(new byte[5]);
+ fs.getOutputStream(fs.getPath("/bin/exe")).write(new byte[5]);
assertThat(SearchPath.which(searchPath, "exe")).isNull();
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/SymlinkAwareFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/vfs/SymlinkAwareFileSystemTest.java
index b9f6485c8a..4720a6e773 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/SymlinkAwareFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/SymlinkAwareFileSystemTest.java
@@ -78,7 +78,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
assertThat(linkPath.isDirectory(Symlinks.NOFOLLOW)).isFalse();
assertThat(linkPath.isDirectory(Symlinks.FOLLOW)).isFalse();
- if (testFS.supportsSymbolicLinksNatively(linkPath.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(linkPath)) {
assertThat(linkPath.getFileSize(Symlinks.NOFOLLOW)).isEqualTo(newPath.toString().length());
assertThat(linkPath.getFileSize()).isEqualTo(newPath.getFileSize(Symlinks.NOFOLLOW));
}
@@ -196,7 +196,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
PathFragment relative = PathFragment.create(linkTarget);
linkPath.delete();
createSymbolicLink(linkPath, relative);
- if (testFS.supportsSymbolicLinksNatively(linkPath.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(linkPath)) {
assertThat(linkPath.getFileSize(Symlinks.NOFOLLOW)).isEqualTo(linkTarget.length());
assertThat(linkPath.readSymbolicLink()).isEqualTo(relative);
}
@@ -224,7 +224,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
// The path may not be a symlink, neither on Darwin nor on Linux.
String nonLinkEntry = null;
- for (String child : testFS.getDirectoryEntries(rootPath.getLocalPath())) {
+ for (String child : testFS.getDirectoryEntries(rootPath)) {
Path p = rootPath.getChild(child);
if (!p.isSymbolicLink() && p.isDirectory()) {
nonLinkEntry = p.getBaseName();
@@ -259,7 +259,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
Path link = absolutize("recursive-link");
createSymbolicLink(link, link);
- if (testFS.supportsSymbolicLinksNatively(link.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(link)) {
try {
link.resolveSymbolicLinks();
fail();
@@ -276,7 +276,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
createSymbolicLink(link2, link1);
createSymbolicLink(link1, link2);
- if (testFS.supportsSymbolicLinksNatively(link1.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(link1)) {
try {
link1.resolveSymbolicLinks();
fail();
@@ -288,7 +288,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
@Test
public void testResolveSymbolicLinksENOENT() {
- if (testFS.supportsSymbolicLinksNatively(xDanglingLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xDanglingLink)) {
try {
xDanglingLink.resolveSymbolicLinks();
fail();
@@ -302,7 +302,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
public void testResolveSymbolicLinksENOTDIR() throws IOException {
Path badLinkTarget = xFile.getChild("bad"); // parent is not a directory!
Path badLink = absolutize("badLink");
- if (testFS.supportsSymbolicLinksNatively(badLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(badLink)) {
createSymbolicLink(badLink, badLinkTarget);
try {
badLink.resolveSymbolicLinks();
@@ -317,7 +317,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
@Test
public void testResolveSymbolicLinksWithUplevelRefs() throws IOException {
- if (testFS.supportsSymbolicLinksNatively(xLinkToFile.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xLinkToFile)) {
// Create a series of links that refer to xFile as ./xFile,
// ./../foo/xFile, ./../../bar/foo/xFile, etc. They should all resolve
// to xFile.
@@ -335,7 +335,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
@Test
public void testReadSymbolicLink() throws IOException {
- if (testFS.supportsSymbolicLinksNatively(xDanglingLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xDanglingLink)) {
assertThat(xDanglingLink.readSymbolicLink().toString()).isEqualTo(xNothing.toString());
}
@@ -364,7 +364,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
throws IOException {
xEmptyDirectory.setWritable(false);
Path xChildOfReadonlyDir = xEmptyDirectory.getChild("x");
- if (testFS.supportsSymbolicLinksNatively(xChildOfReadonlyDir.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xChildOfReadonlyDir)) {
try {
xChildOfReadonlyDir.createSymbolicLink(xNothing);
fail();
@@ -386,7 +386,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
assertThat(someLink.isSymbolicLink()).isTrue();
assertThat(someLink.exists(Symlinks.NOFOLLOW)).isTrue(); // the link itself exists
assertThat(someLink.exists()).isFalse(); // ...but the referent doesn't
- if (testFS.supportsSymbolicLinksNatively(someLink.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(someLink)) {
try {
someLink.resolveSymbolicLinks();
} catch (FileNotFoundException e) {
@@ -398,7 +398,7 @@ public abstract class SymlinkAwareFileSystemTest extends FileSystemTest {
@Test
public void testCannotCreateSymbolicLinkWithoutParent() throws IOException {
Path xChildOfMissingDir = xNothing.getChild("x");
- if (testFS.supportsSymbolicLinksNatively(xChildOfMissingDir.getLocalPath())) {
+ if (testFS.supportsSymbolicLinksNatively(xChildOfMissingDir)) {
try {
xChildOfMissingDir.createSymbolicLink(xFile);
fail();
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/UnionFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/vfs/UnionFileSystemTest.java
index a330197a99..1e877a5255 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/UnionFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/UnionFileSystemTest.java
@@ -54,8 +54,8 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
private UnionFileSystem createDefaultUnionFileSystem() {
return new UnionFileSystem(
ImmutableMap.of(
- LocalPath.create("/in"), inDelegate,
- LocalPath.create("/out"), outDelegate),
+ PathFragment.create("/in"), inDelegate,
+ PathFragment.create("/out"), outDelegate),
defaultDelegate);
}
@@ -76,9 +76,9 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
@Test
public void testBasicDelegation() throws Exception {
unionfs = createDefaultUnionFileSystem();
- LocalPath fooPath = LocalPath.create("/foo");
- LocalPath inPath = LocalPath.create("/in");
- LocalPath outPath = LocalPath.create("/out/in.txt");
+ Path fooPath = unionfs.getPath("/foo");
+ Path inPath = unionfs.getPath("/in");
+ Path outPath = unionfs.getPath("/out/in.txt");
assertThat(unionfs.getDelegate(inPath)).isSameAs(inDelegate);
assertThat(unionfs.getDelegate(outPath)).isSameAs(outDelegate);
assertThat(unionfs.getDelegate(fooPath)).isSameAs(defaultDelegate);
@@ -101,7 +101,7 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
@Test
public void testDefaultFileSystemRequired() throws Exception {
try {
- new UnionFileSystem(ImmutableMap.of(), null);
+ new UnionFileSystem(ImmutableMap.<PathFragment, FileSystem>of(), null);
fail("Able to create a UnionFileSystem with no default!");
} catch (NullPointerException expected) {
// OK - should fail in this case.
@@ -114,16 +114,16 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
public void testPrefixDelegation() throws Exception {
unionfs =
new UnionFileSystem(
- ImmutableMap.of(
- LocalPath.create("/foo"), inDelegate,
- LocalPath.create("/foo/bar"), outDelegate),
+ ImmutableMap.<PathFragment, FileSystem>of(
+ PathFragment.create("/foo"), inDelegate,
+ PathFragment.create("/foo/bar"), outDelegate),
defaultDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/foo/foo.txt"))).isSameAs(inDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/foo/bar/foo.txt"))).isSameAs(outDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/foo/bar/../foo.txt"))).isSameAs(inDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/bar/foo.txt"))).isSameAs(defaultDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/foo/bar/../.."))).isSameAs(defaultDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/foo/foo.txt"))).isSameAs(inDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/foo/bar/foo.txt"))).isSameAs(outDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/foo/bar/../foo.txt"))).isSameAs(inDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/bar/foo.txt"))).isSameAs(defaultDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/foo/bar/../.."))).isSameAs(defaultDelegate);
}
// Checks that files cannot be modified when the filesystem is created
@@ -133,17 +133,17 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
unionfs =
new UnionFileSystem(
ImmutableMap.of(
- LocalPath.create("/rw"), new XAttrInMemoryFs(BlazeClock.instance()),
- LocalPath.create("/ro"),
+ PathFragment.create("/rw"), new XAttrInMemoryFs(BlazeClock.instance()),
+ PathFragment.create("/ro"),
new XAttrInMemoryFs(BlazeClock.instance()) {
@Override
- public boolean supportsModifications(LocalPath path) {
+ public boolean supportsModifications(Path path) {
return false;
}
}),
defaultDelegate);
- LocalPath rwPath = LocalPath.create("/rw/foo.txt");
- LocalPath roPath = LocalPath.create("/ro/foo.txt");
+ Path rwPath = unionfs.getPath("/rw/foo.txt");
+ Path roPath = unionfs.getPath("/ro/foo.txt");
assertThat(unionfs.supportsModifications(rwPath)).isTrue();
assertThat(unionfs.supportsModifications(roPath)).isFalse();
}
@@ -152,18 +152,18 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
// delegate filesystems; i.e. they can be seen from the filesystem of the parent.
@Test
public void testDelegateRootDirectoryCreation() throws Exception {
- LocalPath foo = LocalPath.create("/foo");
- LocalPath bar = LocalPath.create("/bar");
- LocalPath out = LocalPath.create("/out");
+ Path foo = unionfs.getPath("/foo");
+ Path bar = unionfs.getPath("/bar");
+ Path out = unionfs.getPath("/out");
assertThat(unionfs.createDirectory(foo)).isTrue();
assertThat(unionfs.createDirectory(bar)).isTrue();
assertThat(unionfs.createDirectory(out)).isTrue();
- LocalPath outFile = LocalPath.create("/out/in");
- FileSystemUtils.writeContentAsLatin1(unionfs, outFile, "Out");
+ Path outFile = unionfs.getPath("/out/in");
+ FileSystemUtils.writeContentAsLatin1(outFile, "Out");
// FileSystemTest.setUp() silently creates the test root on the filesystem...
Path testDirUnderRoot = unionfs.getPath(workingDir.asFragment().subFragment(0, 1));
- assertThat(unionfs.getDirectoryEntries(LocalPath.create("/")))
+ assertThat(unionfs.getDirectoryEntries(unionfs.getRootDirectory()))
.containsExactly(
foo.getBaseName(),
bar.getBaseName(),
@@ -172,30 +172,31 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
assertThat(unionfs.getDirectoryEntries(out)).containsExactly(outFile.getBaseName());
assertThat(defaultDelegate).isSameAs(unionfs.getDelegate(foo));
- assertThat(unionfs.adjustPath(foo, defaultDelegate)).isEqualTo(foo);
+ assertThat(unionfs.adjustPath(foo, defaultDelegate).asFragment()).isEqualTo(foo.asFragment());
assertThat(defaultDelegate).isSameAs(unionfs.getDelegate(bar));
assertThat(outDelegate).isSameAs(unionfs.getDelegate(outFile));
assertThat(outDelegate).isSameAs(unionfs.getDelegate(out));
// As a fragment (i.e. without filesystem or root info), the path name should be preserved.
- assertThat(unionfs.adjustPath(outFile, outDelegate)).isEqualTo(outFile);
+ assertThat(unionfs.adjustPath(outFile, outDelegate).asFragment())
+ .isEqualTo(outFile.asFragment());
}
// Ensure that the right filesystem is still chosen when paths contain "..".
@Test
public void testDelegationOfUpLevelReferences() throws Exception {
- assertThat(unionfs.getDelegate(LocalPath.create("/in/../foo.txt"))).isSameAs(defaultDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/out/../in"))).isSameAs(inDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/out/../in/../out/foo.txt")))
+ assertThat(unionfs.getDelegate(unionfs.getPath("/in/../foo.txt"))).isSameAs(defaultDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/out/../in"))).isSameAs(inDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/out/../in/../out/foo.txt")))
.isSameAs(outDelegate);
- assertThat(unionfs.getDelegate(LocalPath.create("/in/./foo.txt"))).isSameAs(inDelegate);
+ assertThat(unionfs.getDelegate(unionfs.getPath("/in/./foo.txt"))).isSameAs(inDelegate);
}
// Basic *explicit* cross-filesystem symlink check.
// Note: This does not work implicitly yet, as the next test illustrates.
@Test
public void testCrossDeviceSymlinks() throws Exception {
- assertThat(unionfs.createDirectory(LocalPath.create("/out"))).isTrue();
+ assertThat(unionfs.createDirectory(unionfs.getPath("/out"))).isTrue();
// Create an "/in" directory directly on the output delegate to bypass the
// UnionFileSystem's mapping.
@@ -204,8 +205,8 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
outStream.write('i');
outStream.close();
- LocalPath outFoo = LocalPath.create("/out/foo");
- unionfs.createSymbolicLink(outFoo, "../in/bar.txt");
+ Path outFoo = unionfs.getPath("/out/foo");
+ unionfs.createSymbolicLink(outFoo, PathFragment.create("../in/bar.txt"));
assertThat(unionfs.stat(outFoo, false).isSymbolicLink()).isTrue();
try {
@@ -215,13 +216,24 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
// OK
}
- LocalPath resolved = unionfs.resolveSymbolicLinks(outFoo);
- InputStream barInput = unionfs.getInputStream(resolved);
+ Path resolved = unionfs.resolveSymbolicLinks(outFoo);
+ assertThat(resolved.getFileSystem()).isSameAs(unionfs);
+ InputStream barInput = resolved.getInputStream();
int barChar = barInput.read();
barInput.close();
assertThat(barChar).isEqualTo('i');
}
+ @Test
+ public void testNoDelegateLeakage() throws Exception {
+ assertThat(unionfs.getPath("/in/foo.txt").getFileSystem()).isSameAs(unionfs);
+ assertThat(unionfs.getPath("/in/foo/bar").getParentDirectory().getFileSystem())
+ .isSameAs(unionfs);
+ unionfs.createDirectory(unionfs.getPath("/out"));
+ unionfs.createDirectory(unionfs.getPath("/out/foo"));
+ unionfs.createDirectory(unionfs.getPath("/out/foo/bar"));
+ }
+
// Write using the VFS through a UnionFileSystem and check that the file can
// be read back in the same location using standard Java IO.
// There is a similar test in UnixFileSystem, but this is essential to ensure
@@ -230,11 +242,12 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
public void testDelegateOperationsReflectOnLocalFilesystem() throws Exception {
unionfs =
new UnionFileSystem(
- ImmutableMap.of(workingDir.getLocalPath().getParentDirectory(), new UnixFileSystem()),
+ ImmutableMap.<PathFragment, FileSystem>of(
+ workingDir.getParentDirectory().asFragment(), new UnixFileSystem()),
defaultDelegate);
// This is a child of the current tmpdir, and doesn't exist on its own.
// It would be created in setup(), but of course, that didn't use a UnixFileSystem.
- unionfs.createDirectory(workingDir.getLocalPath());
+ unionfs.createDirectory(workingDir);
Path testFile = unionfs.getPath(workingDir.getRelative("test_file").asFragment());
assertThat(testFile.asFragment().startsWith(workingDir.asFragment())).isTrue();
String testString = "This is a test file";
@@ -243,7 +256,7 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
assertThat(new String(FileSystemUtils.readContentAsLatin1(testFile))).isEqualTo(testString);
} finally {
testFile.delete();
- assertThat(unionfs.delete(workingDir.getLocalPath())).isTrue();
+ assertThat(unionfs.delete(workingDir)).isTrue();
}
}
@@ -252,7 +265,8 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
public void testCreateParentsAcrossMapping() throws Exception {
unionfs =
new UnionFileSystem(
- ImmutableMap.of(LocalPath.create("/out/dir"), outDelegate), defaultDelegate);
+ ImmutableMap.<PathFragment, FileSystem>of(PathFragment.create("/out/dir"), outDelegate),
+ defaultDelegate);
Path outDir = unionfs.getPath("/out/dir/biz/bang");
FileSystemUtils.createDirectoryAndParents(outDir);
assertThat(outDir.isDirectory()).isTrue();
@@ -264,7 +278,8 @@ public class UnionFileSystemTest extends SymlinkAwareFileSystemTest {
}
@Override
- public byte[] getxattr(LocalPath path, String name) {
+ public byte[] getxattr(Path path, String name) {
+ assertThat(path.getFileSystem()).isSameAs(this);
return (name.equals(XATTR_KEY)) ? XATTR_VAL.getBytes(UTF_8) : null;
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java
index 16ae52cc4c..2cdb4014ae 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java
@@ -162,17 +162,6 @@ public class UnixLocalPathTest extends LocalPathAbstractTest {
assertThat(create("/..")).isEqualTo(create("/.."));
}
- @Test
- public void testRootsUnix() {
- assertThat(create("/").getDrive().getPathString()).isEqualTo("/");
- assertThat(create("/usr").getDrive().getPathString()).isEqualTo("/");
- assertThrows(IllegalArgumentException.class, () -> create("").getDrive());
-
- assertThat(create("/").isRoot()).isTrue();
- assertThat(create("/usr").isRoot()).isFalse();
- assertThat(create("").isRoot()).isFalse();
- }
-
@Override
protected OsPathPolicy getFilePathOs() {
return new UnixOsPathPolicy();
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java
index 88c7b6f248..ac5acef1f4 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java
@@ -14,9 +14,9 @@
package com.google.devtools.build.lib.vfs;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import com.google.common.testing.EqualsTester;
+import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.vfs.LocalPath.OsPathPolicy;
import com.google.devtools.build.lib.vfs.LocalPath.WindowsOsPathPolicy;
import com.google.devtools.build.lib.vfs.LocalPath.WindowsOsPathPolicy.ShortPathResolver;
@@ -101,14 +101,8 @@ public class WindowsLocalPathTest extends LocalPathAbstractTest {
@Test
public void testisAbsoluteWindows() {
assertThat(create("C:/").isAbsolute()).isTrue();
- }
-
- // We support unix paths to make test sharing easier
- @Test
- public void testUnixPathSupport() {
+ // test that msys paths turn into absolute paths
assertThat(create("/").isAbsolute()).isTrue();
- assertThat(create("/foo").isAbsolute()).isTrue();
- assertThat(create("/foo").getParentDirectory().getPathString()).isEqualTo("/");
}
@Test
@@ -116,7 +110,22 @@ public class WindowsLocalPathTest extends LocalPathAbstractTest {
assertThat(create("C:/foo").relativeTo(create("C:/"))).isEqualTo(create("foo"));
// Case insensitivity test
assertThat(create("C:/foo/bar").relativeTo(create("C:/FOO"))).isEqualTo(create("bar"));
- assertThrows(IllegalArgumentException.class, () -> create("D:/foo").relativeTo(create("C:/")));
+ MoreAsserts.assertThrows(
+ IllegalArgumentException.class, () -> create("D:/foo").relativeTo(create("C:/")));
+ }
+
+ @Test
+ public void testAbsoluteUnixPathIsRelativeToWindowsUnixRoot() {
+ assertThat(create("/").getPathString()).isEqualTo("C:/fake/msys");
+ assertThat(create("/foo/bar").getPathString()).isEqualTo("C:/fake/msys/foo/bar");
+ assertThat(create("/foo/bar").getPathString()).isEqualTo("C:/fake/msys/foo/bar");
+ }
+
+ @Test
+ public void testAbsoluteUnixPathReferringToDriveIsRecognized() {
+ assertThat(create("/c/foo").getPathString()).isEqualTo("C:/foo");
+ assertThat(create("/c/foo").getPathString()).isEqualTo("C:/foo");
+ assertThat(create("/c:").getPathString()).isNotEqualTo("C:/foo");
}
@Test
@@ -152,16 +161,4 @@ public class WindowsLocalPathTest extends LocalPathAbstractTest {
// Assert relative paths that look like short paths are untouched
assertThat(create("progra~1").getPathString()).isEqualTo("progra~1");
}
-
- @Test
- public void testRootsWindows() {
- assertThat(create("C:/").getDrive().getPathString()).isEqualTo("C:/");
- assertThat(create("C:/usr").getDrive().getPathString()).isEqualTo("C:/");
- assertThrows(IllegalArgumentException.class, () -> create("").getDrive());
-
- assertThat(create("C:/").isRoot()).isFalse();
- assertThat(create("C:/usr").isRoot()).isFalse();
- assertThat(create("/").isRoot()).isTrue();
- assertThat(create("").isRoot()).isFalse();
- }
}
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
index d50b243f5f..8937c453a7 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.lib.windows.WindowsFileSystem.WindowsPath;
import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
@@ -99,9 +100,9 @@ public class WindowsFileSystemTest {
assertThat(juncBadPath.exists(Symlinks.NOFOLLOW)).isTrue();
// TODO(bazel-team): fix https://github.com/bazelbuild/bazel/issues/1690 and uncomment the
// assertion below.
- // assertThat(fs.isSymbolicLink(juncBadPath)).isTrue();
- assertThat(fs.isDirectory(juncBadPath.getLocalPath(), /* followSymlinks */ true)).isFalse();
- assertThat(fs.isDirectory(juncBadPath.getLocalPath(), /* followSymlinks */ false)).isFalse();
+ //assertThat(fs.isSymbolicLink(juncBadPath)).isTrue();
+ assertThat(fs.isDirectory(juncBadPath, /* followSymlinks */ true)).isFalse();
+ assertThat(fs.isDirectory(juncBadPath, /* followSymlinks */ false)).isFalse();
// Test deleting a dangling junction.
assertThat(juncBadPath.delete()).isTrue();
@@ -332,21 +333,19 @@ public class WindowsFileSystemTest {
assertThat(fs.getPath(scratchRoot).createDirectory()).isTrue();
// Create symlink with directory target, relative path.
Path link1 = fs.getPath(scratchRoot).getRelative("link1");
- fs.createSymbolicLink(link1.getLocalPath(), "..");
+ fs.createSymbolicLink(link1, PathFragment.create(".."));
// Create symlink with directory target, absolute path.
Path link2 = fs.getPath(scratchRoot).getRelative("link2");
- fs.createSymbolicLink(
- link2.getLocalPath(), fs.getPath(scratchRoot).getRelative("link1").getPathString());
+ fs.createSymbolicLink(link2, fs.getPath(scratchRoot).getRelative("link1").asFragment());
// Create scratch files that'll be symlink targets.
testUtil.scratchFile("foo.txt", "hello");
testUtil.scratchFile("bar.txt", "hello");
// Create symlink with file target, relative path.
Path link3 = fs.getPath(scratchRoot).getRelative("link3");
- fs.createSymbolicLink(link3.getLocalPath(), "foo.txt");
+ fs.createSymbolicLink(link3, PathFragment.create("foo.txt"));
// Create symlink with file target, absolute path.
Path link4 = fs.getPath(scratchRoot).getRelative("link4");
- fs.createSymbolicLink(
- link4.getLocalPath(), fs.getPath(scratchRoot).getRelative("bar.txt").getPathString());
+ fs.createSymbolicLink(link4, fs.getPath(scratchRoot).getRelative("bar.txt").asFragment());
// Assert that link1 and link2 are true junctions and have the right contents.
for (Path p : ImmutableList.of(link1, link2)) {
assertThat(WindowsFileOperations.isJunction(p.getPathString())).isTrue();