aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
diff options
context:
space:
mode:
authorGravatar Han-Wen Nienhuys <hanwen@google.com>2015-02-25 16:45:20 +0100
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-02-25 16:45:20 +0100
commitd08b27fa9701fecfdb69e1b0d1ac2459efc2129b (patch)
tree5d50963026239ca5aebfb47ea5b8db7e814e57c8 /src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
Update from Google.
-- MOE_MIGRATED_REVID=85702957
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java b/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
new file mode 100644
index 0000000000..acc0e86a51
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
@@ -0,0 +1,314 @@
+// Copyright 2014 Google Inc. 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.actions;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversal;
+import com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversalRoot;
+import com.google.devtools.build.lib.syntax.FilesetEntry.SymlinkBehavior;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.util.Fingerprint;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.vfs.RootedPath;
+
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/** Factory of {@link FilesetTraversalParams}. */
+public final class FilesetTraversalParamsFactory {
+
+ /**
+ * Creates parameters for a recursive traversal request in a package.
+ *
+ * <p>"Recursive" means that a directory is traversed along with all of its subdirectories. Such
+ * a traversal is created when FilesetEntry.files is unspecified.
+ *
+ * @param ownerLabel the rule that created this object
+ * @param buildFile path of the BUILD file of the package to traverse
+ * @param destPath path in the Fileset's output directory that will be the root of files found
+ * in this directory
+ * @param excludes optional; set of files directly under this package's directory to exclude;
+ * files in subdirectories cannot be excluded
+ * @param symlinkBehaviorMode what to do with symlinks
+ * @param crossPkgBoundary whether to traverse a subdirectory if it's also a subpackage (contains
+ * a BUILD file)
+ */
+ public static FilesetTraversalParams recursiveTraversalOfPackage(Label ownerLabel,
+ Artifact buildFile, PathFragment destPath, @Nullable Set<String> excludes,
+ SymlinkBehavior symlinkBehaviorMode, boolean crossPkgBoundary) {
+ Preconditions.checkState(buildFile.isSourceArtifact(), "%s", buildFile);
+ return new DirectoryTraversalParams(ownerLabel, DirectTraversalRootImpl.forPackage(buildFile),
+ true, destPath, excludes, symlinkBehaviorMode, crossPkgBoundary, true, false);
+ }
+
+ /**
+ * Creates parameters for a recursive traversal request in a directory.
+ *
+ * <p>"Recursive" means that a directory is traversed along with all of its subdirectories. Such
+ * a traversal is created when FilesetEntry.files is unspecified.
+ *
+ * @param ownerLabel the rule that created this object
+ * @param directoryToTraverse path of the directory to traverse
+ * @param destPath path in the Fileset's output directory that will be the root of files found
+ * in this directory
+ * @param excludes optional; set of files directly below this directory to exclude; files in
+ * subdirectories cannot be excluded
+ * @param symlinkBehaviorMode what to do with symlinks
+ * @param crossPkgBoundary whether to traverse a subdirectory if it's also a subpackage (contains
+ * a BUILD file)
+ */
+ public static FilesetTraversalParams recursiveTraversalOfDirectory(Label ownerLabel,
+ Artifact directoryToTraverse, PathFragment destPath, @Nullable Set<String> excludes,
+ SymlinkBehavior symlinkBehaviorMode, boolean crossPkgBoundary) {
+ return new DirectoryTraversalParams(ownerLabel,
+ DirectTraversalRootImpl.forFileOrDirectory(directoryToTraverse), false, destPath,
+ excludes, symlinkBehaviorMode, crossPkgBoundary, true,
+ !directoryToTraverse.isSourceArtifact());
+ }
+
+ /**
+ * Creates parameters for a file traversal request.
+ *
+ * <p>Such a traversal is created for every entry in FilesetEntry.files, when it is specified.
+ *
+ * @param ownerLabel the rule that created this object
+ * @param fileToTraverse the file to traverse; "traversal" means that if this file is actually a
+ * directory or a symlink to one then it'll be traversed as one
+ * @param destPath path in the Fileset's output directory that will be the name of this file's
+ * respective symlink there, or the root of files found (in case this is a directory)
+ * @param symlinkBehaviorMode what to do with symlinks
+ * @param crossPkgBoundary whether to traverse a subdirectory if it's also a subpackage (contains
+ * a BUILD file)
+ */
+ public static FilesetTraversalParams fileTraversal(Label ownerLabel, Artifact fileToTraverse,
+ PathFragment destPath, SymlinkBehavior symlinkBehaviorMode, boolean crossPkgBoundary) {
+ return new DirectoryTraversalParams(ownerLabel,
+ DirectTraversalRootImpl.forFileOrDirectory(fileToTraverse), false, destPath, null,
+ symlinkBehaviorMode, crossPkgBoundary, false, !fileToTraverse.isSourceArtifact());
+ }
+
+ /**
+ * Creates traversal request parameters for a FilesetEntry wrapping another Fileset.
+ *
+ * @param ownerLabel the rule that created this object
+ * @param nested the traversal params that were used for the nested (inner) Fileset
+ * @param destDir path in the Fileset's output directory that will be the root of files coming
+ * from the nested Fileset
+ * @param excludes optional; set of files directly below (not in a subdirectory of) the nested
+ * Fileset that should be excluded from the outer Fileset
+ */
+ public static FilesetTraversalParams nestedTraversal(Label ownerLabel,
+ FilesetTraversalParams nested, PathFragment destDir, @Nullable Set<String> excludes) {
+ // When srcdir is another Fileset, then files must be null so strip_prefix must also be null.
+ return new NestedTraversalParams(ownerLabel, nested, destDir, excludes);
+ }
+
+ private abstract static class ParamsCommon implements FilesetTraversalParams {
+ private final Label ownerLabel;
+ private final PathFragment destDir;
+ private final ImmutableSet<String> excludes;
+
+ ParamsCommon(Label ownerLabel, PathFragment destDir, @Nullable Set<String> excludes) {
+ this.ownerLabel = ownerLabel;
+ this.destDir = destDir;
+ if (excludes == null) {
+ this.excludes = ImmutableSet.<String>of();
+ } else {
+ // Order the set for the sake of deterministic fingerprinting.
+ this.excludes = ImmutableSet.copyOf(Ordering.natural().immutableSortedCopy(excludes));
+ }
+ }
+
+ @Override
+ public Label getOwnerLabel() {
+ return ownerLabel;
+ }
+
+ @Override
+ public Set<String> getExcludedFiles() {
+ return excludes;
+ }
+
+ @Override
+ public PathFragment getDestPath() {
+ return destDir;
+ }
+
+ protected final void commonFingerprint(Fingerprint fp) {
+ fp.addPath(destDir);
+ if (!excludes.isEmpty()) {
+ fp.addStrings(excludes);
+ }
+ }
+ }
+
+ private static final class DirectTraversalImpl implements DirectTraversal {
+ private final DirectTraversalRoot root;
+ private final boolean isPackage;
+ private final boolean followSymlinks;
+ private final boolean crossPkgBoundary;
+ private final boolean isRecursive;
+ private final boolean isGenerated;
+
+ DirectTraversalImpl(DirectTraversalRoot root, boolean isPackage, boolean followSymlinks,
+ boolean crossPkgBoundary, boolean isRecursive, boolean isGenerated) {
+ this.root = root;
+ this.isPackage = isPackage;
+ this.followSymlinks = followSymlinks;
+ this.crossPkgBoundary = crossPkgBoundary;
+ this.isRecursive = isRecursive;
+ this.isGenerated = isGenerated;
+ }
+
+ @Override
+ public DirectTraversalRoot getRoot() {
+ return root;
+ }
+
+ @Override
+ public boolean isPackage() {
+ return isPackage;
+ }
+
+ @Override
+ public boolean isRecursive() {
+ return isRecursive;
+ }
+
+ @Override
+ public boolean isGenerated() {
+ return isGenerated;
+ }
+
+ @Override
+ public boolean isFollowingSymlinks() {
+ return followSymlinks;
+ }
+
+ @Override
+ public boolean getCrossPackageBoundary() {
+ return crossPkgBoundary;
+ }
+
+ void fingerprint(Fingerprint fp) {
+ fp.addPath(root.asRootedPath().asPath());
+ fp.addBoolean(isPackage);
+ fp.addBoolean(followSymlinks);
+ fp.addBoolean(isRecursive);
+ fp.addBoolean(isGenerated);
+ fp.addBoolean(crossPkgBoundary);
+ }
+ }
+
+ private static final class DirectoryTraversalParams extends ParamsCommon {
+ private final DirectTraversalImpl traversal;
+
+ DirectoryTraversalParams(Label ownerLabel,
+ DirectTraversalRoot root,
+ boolean isPackage,
+ PathFragment destPath,
+ @Nullable Set<String> excludes,
+ SymlinkBehavior symlinkBehaviorMode,
+ boolean crossPkgBoundary,
+ boolean isRecursive,
+ boolean isGenerated) {
+ super(ownerLabel, destPath, excludes);
+ traversal = new DirectTraversalImpl(root, isPackage,
+ symlinkBehaviorMode == SymlinkBehavior.DEREFERENCE, crossPkgBoundary, isRecursive,
+ isGenerated);
+ }
+
+ @Override
+ public Optional<DirectTraversal> getDirectTraversal() {
+ return Optional.<DirectTraversal>of(traversal);
+ }
+
+ @Override
+ public Optional<FilesetTraversalParams> getNestedTraversal() {
+ return Optional.absent();
+ }
+
+ @Override
+ public void fingerprint(Fingerprint fp) {
+ commonFingerprint(fp);
+ traversal.fingerprint(fp);
+ }
+ }
+
+ private static final class NestedTraversalParams extends ParamsCommon {
+ private final FilesetTraversalParams nested;
+
+ public NestedTraversalParams(Label ownerLabel, FilesetTraversalParams nested,
+ PathFragment destDir, @Nullable Set<String> excludes) {
+ super(ownerLabel, destDir, excludes);
+ this.nested = nested;
+ }
+
+ @Override
+ public Optional<DirectTraversal> getDirectTraversal() {
+ return Optional.absent();
+ }
+
+ @Override
+ public Optional<FilesetTraversalParams> getNestedTraversal() {
+ return Optional.of(nested);
+ }
+
+ @Override
+ public void fingerprint(Fingerprint fp) {
+ commonFingerprint(fp);
+ nested.fingerprint(fp);
+ }
+ }
+
+ private static final class DirectTraversalRootImpl implements DirectTraversalRoot {
+ private final Path rootDir;
+ private final PathFragment relativeDir;
+
+ static DirectTraversalRoot forPackage(Artifact buildFile) {
+ return new DirectTraversalRootImpl(buildFile.getRoot().getPath(),
+ buildFile.getRootRelativePath().getParentDirectory());
+ }
+
+ static DirectTraversalRoot forFileOrDirectory(Artifact fileOrDirectory) {
+ return new DirectTraversalRootImpl(fileOrDirectory.getRoot().getPath(),
+ fileOrDirectory.getRootRelativePath());
+ }
+
+ private DirectTraversalRootImpl(Path rootDir, PathFragment relativeDir) {
+ this.rootDir = rootDir;
+ this.relativeDir = relativeDir;
+ }
+
+ @Override
+ public Path getRootPart() {
+ return rootDir;
+ }
+
+ @Override
+ public PathFragment getRelativePart() {
+ return relativeDir;
+ }
+
+ @Override
+ public RootedPath asRootedPath() {
+ return RootedPath.toRootedPath(rootDir, relativeDir);
+ }
+ }
+}