use of com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest in project bazel by bazelbuild.
the class RecursiveFilesystemTraversalFunctionTest method assertTraverseSubpackages.
private void assertTraverseSubpackages(PackageBoundaryMode traverseSubpackages) throws Exception {
Artifact pkgDirArtifact = sourceArtifact("pkg1/foo");
Artifact subpkgDirArtifact = sourceArtifact("pkg1/foo/subdir/subpkg");
RootedPath pkgBuildFile = childOf(pkgDirArtifact, "BUILD");
RootedPath subpkgBuildFile = childOf(subpkgDirArtifact, "BUILD");
scratch.dir(rootedPath(pkgDirArtifact).asPath().getPathString());
scratch.dir(rootedPath(subpkgDirArtifact).asPath().getPathString());
createFile(pkgBuildFile);
createFile(subpkgBuildFile);
TraversalRequest traversalRoot = pkgRoot(parentOf(pkgBuildFile), traverseSubpackages);
ResolvedFile expected1 = regularFileForTesting(pkgBuildFile);
ResolvedFile expected2 = regularFileForTesting(subpkgBuildFile);
switch(traverseSubpackages) {
case CROSS:
traverseAndAssertFiles(traversalRoot, expected1, expected2);
break;
case DONT_CROSS:
traverseAndAssertFiles(traversalRoot, expected1);
break;
case REPORT_ERROR:
SkyKey key = rftvSkyKey(traversalRoot);
EvaluationResult<SkyValue> result = eval(key);
assertThat(result.hasError()).isTrue();
assertThat(result.getError().getException().getMessage()).contains("crosses package boundary into package rooted at");
break;
default:
throw new IllegalStateException(traverseSubpackages.toString());
}
}
use of com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest in project bazel by bazelbuild.
the class RecursiveFilesystemTraversalFunctionTest method assertTraversalOfDirectory.
private void assertTraversalOfDirectory(Artifact directoryArtifact) throws Exception {
// Create files under the directory.
// Use the root + root-relative path of the rootArtifact to create these files, rather than
// using the rootDirectory + execpath of the rootArtifact. The resulting paths are the same
// but the RootedPaths are different:
// in the 1st case, it is: RootedPath(/root/execroot, relative), in the second it is
// in the 2nd case, it is: RootedPath(/root, execroot/relative).
// Creating the files will also create the parent directories.
RootedPath file1 = createFile(childOf(directoryArtifact, "bar.txt"));
RootedPath file2 = createFile(childOf(directoryArtifact, "baz/qux.txt"));
TraversalRequest traversalRoot = fileLikeRoot(directoryArtifact, DONT_CROSS);
// Assert that the SkyValue is built and looks right.
ResolvedFile expected1 = regularFileForTesting(file1);
ResolvedFile expected2 = regularFileForTesting(file2);
RecursiveFilesystemTraversalValue v1 = traverseAndAssertFiles(traversalRoot, expected1, expected2);
assertThat(progressReceiver.invalidations).isEmpty();
assertThat(progressReceiver.evaluations).contains(v1);
progressReceiver.clear();
// Add a new file to the directory and see that the value is rebuilt.
RootedPath file3 = createFile(childOf(directoryArtifact, "foo.txt"));
invalidateDirectory(directoryArtifact);
ResolvedFile expected3 = regularFileForTesting(file3);
RecursiveFilesystemTraversalValue v2 = traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3);
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v2);
// Directories always have the same hash code, but that is fine because their contents are also
// part of the RecursiveFilesystemTraversalValue, so v1 and v2 are unequal.
assertThat(v2).isNotEqualTo(v1);
assertTraversalRootHashesAreEqual(v1, v2);
progressReceiver.clear();
// Edit a file in the directory and see that the value is rebuilt.
appendToFile(file1, "bar");
RecursiveFilesystemTraversalValue v3 = traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3);
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v3);
assertThat(v3).isNotEqualTo(v2);
// Directories always have the same hash code, but that is fine because their contents are also
// part of the RecursiveFilesystemTraversalValue, so v2 and v3 are unequal.
assertTraversalRootHashesAreEqual(v2, v3);
progressReceiver.clear();
// Add a new file *outside* of the directory and see that the value is *not* rebuilt.
Artifact someFile = sourceArtifact("somewhere/else/a.file");
createFile(someFile, "new file");
appendToFile(someFile, "not all changes are treated equal");
RecursiveFilesystemTraversalValue v4 = traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3);
assertThat(v4).isEqualTo(v3);
assertTraversalRootHashesAreEqual(v3, v4);
assertThat(progressReceiver.invalidations).doesNotContain(rftvSkyKey(traversalRoot));
}
use of com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest in project bazel by bazelbuild.
the class RecursiveFilesystemTraversalFunction method compute.
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws RecursiveFilesystemTraversalFunctionException, InterruptedException {
TraversalRequest traversal = (TraversalRequest) skyKey.argument();
try {
// Stat the traversal root.
FileInfo rootInfo = lookUpFileInfo(env, traversal);
if (!rootInfo.type.exists()) {
// May be a dangling symlink or a non-existent file. Handle gracefully.
if (rootInfo.type.isSymlink()) {
return resultForDanglingSymlink(traversal.path, rootInfo);
} else {
return RecursiveFilesystemTraversalValue.EMPTY;
}
}
if (rootInfo.type.isFile()) {
if (traversal.pattern == null || traversal.pattern.matcher(rootInfo.realPath.getRelativePath().getPathString()).matches()) {
// The root is a file or a symlink to one.
return resultForFileRoot(traversal.path, rootInfo);
} else {
return RecursiveFilesystemTraversalValue.EMPTY;
}
}
// Otherwise the root is a directory or a symlink to one.
PkgLookupResult pkgLookupResult = checkIfPackage(env, traversal, rootInfo);
traversal = pkgLookupResult.traversal;
if (pkgLookupResult.isConflicting()) {
// with a source package. We can't handle that, bail out.
throw new RecursiveFilesystemTraversalFunctionException(new GeneratedPathConflictException(traversal));
} else if (pkgLookupResult.isPackage() && !traversal.skipTestingForSubpackage) {
// The traversal was requested for a directory that defines a package.
String msg = traversal.errorInfo + " crosses package boundary into package rooted at " + traversal.path.getRelativePath().getPathString();
switch(traversal.crossPkgBoundaries) {
case CROSS:
// We are free to traverse the subpackage but we need to display a warning.
env.getListener().handle(Event.warn(null, msg));
break;
case DONT_CROSS:
// We cannot traverse the subpackage and should skip it silently. Return empty results.
return RecursiveFilesystemTraversalValue.EMPTY;
case REPORT_ERROR:
// We cannot traverse the subpackage and should complain loudly (display an error).
throw new RecursiveFilesystemTraversalFunctionException(new CannotCrossPackageBoundaryException(msg));
default:
throw new IllegalStateException(traversal.toString());
}
}
// We are free to traverse this directory.
Collection<SkyKey> dependentKeys = createRecursiveTraversalKeys(env, traversal);
return resultForDirectory(traversal, rootInfo, traverseChildren(env, dependentKeys));
} catch (MissingDepException e) {
return null;
}
}
use of com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest in project bazel by bazelbuild.
the class RecursiveFilesystemTraversalFunction method createRecursiveTraversalKeys.
/**
* List the directory and create {@code SkyKey}s to request contents of its children recursively.
*
* <p>The returned keys are of type {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL}.
*/
private static Collection<SkyKey> createRecursiveTraversalKeys(Environment env, TraversalRequest traversal) throws MissingDepException, InterruptedException {
// Use the traversal's path, even if it's a symlink. The contents of the directory, as listed
// in the result, must be relative to it.
DirectoryListingValue dirListing = (DirectoryListingValue) getDependentSkyValue(env, DirectoryListingValue.key(traversal.path));
List<SkyKey> result = new ArrayList<>();
for (Dirent dirent : dirListing.getDirents()) {
RootedPath childPath = RootedPath.toRootedPath(traversal.path.getRoot(), traversal.path.getRelativePath().getRelative(dirent.getName()));
TraversalRequest childTraversal = traversal.forChildEntry(childPath);
result.add(RecursiveFilesystemTraversalValue.key(childTraversal));
}
return result;
}
use of com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest in project bazel by bazelbuild.
the class RecursiveFilesystemTraversalFunctionTest method testRegexp.
@Test
public void testRegexp() throws Exception {
Artifact wantedArtifact = sourceArtifact("foo/bar/baz.txt");
Artifact unwantedArtifact = sourceArtifact("foo/boo/baztxt.bak");
RootedPath wantedPath = rootedPath(wantedArtifact);
createFile(wantedPath, "hello");
createFile(unwantedArtifact, "nope");
Artifact pkgDirArtifact = sourceArtifact("foo");
RootedPath dir = rootedPath(pkgDirArtifact);
scratch.dir(dir.asPath().getPathString());
TraversalRequest traversalRoot = new TraversalRequest(dir, false, PackageBoundaryMode.REPORT_ERROR, true, null, Pattern.compile(".*\\.txt"));
ResolvedFile expected = regularFileForTesting(wantedPath);
traverseAndAssertFiles(traversalRoot, expected);
}
Aggregations