aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/vfs
diff options
context:
space:
mode:
authorGravatar lberki <lberki@google.com>2018-07-09 01:58:09 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-07-09 01:59:10 -0700
commit325e2ea234418d906778bee4aacea90163e2c311 (patch)
tree4fd30bc5153f391a61a81e39074eb6fd02b8b222 /src/main/java/com/google/devtools/build/lib/vfs
parent8f16879813383dad7026757e41111aac6bd8e7a1 (diff)
Delete UnionFileSystem.
It was used in a single, Google-internal test which I cleaned up as pre-work for this change. RELNOTES: None. PiperOrigin-RevId: 203727293
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs')
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java513
1 files changed, 0 insertions, 513 deletions
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
deleted file mode 100644
index 2136633bc6..0000000000
--- a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java
+++ /dev/null
@@ -1,513 +0,0 @@
-// 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;
-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;
-
-/**
- * Presents a unified view of multiple virtual {@link FileSystem} instances, to which requests are
- * delegated based on a {@link PathFragment} prefix mapping. If multiple prefixes apply to a given
- * path, the *longest* (i.e. most specific) match is used. The order in which the delegates are
- * specified does not influence the mapping.
- *
- * <p>Paths are preserved absolutely, contrary to how "mount" works, e.g.: /foo/bar maps to /foo/bar
- * on the delegate, even if it is mounted at /foo.
- *
- * <p>For example: "/in" maps to InFileSystem, "/" maps to OtherFileSystem. Reading from
- * "/in/base/BUILD" through the UnionFileSystem will delegate the read operation to InFileSystem,
- * which will read "/in/base/BUILD" relative to its root. ("mount" behavior would remap it to
- * "/base/BUILD" on the delegate).
- *
- * <p>Intra-filesystem symbolic links are resolved to their ultimate targets. Cross-filesystem links
- * are not currently supported.
- */
-@ThreadSafety.ThreadSafe
-public final class UnionFileSystem extends FileSystem {
-
- private static class FileSystemAndPrefix {
- final PathFragment prefix;
- final FileSystem fileSystem;
-
- public FileSystemAndPrefix(PathFragment 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;
-
- // True if the file path is case-sensitive on all the FileSystem
- // or False if they are all case-insensitive, otherwise error.
- private final boolean isCaseSensitive;
-
- /**
- * Creates a new modifiable UnionFileSystem with prefix mappings specified by a map.
- *
- * @param prefixMapping map of path prefixes to {@link FileSystem}s
- * @param rootFileSystem root for default requests; i.e. mapping of "/"
- */
- 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.keySet().stream().noneMatch(p -> p.getPathString().equals("/")),
- "Attempted to specify an explicit root prefix mapping; "
- + "please use the rootFileSystem argument instead.");
-
- this.fileSystems = new ArrayList<>();
- this.rootFileSystem = rootFileSystem;
- this.isCaseSensitive = rootFileSystem.isFilePathCaseSensitive();
-
- 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");
- PathFragment prefixPath = prefix.getKey();
-
- // Extra slash prevents within-directory mappings, which Path can't handle.
- fileSystems.add(new FileSystemAndPrefix(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());
- }
-
- /**
- * Retrieves the filesystem delegate of a path mapping. Does not follow symlinks (but you can call
- * on a path preprocessed with {@link #resolveSymbolicLinks} to support this use case).
- *
- * @param path the {@link Path} to map to a filesystem
- * @throws IllegalArgumentException if no delegate exists for the path
- */
- 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;
- }
-
- // Associates the path with the root of the given delegate filesystem.
- // Necessary to avoid null pointer problems inside of the delegates.
- Path adjustPath(Path path, FileSystem delegate) {
- return delegate.getPath(path.getPathString());
- }
-
- /**
- * Follow a symbolic link once using the appropriate delegate filesystem, also resolving parent
- * directory symlinks.
- *
- * @param path {@link Path} to the symbolic link
- */
- @Override
- protected PathFragment readSymbolicLink(Path path) throws IOException {
- Preconditions.checkNotNull(path);
- FileSystem delegate = getDelegate(path);
- return delegate.readSymbolicLink(adjustPath(path, delegate));
- }
-
- @Override
- protected PathFragment resolveOneLink(Path path) throws IOException {
- Preconditions.checkNotNull(path);
- FileSystem delegate = getDelegate(path);
- return delegate.resolveOneLink(adjustPath(path, delegate));
- }
-
- private void checkModifiable(Path path) {
- if (!supportsModifications(path)) {
- throw new UnsupportedOperationException(
- String.format("Modifications to this %s are disabled.", getClass().getSimpleName()));
- }
- }
-
- @Override
- public boolean supportsModifications(Path path) {
- FileSystem delegate = getDelegate(path);
- path = adjustPath(path, delegate);
- return delegate.supportsModifications(path);
- }
-
- @Override
- public boolean supportsSymbolicLinksNatively(Path path) {
- FileSystem delegate = getDelegate(path);
- path = adjustPath(path, delegate);
- return delegate.supportsSymbolicLinksNatively(path);
- }
-
- @Override
- public boolean supportsHardLinksNatively(Path path) {
- FileSystem delegate = getDelegate(path);
- path = adjustPath(path, delegate);
- return delegate.supportsHardLinksNatively(path);
- }
-
- @Override
- public boolean isFilePathCaseSensitive() {
- return isCaseSensitive;
- }
-
- @Override
- public String getFileSystemType(Path path) {
- try {
- path = internalResolveSymlink(path);
- } catch (IOException e) {
- return "unknown";
- }
- FileSystem delegate = getDelegate(path);
- return delegate.getFileSystemType(path);
- }
-
- @Override
- protected byte[] getDigest(Path path, DigestHashFunction hashFunction) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.getDigest(adjustPath(path, delegate), hashFunction);
- }
-
- @Override
- 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.
- // This is necessary both for the parent to see the directory and for the
- // delegate to use it.
- // This is present to address this problematic case:
- // / -> RootFs
- // /foo -> FooFs
- // mkdir /foo
- // 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);
- Path parent = path.getParentDirectory();
- if (parent != null) {
- parent = internalResolveSymlink(parent);
- FileSystem parentDelegate = getDelegate(parent);
- if (parentDelegate != delegate) {
- // There's a possibility it already exists on the parent, so don't die
- // if the directory can't be created there.
- parentDelegate.createDirectory(adjustPath(path, parentDelegate));
- }
- }
- return delegate.createDirectory(adjustPath(path, delegate));
- }
-
- @Override
- public void createDirectoryAndParents(Path path) throws IOException {
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- delegate.createDirectoryAndParents(adjustPath(path, delegate));
- }
-
- @Override
- 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(Path path) throws IOException {
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- return delegate.delete(adjustPath(path, delegate));
- }
-
- @Override
- 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(Path path, long newTime) throws IOException {
- path = internalResolveSymlink(path);
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- delegate.setLastModifiedTime(adjustPath(path, delegate), newTime);
- }
-
- @Override
- protected boolean isSymbolicLink(Path path) {
- FileSystem delegate = getDelegate(path);
- path = adjustPath(path, delegate);
- return delegate.isSymbolicLink(path);
- }
-
- @Override
- protected boolean isDirectory(Path path, boolean followSymlinks) {
- try {
- path = followSymlinks ? internalResolveSymlink(path) : path;
- } catch (IOException e) {
- return false;
- }
- FileSystem delegate = getDelegate(path);
- return delegate.isDirectory(adjustPath(path, delegate), false);
- }
-
- @Override
- protected boolean isFile(Path path, boolean followSymlinks) {
- try {
- path = followSymlinks ? internalResolveSymlink(path) : path;
- } catch (IOException e) {
- return false;
- }
- FileSystem delegate = getDelegate(path);
- return delegate.isFile(adjustPath(path, delegate), false);
- }
-
- @Override
- protected boolean isSpecialFile(Path path, boolean followSymlinks) {
- try {
- path = followSymlinks ? internalResolveSymlink(path) : path;
- } catch (IOException e) {
- return false;
- }
- FileSystem delegate = getDelegate(path);
- return delegate.isSpecialFile(adjustPath(path, delegate), false);
- }
-
- @Override
- protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
- checkModifiable(linkPath);
- if (!supportsSymbolicLinksNatively(linkPath)) {
- throw new UnsupportedOperationException(
- "Attempted to create a symlink, but symlink support is disabled.");
- }
-
- FileSystem delegate = getDelegate(linkPath);
- delegate.createSymbolicLink(adjustPath(linkPath, delegate), targetFragment);
- }
-
- @Override
- protected boolean exists(Path path, boolean followSymlinks) {
- try {
- path = followSymlinks ? internalResolveSymlink(path) : path;
- } catch (IOException e) {
- return false;
- }
- FileSystem delegate = getDelegate(path);
- return delegate.exists(adjustPath(path, delegate), false);
- }
-
- @Override
- 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);
- }
-
- // Needs to be overridden for the delegation logic, because the
- // UnixFileSystem implements statNullable and stat as separate codepaths.
- // More generally, we wish to delegate all filesystem operations.
- @Override
- protected FileStatus statNullable(Path path, boolean followSymlinks) {
- try {
- path = followSymlinks ? internalResolveSymlink(path) : path;
- } catch (IOException e) {
- return null;
- }
- FileSystem delegate = getDelegate(path);
- return delegate.statNullable(adjustPath(path, delegate), false);
- }
-
- @Override
- @Nullable
- 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);
- }
-
- /**
- * Retrieves the directory entries for the specified path under the assumption that {@code
- * resolvedPath} is the resolved path of {@code path} in one of the underlying file systems.
- *
- * @param path the {@link Path} whose children are to be retrieved
- */
- @Override
- protected Collection<String> getDirectoryEntries(Path path) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- Path resolvedPath = adjustPath(path, delegate);
- return delegate.getDirectoryEntries(resolvedPath);
- }
-
- // No need for the more complex logic of getDirectoryEntries; it calls it implicitly.
- @Override
- 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(Path path) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.isReadable(adjustPath(path, delegate));
- }
-
- @Override
- protected void setReadable(Path path, boolean readable) throws IOException {
- path = internalResolveSymlink(path);
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- delegate.setReadable(adjustPath(path, delegate), readable);
- }
-
- @Override
- protected boolean isWritable(Path path) throws IOException {
- if (!supportsModifications(path)) {
- return false;
- }
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.isWritable(adjustPath(path, delegate));
- }
-
- @Override
- public void setWritable(Path path, boolean writable) throws IOException {
- checkModifiable(path);
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- delegate.setWritable(adjustPath(path, delegate), writable);
- }
-
- @Override
- protected boolean isExecutable(Path path) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.isExecutable(adjustPath(path, delegate));
- }
-
- @Override
- protected void setExecutable(Path path, boolean executable) throws IOException {
- path = internalResolveSymlink(path);
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- delegate.setExecutable(adjustPath(path, delegate), executable);
- }
-
- @Override
- protected byte[] getFastDigest(Path path, DigestHashFunction hashFunction) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.getFastDigest(adjustPath(path, delegate), hashFunction);
- }
-
- @Override
- 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(Path path) throws IOException {
- path = internalResolveSymlink(path);
- FileSystem delegate = getDelegate(path);
- return delegate.getInputStream(adjustPath(path, delegate));
- }
-
- @Override
- protected OutputStream getOutputStream(Path path, boolean append) throws IOException {
- path = internalResolveSymlink(path);
- checkModifiable(path);
- FileSystem delegate = getDelegate(path);
- return delegate.getOutputStream(adjustPath(path, delegate), append);
- }
-
- @Override
- public void renameTo(Path sourcePath, Path targetPath) throws IOException {
- sourcePath = internalResolveSymlink(sourcePath);
- FileSystem sourceDelegate = getDelegate(sourcePath);
- if (!sourceDelegate.supportsModifications(sourcePath)) {
- throw new UnsupportedOperationException(
- String.format(
- "The filesystem for the source path %s does not support modifications.",
- sourcePath.getPathString()));
- }
- sourcePath = adjustPath(sourcePath, sourceDelegate);
-
- FileSystem targetDelegate = getDelegate(targetPath);
- if (!targetDelegate.supportsModifications(targetPath)) {
- throw new UnsupportedOperationException(
- String.format(
- "The filesystem for the target path %s does not support modifications.",
- targetPath.getPathString()));
- }
- targetPath = adjustPath(targetPath, targetDelegate);
-
- if (sourceDelegate == targetDelegate) {
- // Easy, same filesystem.
- sourceDelegate.renameTo(sourcePath, targetPath);
- return;
- } else {
- // Copy across filesystems, then delete.
- // copyFile throws on failure, so delete will never be reached if it fails.
- FileSystemUtils.copyFile(sourcePath, targetPath);
- sourceDelegate.delete(sourcePath);
- }
- }
-
- @Override
- protected void createFSDependentHardLink(Path linkPath, Path originalPath) throws IOException {
- checkModifiable(linkPath);
-
- originalPath = internalResolveSymlink(originalPath);
- FileSystem originalDelegate = getDelegate(originalPath);
- FileSystem linkDelegate = getDelegate(linkPath);
-
- if (!originalDelegate.equals(linkDelegate)
- || !linkDelegate.supportsHardLinksNatively(linkPath)) {
- throw new UnsupportedOperationException(
- "Attempted to create a hard link, but hard link support is disabled.");
- }
- linkDelegate.createFSDependentHardLink(
- adjustPath(linkPath, linkDelegate), adjustPath(originalPath, originalDelegate));
- }
-
- private Path internalResolveSymlink(Path path) throws IOException {
- while (isSymbolicLink(path)) {
- PathFragment pathFragment = resolveOneLink(path);
- path = path.getRelative(pathFragment);
- }
- return path;
- }
-}