/* * Copyright 2012-present Facebook, Inc. * * 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.facebook.buck.model; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import com.facebook.buck.config.Config; import com.facebook.buck.config.ConfigBuilder; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.testutil.integration.TemporaryPaths; import com.google.common.collect.ImmutableSet; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.Optional; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; public class FilesystemBackedBuildFileTreeTest { @Rule public TemporaryPaths tmp = new TemporaryPaths(); @Test @Ignore("Remove when test passes on OS X (the case preserving file system hurts us)") public void testCanConstructBuildFileTreeFromFilesystemOnOsX() throws InterruptedException, IOException { Path tempDir = tmp.getRoot(); ProjectFilesystem filesystem = new ProjectFilesystem(tempDir); Path command = tempDir.resolve("src/com/facebook/buck/command"); Files.createDirectories(command); Path notbuck = tempDir.resolve("src/com/facebook/buck/notbuck"); Files.createDirectories(notbuck); // Although these next two lines create a file and a directory, the OS X filesystem is often // case insensitive. As we run File.listFiles only the directory entry is returned. Thanks OS X. touch(tempDir.resolve("src/com/facebook/BUCK")); touch(tempDir.resolve("src/com/facebook/buck/BUCK")); touch(tempDir.resolve("src/com/facebook/buck/command/BUCK")); touch(tempDir.resolve("src/com/facebook/buck/notbuck/BUCK")); BuildFileTree buildFiles = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Iterable<Path> allChildren = buildFiles.getChildPaths(BuildTarget.builder(tmp.getRoot(), "src", "com/facebook").build()); assertEquals(ImmutableSet.of(Paths.get("buck")), ImmutableSet.copyOf(allChildren)); Iterable<Path> subChildren = buildFiles.getChildPaths( BuildTarget.builder(tmp.getRoot(), "//src", "/com/facebook/buck").build()); assertEquals( ImmutableSet.of(Paths.get("command"), Paths.get("notbuck")), ImmutableSet.copyOf(subChildren)); } @Test public void testCanConstructBuildFileTreeFromFilesystem() throws InterruptedException, IOException { Path tempDir = tmp.getRoot(); ProjectFilesystem filesystem = new ProjectFilesystem(tempDir); Path command = tempDir.resolve("src/com/example/build/command"); Files.createDirectories(command); Path notbuck = tempDir.resolve("src/com/example/build/notbuck"); Files.createDirectories(notbuck); Files.createDirectories(tempDir.resolve("src/com/example/some/directory")); touch(tempDir.resolve("src/com/example/BUCK")); touch(tempDir.resolve("src/com/example/build/BUCK")); touch(tempDir.resolve("src/com/example/build/command/BUCK")); touch(tempDir.resolve("src/com/example/build/notbuck/BUCK")); touch(tempDir.resolve("src/com/example/some/directory/BUCK")); BuildFileTree buildFiles = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Collection<Path> allChildren = buildFiles.getChildPaths(BuildTargetFactory.newInstance("//src/com/example:example")); assertEquals( ImmutableSet.of(Paths.get("build"), Paths.get("some/directory")), ImmutableSet.copyOf(allChildren)); Iterable<Path> subChildren = buildFiles.getChildPaths(BuildTargetFactory.newInstance("//src/com/example/build:build")); assertEquals( ImmutableSet.of(Paths.get("command"), Paths.get("notbuck")), ImmutableSet.copyOf(subChildren)); assertEquals( Paths.get("src/com/example"), buildFiles.getBasePathOfAncestorTarget(Paths.get("src/com/example/foo")).get()); assertEquals( Paths.get("src/com/example"), buildFiles.getBasePathOfAncestorTarget(Paths.get("src/com/example/some/bar")).get()); assertEquals( Paths.get("src/com/example/some/directory"), buildFiles .getBasePathOfAncestorTarget(Paths.get("src/com/example/some/directory/baz")) .get()); } @Test public void respectsIgnorePaths() throws InterruptedException, IOException { Path tempDir = tmp.getRoot(); Path fooBuck = tempDir.resolve("foo/BUCK"); Path fooBarBuck = tempDir.resolve("foo/bar/BUCK"); Path fooBazBuck = tempDir.resolve("foo/baz/BUCK"); Files.createDirectories(fooBarBuck.getParent()); Files.createDirectories(fooBazBuck.getParent()); touch(fooBuck); touch(fooBarBuck); touch(fooBazBuck); Config config = ConfigBuilder.createFromText("[project]", "ignore = foo/bar"); ProjectFilesystem filesystem = new ProjectFilesystem(tempDir, config); BuildFileTree buildFiles = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Collection<Path> children = buildFiles.getChildPaths(BuildTarget.builder(tempDir, "//foo", "foo").build()); assertEquals(ImmutableSet.of(Paths.get("baz")), children); Path ancestor = buildFiles.getBasePathOfAncestorTarget(Paths.get("foo/bar/xyzzy")).get(); assertEquals(Paths.get("foo"), ancestor); } @Test public void rootBasePath() throws InterruptedException, IOException { Path root = tmp.getRoot(); Files.createFile(root.resolve("BUCK")); Files.createDirectory(root.resolve("foo")); Files.createFile(root.resolve("foo/BUCK")); ProjectFilesystem filesystem = new ProjectFilesystem(root); BuildFileTree buildFileTree = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Optional<Path> ancestor = buildFileTree.getBasePathOfAncestorTarget(Paths.get("bar/baz")); assertEquals(Optional.of(Paths.get("")), ancestor); } @Test public void missingBasePath() throws InterruptedException, IOException { Path root = tmp.getRoot(); Files.createDirectory(root.resolve("foo")); Files.createFile(root.resolve("foo/BUCK")); ProjectFilesystem filesystem = new ProjectFilesystem(root); BuildFileTree buildFileTree = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Optional<Path> ancestor = buildFileTree.getBasePathOfAncestorTarget(Paths.get("bar/baz")); assertEquals(Optional.empty(), ancestor); } @Test public void shouldIgnoreBuckOutputDirectoriesByDefault() throws InterruptedException, IOException { Path root = tmp.getRoot(); ProjectFilesystem filesystem = new ProjectFilesystem(root, new Config()); Path buckOut = root.resolve(filesystem.getBuckPaths().getBuckOut()); Files.createDirectories(buckOut); touch(buckOut.resolve("BUCK")); Path sibling = buckOut.resolve("someFile"); touch(sibling); // Config doesn't set any "ignore" entries. BuildFileTree buildFileTree = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Optional<Path> ancestor = buildFileTree.getBasePathOfAncestorTarget( filesystem.getBuckPaths().getBuckOut().resolve("someFile")); assertFalse(ancestor.isPresent()); } @Test public void shouldIgnoreBuckCacheDirectoriesByDefault() throws InterruptedException, IOException { Path root = tmp.getRoot(); Path cacheDir = root.resolve("buck-out/cache"); Files.createDirectories(cacheDir); touch(cacheDir.resolve("BUCK")); Path sibling = cacheDir.resolve("someFile"); touch(sibling); // Config doesn't set any "ignore" entries. ProjectFilesystem filesystem = new ProjectFilesystem(root, new Config()); BuildFileTree buildFileTree = new FilesystemBackedBuildFileTree(filesystem, "BUCK"); Optional<Path> ancestor = buildFileTree.getBasePathOfAncestorTarget(cacheDir.resolve("someFile")); assertFalse(ancestor.isPresent()); } private void touch(Path path) throws IOException { Files.write(path, "".getBytes(UTF_8)); } }