aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java26
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java53
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java21
6 files changed, 83 insertions, 41 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java b/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java
index 703611fd27..7740a05b51 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java
@@ -220,6 +220,9 @@ public interface FilesetTraversalParams {
/** Returns the desired behavior when the traversal hits a subpackage. */
public abstract PackageBoundaryMode getPackageBoundaryMode();
+ /** Returns whether Filesets treat outputs in a strict manner, assuming regular files. */
+ public abstract boolean isStrictFilesetOutput();
+
@Memoized
@Override
public abstract int hashCode();
@@ -232,6 +235,7 @@ public interface FilesetTraversalParams {
fp.addBoolean(isFollowingSymlinks());
fp.addBoolean(isRecursive());
fp.addBoolean(isGenerated());
+ fp.addBoolean(isStrictFilesetOutput());
getPackageBoundaryMode().fingerprint(fp);
return fp.digestAndReset();
}
@@ -242,6 +246,7 @@ public interface FilesetTraversalParams {
boolean isPackage,
boolean followingSymlinks,
PackageBoundaryMode packageBoundaryMode,
+ boolean isStrictFilesetOutput,
boolean isRecursive,
boolean isGenerated) {
return new AutoValue_FilesetTraversalParams_DirectTraversal(
@@ -250,7 +255,8 @@ public interface FilesetTraversalParams {
isRecursive,
isGenerated,
followingSymlinks,
- packageBoundaryMode);
+ packageBoundaryMode,
+ isStrictFilesetOutput);
}
}
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
index 93941a7bd7..d1f94f072a 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java
@@ -48,15 +48,16 @@ public final class FilesetTraversalParamsFactory {
* files in subdirectories cannot be excluded
* @param symlinkBehaviorMode what to do with symlinks
* @param pkgBoundaryMode what to do when the traversal hits a subdirectory that is also a
- * subpackage (contains a BUILD file)
+ * @param strictFilesetOutput whether Fileset assumes that output Artifacts are regular files.
*/
public static FilesetTraversalParams recursiveTraversalOfPackage(Label ownerLabel,
Artifact buildFile, PathFragment destPath, @Nullable Set<String> excludes,
- SymlinkBehavior symlinkBehaviorMode, PackageBoundaryMode pkgBoundaryMode) {
+ SymlinkBehavior symlinkBehaviorMode, PackageBoundaryMode pkgBoundaryMode,
+ boolean strictFilesetOutput) {
Preconditions.checkState(buildFile.isSourceArtifact(), "%s", buildFile);
return DirectoryTraversalParams.getDirectoryTraversalParams(ownerLabel,
DirectTraversalRoot.forPackage(buildFile), true, destPath, excludes,
- symlinkBehaviorMode, pkgBoundaryMode, true, false);
+ symlinkBehaviorMode, pkgBoundaryMode, strictFilesetOutput, true, false);
}
/**
@@ -73,14 +74,15 @@ public final class FilesetTraversalParamsFactory {
* subdirectories cannot be excluded
* @param symlinkBehaviorMode what to do with symlinks
* @param pkgBoundaryMode what to do when the traversal hits a subdirectory that is also a
- * subpackage (contains a BUILD file)
+ * @param strictFilesetOutput whether Fileset assumes that output Artifacts are regular files.
*/
public static FilesetTraversalParams recursiveTraversalOfDirectory(Label ownerLabel,
Artifact directoryToTraverse, PathFragment destPath, @Nullable Set<String> excludes,
- SymlinkBehavior symlinkBehaviorMode, PackageBoundaryMode pkgBoundaryMode) {
+ SymlinkBehavior symlinkBehaviorMode, PackageBoundaryMode pkgBoundaryMode,
+ boolean strictFilesetOutput) {
return DirectoryTraversalParams.getDirectoryTraversalParams(ownerLabel,
DirectTraversalRoot.forFileOrDirectory(directoryToTraverse), false, destPath,
- excludes, symlinkBehaviorMode, pkgBoundaryMode, true,
+ excludes, symlinkBehaviorMode, pkgBoundaryMode, strictFilesetOutput, true,
!directoryToTraverse.isSourceArtifact());
}
@@ -96,14 +98,15 @@ public final class FilesetTraversalParamsFactory {
* respective symlink there, or the root of files found (in case this is a directory)
* @param symlinkBehaviorMode what to do with symlinks
* @param pkgBoundaryMode what to do when the traversal hits a subdirectory that is also a
- * subpackage (contains a BUILD file)
+ * @param strictFilesetOutput whether Fileset assumes that output Artifacts are regular files.
*/
public static FilesetTraversalParams fileTraversal(Label ownerLabel, Artifact fileToTraverse,
PathFragment destPath, SymlinkBehavior symlinkBehaviorMode,
- PackageBoundaryMode pkgBoundaryMode) {
+ PackageBoundaryMode pkgBoundaryMode, boolean strictFilesetOutput) {
return DirectoryTraversalParams.getDirectoryTraversalParams(ownerLabel,
DirectTraversalRoot.forFileOrDirectory(fileToTraverse), false, destPath, null,
- symlinkBehaviorMode, pkgBoundaryMode, false, !fileToTraverse.isSourceArtifact());
+ symlinkBehaviorMode, pkgBoundaryMode, strictFilesetOutput, false,
+ !fileToTraverse.isSourceArtifact());
}
/**
@@ -175,11 +178,12 @@ public final class FilesetTraversalParamsFactory {
@Nullable Set<String> excludes,
SymlinkBehavior symlinkBehaviorMode,
PackageBoundaryMode pkgBoundaryMode,
+ boolean strictFilesetOutput,
boolean isRecursive,
boolean isGenerated) {
DirectTraversal traversal = DirectTraversal.getDirectTraversal(root, isPackage,
- symlinkBehaviorMode == SymlinkBehavior.DEREFERENCE, pkgBoundaryMode, isRecursive,
- isGenerated);
+ symlinkBehaviorMode == SymlinkBehavior.DEREFERENCE, pkgBoundaryMode, strictFilesetOutput,
+ isRecursive, isGenerated);
return create(ownerLabel, destPath, getOrderedExcludes(excludes), Optional.of(traversal));
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index e7443ea677..38e446ca3c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -420,6 +420,17 @@ public class BuildConfiguration implements BuildConfigurationApi {
public boolean strictFilesets;
@Option(
+ name = "experimental_strict_fileset_output",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
+ effectTags = {OptionEffectTag.EXECUTION},
+ help =
+ "If this option is enabled, filesets will treat all output artifacts as regular files. "
+ + "They will not traverse directories or be sensitive to symlinks."
+ )
+ public boolean strictFilesetOutput;
+
+ @Option(
name = "stamp",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
@@ -1475,6 +1486,10 @@ public class BuildConfiguration implements BuildConfigurationApi {
return options.strictFilesets;
}
+ public boolean isStrictFilesetOutput() {
+ return options.strictFilesetOutput;
+ }
+
public String getMainRepositoryName() {
return mainRepositoryName.strippedName();
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
index bc91ed7e9c..22f5b31935 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
@@ -243,6 +243,7 @@ public final class FilesetEntryFunction implements SkyFunction {
traversal.getRoot(),
traversal.isGenerated(),
traversal.getPackageBoundaryMode(),
+ traversal.isStrictFilesetOutput(),
traversal.isPackage(),
errorInfo);
RecursiveFilesystemTraversalValue v = (RecursiveFilesystemTraversalValue) env.getValue(depKey);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
index 070b83141b..c4a23b3483 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
@@ -245,33 +245,38 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction {
}
}
- // FileArtifactValue does not currently track symlinks. If it did, we could potentially remove
- // some of the filesystem operations we're doing here.
- Path path = traversal.root.asRootedPath().asPath();
- FileStatus noFollowStat = path.stat(Symlinks.NOFOLLOW);
- FileStatus followStat = path.statIfFound(Symlinks.FOLLOW);
- FileType type;
- PathFragment unresolvedLinkTarget = null;
RootedPath realPath = traversal.root.asRootedPath();
- if (followStat == null) {
- type = FileType.DANGLING_SYMLINK;
- if (!noFollowStat.isSymbolicLink()) {
- throw new IOException("Expected symlink for " + path + ", but got: " + noFollowStat);
- }
- unresolvedLinkTarget = path.readSymbolicLink();
- } else if (noFollowStat.isFile()) {
- type = FileType.FILE;
- } else if (noFollowStat.isDirectory()) {
- type = FileType.DIRECTORY;
+ if (traversal.strictOutputFiles) {
+ Preconditions.checkNotNull(fsVal, "Strict Fileset output tree has null FileArtifactValue");
+ return new FileInfo(FileType.FILE, fsVal, realPath, null);
} else {
- unresolvedLinkTarget = path.readSymbolicLink();
- realPath = RootedPath.toRootedPath(
- Root.absoluteRoot(path.getFileSystem()),
- path.resolveSymbolicLinks());
- type = followStat.isFile() ? FileType.SYMLINK_TO_FILE : FileType.SYMLINK_TO_DIRECTORY;
+ // FileArtifactValue does not currently track symlinks. If it did, we could potentially
+ // remove some of the filesystem operations we're doing here.
+ Path path = traversal.root.asRootedPath().asPath();
+ FileStatus noFollowStat = path.stat(Symlinks.NOFOLLOW);
+ FileStatus followStat = path.statIfFound(Symlinks.FOLLOW);
+ FileType type;
+ PathFragment unresolvedLinkTarget = null;
+ if (followStat == null) {
+ type = FileType.DANGLING_SYMLINK;
+ if (!noFollowStat.isSymbolicLink()) {
+ throw new IOException("Expected symlink for " + path + ", but got: " + noFollowStat);
+ }
+ unresolvedLinkTarget = path.readSymbolicLink();
+ } else if (noFollowStat.isFile()) {
+ type = FileType.FILE;
+ } else if (noFollowStat.isDirectory()) {
+ type = FileType.DIRECTORY;
+ } else {
+ unresolvedLinkTarget = path.readSymbolicLink();
+ realPath =
+ RootedPath.toRootedPath(
+ Root.absoluteRoot(path.getFileSystem()), path.resolveSymbolicLinks());
+ type = followStat.isFile() ? FileType.SYMLINK_TO_FILE : FileType.SYMLINK_TO_DIRECTORY;
+ }
+ return new FileInfo(
+ type, fsVal != null ? fsVal : noFollowStat.hashCode(), realPath, unresolvedLinkTarget);
}
- return new FileInfo(
- type, fsVal != null ? fsVal : noFollowStat.hashCode(), realPath, unresolvedLinkTarget);
} else {
// Stat the file.
FileValue fileValue =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
index 94041f9bc9..c849f10ec9 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
@@ -124,6 +124,9 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
/** Whether traversal should descend into directories that are roots of subpackages. */
final PackageBoundaryMode crossPkgBoundaries;
+ /** Whether Fileset assumes that output Artifacts are regular files. */
+ final boolean strictOutputFiles;
+
/**
* Whether to skip checking if the root (if it's a directory) contains a BUILD file.
*
@@ -140,11 +143,13 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
DirectTraversalRoot root,
boolean isRootGenerated,
PackageBoundaryMode crossPkgBoundaries,
+ boolean strictOutputFiles,
boolean skipTestingForSubpackage,
@Nullable String errorInfo) {
this.root = root;
this.isRootGenerated = isRootGenerated;
this.crossPkgBoundaries = crossPkgBoundaries;
+ this.strictOutputFiles = strictOutputFiles;
this.skipTestingForSubpackage = skipTestingForSubpackage;
this.errorInfo = errorInfo;
}
@@ -155,17 +160,20 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
DirectTraversalRoot root,
boolean isRootGenerated,
PackageBoundaryMode crossPkgBoundaries,
+ boolean strictOutputFiles,
boolean skipTestingForSubpackage,
@Nullable String errorInfo) {
return interner.intern(
new TraversalRequest(
- root, isRootGenerated, crossPkgBoundaries, skipTestingForSubpackage, errorInfo));
+ root, isRootGenerated, crossPkgBoundaries, strictOutputFiles,
+ skipTestingForSubpackage, errorInfo));
}
private TraversalRequest duplicate(DirectTraversalRoot newRoot,
boolean newSkipTestingForSubpackage) {
return create(
- newRoot, isRootGenerated, crossPkgBoundaries, newSkipTestingForSubpackage, errorInfo);
+ newRoot, isRootGenerated, crossPkgBoundaries, strictOutputFiles,
+ newSkipTestingForSubpackage, errorInfo);
}
/** Creates a new request to traverse a child element in the current directory (the root). */
@@ -198,20 +206,23 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
return root.equals(o.root)
&& isRootGenerated == o.isRootGenerated
&& crossPkgBoundaries == o.crossPkgBoundaries
+ && strictOutputFiles == o.strictOutputFiles
&& skipTestingForSubpackage == o.skipTestingForSubpackage;
}
@Override
public int hashCode() {
- return Objects.hashCode(root, isRootGenerated, crossPkgBoundaries, skipTestingForSubpackage);
+ return Objects.hashCode(root, isRootGenerated, crossPkgBoundaries, strictOutputFiles,
+ skipTestingForSubpackage);
}
@Override
public String toString() {
return String.format(
"TraversalParams(root=%s, is_generated=%d, skip_testing_for_subpkg=%d,"
- + " pkg_boundaries=%s)",
- root, isRootGenerated ? 1 : 0, skipTestingForSubpackage ? 1 : 0, crossPkgBoundaries);
+ + " pkg_boundaries=%s, strictOutputFiles=%d)",
+ root, isRootGenerated ? 1 : 0, skipTestingForSubpackage ? 1 : 0, crossPkgBoundaries,
+ strictOutputFiles ? 1 : 0);
}
@Override