aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/SymlinkForest.java124
-rw-r--r--src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java3
-rw-r--r--src/test/java/com/google/devtools/build/lib/buildtool/BUILD1
-rw-r--r--src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java132
6 files changed, 196 insertions, 84 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
index a11cd65461..034651422b 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
@@ -18,7 +18,6 @@ import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.base.Throwables;
import com.google.common.base.Verify;
-import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.actions.TestExecException;
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
@@ -73,11 +72,8 @@ import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.Preconditions;
-import com.google.devtools.build.lib.vfs.Path;
-import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
@@ -204,7 +200,7 @@ public final class BuildTool {
if (needsExecutionPhase(request.getBuildOptions())) {
env.getSkyframeExecutor().injectTopLevelContext(request.getTopLevelArtifactContext());
executionTool.executeBuild(request.getId(), analysisResult, result,
- configurations, transformPackageRoots(analysisResult.getPackageRoots()));
+ configurations, analysisResult.getPackageRoots());
}
String delayedErrorMsg = analysisResult.getError();
@@ -299,15 +295,6 @@ public final class BuildTool {
}
}
- private ImmutableMap<PathFragment, Path> transformPackageRoots(
- ImmutableMap<PackageIdentifier, Path> packageRoots) {
- ImmutableMap.Builder<PathFragment, Path> builder = ImmutableMap.builder();
- for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
- builder.put(entry.getKey().getPathFragment(), entry.getValue());
- }
- return builder.build();
- }
-
private void reportExceptionError(Exception e) {
if (e.getMessage() != null) {
getReporter().handle(Event.error(e.getMessage()));
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
index 76706bc538..0a8a0cbbb9 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
@@ -61,6 +61,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
import com.google.devtools.build.lib.buildtool.buildevent.ExecutionPhaseCompleteEvent;
import com.google.devtools.build.lib.buildtool.buildevent.ExecutionStartingEvent;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.EventKind;
@@ -335,7 +336,7 @@ public class ExecutionTool {
void executeBuild(UUID buildId, AnalysisResult analysisResult,
BuildResult buildResult,
BuildConfigurationCollection configurations,
- ImmutableMap<PathFragment, Path> packageRoots)
+ ImmutableMap<PackageIdentifier, Path> packageRoots)
throws BuildFailedException, InterruptedException, TestExecException, AbruptExitException {
Stopwatch timer = Stopwatch.createStarted();
prepare(packageRoots);
@@ -495,7 +496,7 @@ public class ExecutionTool {
}
}
- private void prepare(ImmutableMap<PathFragment, Path> packageRoots)
+ private void prepare(ImmutableMap<PackageIdentifier, Path> packageRoots)
throws ExecutorInitException {
// Prepare for build.
Profiler.instance().markPhase(ProfilePhase.PREPARE);
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/SymlinkForest.java b/src/main/java/com/google/devtools/build/lib/buildtool/SymlinkForest.java
index ceeb77a726..5c8ff90565 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/SymlinkForest.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/SymlinkForest.java
@@ -16,9 +16,13 @@ package com.google.devtools.build.lib.buildtool;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.concurrent.ThreadSafety;
+import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -37,13 +41,13 @@ class SymlinkForest {
private static final Logger LOG = Logger.getLogger(SymlinkForest.class.getName());
private static final boolean LOG_FINER = LOG.isLoggable(Level.FINER);
- private final ImmutableMap<PathFragment, Path> packageRoots;
+ private final ImmutableMap<PackageIdentifier, Path> packageRoots;
private final Path workspace;
private final String productName;
private final String[] prefixes;
SymlinkForest(
- ImmutableMap<PathFragment, Path> packageRoots, Path workspace, String productName) {
+ ImmutableMap<PackageIdentifier, Path> packageRoots, Path workspace, String productName) {
this.packageRoots = packageRoots;
this.workspace = workspace;
this.productName = productName;
@@ -54,11 +58,14 @@ class SymlinkForest {
* Returns the longest prefix from a given set of 'prefixes' that are
* contained in 'path'. I.e the closest ancestor directory containing path.
* Returns null if none found.
+ * @param path
+ * @param prefixes
*/
@VisibleForTesting
- static PathFragment longestPathPrefix(PathFragment path, Set<PathFragment> prefixes) {
- for (int i = path.segmentCount(); i >= 0; i--) {
- PathFragment prefix = path.subFragment(0, i);
+ static PackageIdentifier longestPathPrefix(
+ PackageIdentifier path, ImmutableSet<PackageIdentifier> prefixes) {
+ for (int i = path.getPackageFragment().segmentCount(); i >= 0; i--) {
+ PackageIdentifier prefix = createInRepo(path, path.getPackageFragment().subFragment(0, i));
if (prefixes.contains(prefix)) {
return prefix;
}
@@ -76,8 +83,8 @@ class SymlinkForest {
dirloop:
for (Path p : dir.getDirectoryEntries()) {
String name = p.getBaseName();
- for (int i = 0; i < prefixes.length; i++) {
- if (name.startsWith(prefixes[i])) {
+ for (String prefix : prefixes) {
+ if (name.startsWith(prefix)) {
continue dirloop;
}
}
@@ -87,20 +94,20 @@ class SymlinkForest {
void plantSymlinkForest() throws IOException {
deleteTreesBelowNotPrefixed(workspace, prefixes);
- Path emptyPackagePath = null;
// Create a sorted map of all dirs (packages and their ancestors) to sets of their roots.
// Packages come from exactly one root, but their shared ancestors may come from more.
// The map is maintained sorted lexicographically, so parents are before their children.
- Map<PathFragment, Set<Path>> dirRootsMap = Maps.newTreeMap();
- for (Map.Entry<PathFragment, Path> entry : packageRoots.entrySet()) {
- PathFragment pkgDir = entry.getKey();
+ Map<PackageIdentifier, Set<Path>> dirRootsMap = Maps.newTreeMap();
+ for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
+ PackageIdentifier pkgId = entry.getKey();
Path pkgRoot = entry.getValue();
- if (pkgDir.segmentCount() == 0) {
- emptyPackagePath = entry.getValue();
- }
- for (int i = 1; i <= pkgDir.segmentCount(); i++) {
- PathFragment dir = pkgDir.subFragment(0, i);
+ for (int i = 1; i <= pkgId.getPackageFragment().segmentCount(); i++) {
+ if (pkgId.equals(Label.EXTERNAL_PACKAGE_IDENTIFIER)) {
+ // This isn't a "real" package, don't add it to the symlink tree.
+ continue;
+ }
+ PackageIdentifier dir = createInRepo(pkgId, pkgId.getPackageFragment().subFragment(0, i));
Set<Path> roots = dirRootsMap.get(dir);
if (roots == null) {
roots = Sets.newHashSet();
@@ -110,59 +117,68 @@ class SymlinkForest {
}
}
// Now add in roots for all non-pkg dirs that are in between two packages, and missed above.
- for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) {
- PathFragment dir = entry.getKey();
+ for (Map.Entry<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
+ PackageIdentifier dir = entry.getKey();
if (!packageRoots.containsKey(dir)) {
- PathFragment pkgDir = longestPathPrefix(dir, packageRoots.keySet());
- if (pkgDir != null) {
- entry.getValue().add(packageRoots.get(pkgDir));
+ PackageIdentifier pkgId = longestPathPrefix(dir, packageRoots.keySet());
+ if (pkgId != null) {
+ entry.getValue().add(packageRoots.get(pkgId));
}
}
}
// Create output dirs for all dirs that have more than one root and need to be split.
- for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) {
- PathFragment dir = entry.getKey();
+ for (Map.Entry<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
+ PackageIdentifier dir = entry.getKey();
+ if (!dir.getRepository().isMain()) {
+ FileSystemUtils.createDirectoryAndParents(
+ workspace.getRelative(dir.getRepository().getPathFragment()));
+ }
if (entry.getValue().size() > 1) {
if (LOG_FINER) {
- LOG.finer("mkdir " + workspace.getRelative(dir));
+ LOG.finer("mkdir " + workspace.getRelative(dir.getPathFragment()));
}
- FileSystemUtils.createDirectoryAndParents(workspace.getRelative(dir));
+ FileSystemUtils.createDirectoryAndParents(workspace.getRelative(dir.getPathFragment()));
}
}
+
// Make dir links for single rooted dirs.
- for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) {
- PathFragment dir = entry.getKey();
+ for (Map.Entry<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
+ PackageIdentifier dir = entry.getKey();
Set<Path> roots = entry.getValue();
// Simple case of one root for this dir.
if (roots.size() == 1) {
- if (dir.segmentCount() > 1 && dirRootsMap.get(dir.getParentDirectory()).size() == 1) {
+ if (dir.getPackageFragment().segmentCount() > 1
+ && dirRootsMap.get(getParent(dir)).size() == 1) {
continue; // skip--an ancestor will link this one in from above
}
// This is the top-most dir that can be linked to a single root. Make it so.
Path root = roots.iterator().next(); // lone root in set
if (LOG_FINER) {
- LOG.finer("ln -s " + root.getRelative(dir) + " " + workspace.getRelative(dir));
+ LOG.finer("ln -s " + root.getRelative(dir.getPathFragment()) + " "
+ + workspace.getRelative(dir.getPathFragment()));
}
- workspace.getRelative(dir).createSymbolicLink(root.getRelative(dir));
+ workspace.getRelative(dir.getPathFragment())
+ .createSymbolicLink(root.getRelative(dir.getPathFragment()));
}
}
// Make links for dirs within packages, skip parent-only dirs.
- for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) {
- PathFragment dir = entry.getKey();
+ for (Map.Entry<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
+ PackageIdentifier dir = entry.getKey();
if (entry.getValue().size() > 1) {
// If this dir is at or below a package dir, link in its contents.
- PathFragment pkgDir = longestPathPrefix(dir, packageRoots.keySet());
- if (pkgDir != null) {
- Path root = packageRoots.get(pkgDir);
+ PackageIdentifier pkgId = longestPathPrefix(dir, packageRoots.keySet());
+ if (pkgId != null) {
+ Path root = packageRoots.get(pkgId);
try {
- Path absdir = root.getRelative(dir);
+ Path absdir = root.getRelative(dir.getPathFragment());
if (absdir.isDirectory()) {
if (LOG_FINER) {
- LOG.finer("ln -s " + absdir + "/* " + workspace.getRelative(dir) + "/");
+ LOG.finer("ln -s " + absdir + "/* "
+ + workspace.getRelative(dir.getPathFragment()) + "/");
}
for (Path target : absdir.getDirectoryEntries()) {
PathFragment p = target.relativeTo(root);
- if (!dirRootsMap.containsKey(p)) {
+ if (!dirRootsMap.containsKey(createInRepo(pkgId, p))) {
//LOG.finest("ln -s " + target + " " + linkRoot.getRelative(p));
workspace.getRelative(p).createSymbolicLink(target);
}
@@ -178,17 +194,39 @@ class SymlinkForest {
}
}
- if (emptyPackagePath != null) {
+ for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
+ PackageIdentifier pkgId = entry.getKey();
+ if (!pkgId.getPackageFragment().equals(PathFragment.EMPTY_FRAGMENT)) {
+ continue;
+ }
+ Path execrootDirectory = workspace.getRelative(pkgId.getPathFragment());
+ // If there were no subpackages, this directory might not exist yet.
+ if (!execrootDirectory.exists()) {
+ FileSystemUtils.createDirectoryAndParents(execrootDirectory);
+ }
// For the top-level directory, generate symlinks to everything in the directory instead of
// the directory itself.
- for (Path target : emptyPackagePath.getDirectoryEntries()) {
+ Path sourceDirectory = entry.getValue().getRelative(pkgId.getPathFragment());
+ for (Path target : sourceDirectory.getDirectoryEntries()) {
String baseName = target.getBaseName();
+ Path execPath = execrootDirectory.getRelative(baseName);
// Create any links that don't exist yet and don't start with bazel-.
- if (!baseName.startsWith(productName + "-")
- && !workspace.getRelative(baseName).exists()) {
- workspace.getRelative(baseName).createSymbolicLink(target);
+ if (!baseName.startsWith(productName + "-") && !execPath.exists()) {
+ execPath.createSymbolicLink(target);
}
}
}
}
+
+ private static PackageIdentifier getParent(PackageIdentifier packageIdentifier) {
+ Preconditions.checkArgument(
+ packageIdentifier.getPackageFragment().getParentDirectory() != null);
+ return createInRepo(
+ packageIdentifier, packageIdentifier.getPackageFragment().getParentDirectory());
+ }
+
+ private static PackageIdentifier createInRepo(
+ PackageIdentifier repo, PathFragment packageFragment) {
+ return PackageIdentifier.create(repo.getRepository(), packageFragment);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
index 74cd6fa8d7..6445f48b32 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
@@ -38,7 +38,6 @@ public final class PackageIdentifier implements Comparable<PackageIdentifier>, S
private static final Interner<PackageIdentifier> INTERNER = Interners.newWeakInterner();
-
public static PackageIdentifier create(String repository, PathFragment pkgName)
throws LabelSyntaxException {
return create(RepositoryName.create(repository), pkgName);
@@ -51,11 +50,13 @@ public final class PackageIdentifier implements Comparable<PackageIdentifier>, S
public static final String DEFAULT_REPOSITORY = "";
public static final RepositoryName DEFAULT_REPOSITORY_NAME;
public static final RepositoryName MAIN_REPOSITORY_NAME;
+ public static final PackageIdentifier EMPTY_PACKAGE_ID;
static {
try {
DEFAULT_REPOSITORY_NAME = RepositoryName.create(DEFAULT_REPOSITORY);
MAIN_REPOSITORY_NAME = RepositoryName.create("@");
+ EMPTY_PACKAGE_ID = createInMainRepo(PathFragment.EMPTY_FRAGMENT);
} catch (LabelSyntaxException e) {
throw new IllegalStateException(e);
}
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/BUILD b/src/test/java/com/google/devtools/build/lib/buildtool/BUILD
index 3b4268ade6..dc1559e4ce 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/BUILD
@@ -23,5 +23,6 @@ java_test(
"//src/test/java/com/google/devtools/build/lib:packages_testutil",
"//src/test/java/com/google/devtools/build/lib:testutil",
"//third_party:junit4",
+ "//third_party:truth",
],
)
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java b/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
index 7ea95a4c3e..b3a66c50a7 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.buildtool;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.vfs.FileSystemUtils.createDirectoryAndParents;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -20,6 +21,11 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.vfs.FileSystem;
@@ -35,8 +41,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
/**
* Tests {@link SymlinkForest}.
@@ -50,10 +54,15 @@ public class SymlinkForestTest {
private Path file2;
private Path aDir;
+ // The execution root.
+ private Path linkRoot;
+
@Before
- public final void initializeFileSystem() throws Exception {
+ public final void initializeFileSystem() throws Exception {
ManualClock clock = new ManualClock();
fileSystem = new InMemoryFileSystem(clock);
+ linkRoot = fileSystem.getPath("/linkRoot");
+ createDirectoryAndParents(linkRoot);
}
/*
@@ -95,12 +104,13 @@ public class SymlinkForestTest {
}
private static String longestPathPrefixStr(String path, String... prefixStrs) {
- Set<PathFragment> prefixes = new HashSet<>();
+ ImmutableSet.Builder<PackageIdentifier> prefixes = ImmutableSet.builder();
for (String prefix : prefixStrs) {
- prefixes.add(new PathFragment(prefix));
+ prefixes.add(PackageIdentifier.createInMainRepo(prefix));
}
- PathFragment longest = SymlinkForest.longestPathPrefix(new PathFragment(path), prefixes);
- return longest != null ? longest.getPathString() : null;
+ PackageIdentifier longest = SymlinkForest.longestPathPrefix(
+ PackageIdentifier.createInMainRepo(path), prefixes.build());
+ return longest != null ? longest.getPackageFragment().getPathString() : null;
}
@Test
@@ -117,13 +127,13 @@ public class SymlinkForestTest {
@Test
public void testDeleteTreesBelowNotPrefixed() throws IOException {
createTestDirectoryTree();
- SymlinkForest.deleteTreesBelowNotPrefixed(topDir, new String[] { "file-"});
+ SymlinkForest.deleteTreesBelowNotPrefixed(topDir, new String[]{"file-"});
assertTrue(file1.exists());
assertTrue(file2.exists());
assertFalse(aDir.exists());
}
- private PathFragment createPkg(Path rootA, Path rootB, String pkg) throws IOException {
+ private PackageIdentifier createPkg(Path rootA, Path rootB, String pkg) throws IOException {
if (rootA != null) {
createDirectoryAndParents(rootA.getRelative(pkg));
FileSystemUtils.createEmptyFile(rootA.getRelative(pkg).getChild("file"));
@@ -132,13 +142,26 @@ public class SymlinkForestTest {
createDirectoryAndParents(rootB.getRelative(pkg));
FileSystemUtils.createEmptyFile(rootB.getRelative(pkg).getChild("file"));
}
- return new PathFragment(pkg);
+ return PackageIdentifier.createInMainRepo(pkg);
+ }
+
+ private PackageIdentifier createPkg(Path root, String repo, String pkg)
+ throws IOException, LabelSyntaxException {
+ if (root != null) {
+ Path repoRoot = root.getRelative(Label.EXTERNAL_PACKAGE_NAME).getRelative(repo);
+ createDirectoryAndParents(repoRoot.getRelative(pkg));
+ FileSystemUtils.createEmptyFile(repoRoot.getRelative(pkg).getChild("file"));
+ }
+ return PackageIdentifier.create(RepositoryName.create("@" + repo), new PathFragment(pkg));
}
private void assertLinksTo(Path fromRoot, Path toRoot, String relpart) throws IOException {
- assertTrue(fromRoot.getRelative(relpart).isSymbolicLink());
- assertEquals(toRoot.getRelative(relpart).asFragment(),
- fromRoot.getRelative(relpart).readSymbolicLink());
+ assertLinksTo(fromRoot.getRelative(relpart), toRoot.getRelative(relpart));
+ }
+
+ private void assertLinksTo(Path fromRoot, Path toRoot) throws IOException {
+ assertTrue("stat: " + fromRoot.stat(), fromRoot.isSymbolicLink());
+ assertEquals(toRoot.asFragment(), fromRoot.readSymbolicLink());
}
private void assertIsDir(Path root, String relpart) {
@@ -150,17 +173,18 @@ public class SymlinkForestTest {
Path rootA = fileSystem.getPath("/A");
Path rootB = fileSystem.getPath("/B");
- ImmutableMap<PathFragment, Path> packageRootMap = ImmutableMap.<PathFragment, Path>builder()
- .put(createPkg(rootA, rootB, "pkgA"), rootA)
- .put(createPkg(rootA, rootB, "dir1/pkgA"), rootA)
- .put(createPkg(rootA, rootB, "dir1/pkgB"), rootB)
- .put(createPkg(rootA, rootB, "dir2/pkg"), rootA)
- .put(createPkg(rootA, rootB, "dir2/pkg/pkg"), rootB)
- .put(createPkg(rootA, rootB, "pkgB"), rootB)
- .put(createPkg(rootA, rootB, "pkgB/dir/pkg"), rootA)
- .put(createPkg(rootA, rootB, "pkgB/pkg"), rootA)
- .put(createPkg(rootA, rootB, "pkgB/pkg/pkg"), rootA)
- .build();
+ ImmutableMap<PackageIdentifier, Path> packageRootMap =
+ ImmutableMap.<PackageIdentifier, Path>builder()
+ .put(createPkg(rootA, rootB, "pkgA"), rootA)
+ .put(createPkg(rootA, rootB, "dir1/pkgA"), rootA)
+ .put(createPkg(rootA, rootB, "dir1/pkgB"), rootB)
+ .put(createPkg(rootA, rootB, "dir2/pkg"), rootA)
+ .put(createPkg(rootA, rootB, "dir2/pkg/pkg"), rootB)
+ .put(createPkg(rootA, rootB, "pkgB"), rootB)
+ .put(createPkg(rootA, rootB, "pkgB/dir/pkg"), rootA)
+ .put(createPkg(rootA, rootB, "pkgB/pkg"), rootA)
+ .put(createPkg(rootA, rootB, "pkgB/pkg/pkg"), rootA)
+ .build();
createPkg(rootA, rootB, "pkgB/dir"); // create a file in there
Path linkRoot = fileSystem.getPath("/linkRoot");
@@ -181,4 +205,64 @@ public class SymlinkForestTest {
assertLinksTo(linkRoot, rootA, "pkgB/dir/pkg");
assertLinksTo(linkRoot, rootA, "pkgB/pkg");
}
+
+ @Test
+ public void testTopLevelPackage() throws Exception {
+ Path rootX = fileSystem.getPath("/X");
+ Path rootY = fileSystem.getPath("/Y");
+ ImmutableMap<PackageIdentifier, Path> packageRootMap =
+ ImmutableMap.<PackageIdentifier, Path>builder()
+ .put(createPkg(rootX, rootY, ""), rootX)
+ .put(createPkg(rootX, rootY, "foo"), rootX)
+ .build();
+
+ new SymlinkForest(packageRootMap, linkRoot, TestConstants.PRODUCT_NAME).plantSymlinkForest();
+ assertLinksTo(linkRoot, rootX, "file");
+ }
+
+ @Test
+ public void testRemotePackage() throws Exception {
+ Path outputBase = fileSystem.getPath("/ob");
+ Path rootY = outputBase.getRelative(Label.EXTERNAL_PATH_PREFIX).getRelative("y");
+ Path rootZ = outputBase.getRelative(Label.EXTERNAL_PATH_PREFIX).getRelative("z");
+ Path rootW = outputBase.getRelative(Label.EXTERNAL_PATH_PREFIX).getRelative("w");
+ createDirectoryAndParents(rootY);
+ FileSystemUtils.createEmptyFile(rootY.getRelative("file"));
+
+ ImmutableMap<PackageIdentifier, Path> packageRootMap =
+ ImmutableMap.<PackageIdentifier, Path>builder()
+ // Remote repo without top-level package.
+ .put(createPkg(outputBase, "y", "w"), outputBase)
+ // Remote repo with and without top-level package.
+ .put(createPkg(outputBase, "z", ""), outputBase)
+ .put(createPkg(outputBase, "z", "a/b/c"), outputBase)
+ // Only top-level pkg.
+ .put(createPkg(outputBase, "w", ""), outputBase)
+ .build();
+
+ new SymlinkForest(packageRootMap, linkRoot, TestConstants.PRODUCT_NAME).plantSymlinkForest();
+ assertFalse(linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX + "/y/file").exists());
+ assertLinksTo(
+ linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX + "/y/w"), rootY.getRelative("w"));
+ assertLinksTo(
+ linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX + "/z/file"), rootZ.getRelative("file"));
+ assertLinksTo(
+ linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX + "/z/a"), rootZ.getRelative("a"));
+ assertLinksTo(
+ linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX + "/w/file"),
+ rootW.getRelative("file"));
+ }
+
+ @Test
+ public void testExternalPackage() throws Exception {
+ Path root = fileSystem.getPath("/src");
+ ImmutableMap<PackageIdentifier, Path> packageRootMap =
+ ImmutableMap.<PackageIdentifier, Path>builder()
+ // Virtual root, shouldn't actually be linked in.
+ .put(Label.EXTERNAL_PACKAGE_IDENTIFIER, root)
+ .build();
+
+ new SymlinkForest(packageRootMap, linkRoot, TestConstants.PRODUCT_NAME).plantSymlinkForest();
+ assertThat(linkRoot.getRelative(Label.EXTERNAL_PATH_PREFIX).exists()).isFalse();
+ }
}