diff options
author | Kristina Chodorow <kchodorow@google.com> | 2016-06-16 20:30:57 +0000 |
---|---|---|
committer | Yue Gan <yueg@google.com> | 2016-06-17 09:26:21 +0000 |
commit | bdfd58a8ca2ed5735d6aaa5b238fb0f689515724 (patch) | |
tree | fd40061fd63c6d4403d04e94af05d16ded2cab42 /src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java | |
parent | 3b62451a3c9e5eba3a892473d406cd02d84db5c3 (diff) |
Make the execution root match the runfiles tree structure for external repositories
One interesting side effect of how this is implemented is that for external
repositories, bin/ and genfiles/ are combined. External repo output is under
bazel-out/local-fastbuild/repo_name for each repo.
Fixes #1262.
RELNOTES[INC]: Previously, an external repository would be symlinked into the
execution root at execroot/local_repo/external/remote_repo. This changes it to
be at execroot/remote_repo. This may break genrules/Skylark actions that
hardcode execution root paths. If this causes breakages for you, ensure that
genrules are using $(location :target) to access files and Skylark rules are
using http://bazel.io/docs/skylark/lib/File.html's path, dirname, etc.
functions.
--
MOS_MIGRATED_REVID=125095799
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java | 139 |
1 files changed, 0 insertions, 139 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java index 0facfefde1..aaac85007c 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystemUtils.java @@ -16,9 +16,6 @@ package com.google.devtools.build.lib.vfs; import static java.nio.charset.StandardCharsets.ISO_8859_1; import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.common.io.ByteSink; import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; @@ -35,10 +32,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Helper functions that implement often-used complex operations on file @@ -47,9 +40,6 @@ import java.util.logging.Logger; @ConditionallyThreadSafe // ThreadSafe except for deleteTree. public class FileSystemUtils { - static final Logger LOG = Logger.getLogger(FileSystemUtils.class.getName()); - static final boolean LOG_FINER = LOG.isLoggable(Level.FINER); - private FileSystemUtils() {} /**************************************************************************** @@ -137,21 +127,6 @@ public class FileSystemUtils { } /** - * 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. - */ - static PathFragment longestPathPrefix(PathFragment path, Set<PathFragment> prefixes) { - for (int i = path.segmentCount(); i >= 0; i--) { - PathFragment prefix = path.subFragment(0, i); - if (prefixes.contains(prefix)) { - return prefix; - } - } - return null; - } - - /** * Removes the shortest suffix beginning with '.' from the basename of the * filename string. If the basename contains no '.', the filename is returned * unchanged. @@ -676,120 +651,6 @@ public class FileSystemUtils { return true; } - /** - * Takes a map of directory fragments to root paths, and creates a symlink - * forest under an existing linkRoot to the corresponding source dirs or - * files. Symlink are made at the highest dir possible, linking files directly - * only when needed with nested packages. - */ - public static void plantLinkForest(ImmutableMap<PathFragment, Path> packageRootMap, - Path linkRoot, String productName) - throws IOException { - 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 : packageRootMap.entrySet()) { - PathFragment pkgDir = 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); - Set<Path> roots = dirRootsMap.get(dir); - if (roots == null) { - roots = Sets.newHashSet(); - dirRootsMap.put(dir, roots); - } - roots.add(pkgRoot); - } - } - // 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(); - if (!packageRootMap.containsKey(dir)) { - PathFragment pkgDir = longestPathPrefix(dir, packageRootMap.keySet()); - if (pkgDir != null) { - entry.getValue().add(packageRootMap.get(pkgDir)); - } - } - } - // 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(); - if (entry.getValue().size() > 1) { - if (LOG_FINER) { - LOG.finer("mkdir " + linkRoot.getRelative(dir)); - } - createDirectoryAndParents(linkRoot.getRelative(dir)); - } - } - // Make dir links for single rooted dirs. - for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) { - PathFragment 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) { - 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) + " " + linkRoot.getRelative(dir)); - } - linkRoot.getRelative(dir).createSymbolicLink(root.getRelative(dir)); - } - } - // Make links for dirs within packages, skip parent-only dirs. - for (Map.Entry<PathFragment, Set<Path>> entry : dirRootsMap.entrySet()) { - PathFragment 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, packageRootMap.keySet()); - if (pkgDir != null) { - Path root = packageRootMap.get(pkgDir); - try { - Path absdir = root.getRelative(dir); - if (absdir.isDirectory()) { - if (LOG_FINER) { - LOG.finer("ln -s " + absdir + "/* " + linkRoot.getRelative(dir) + "/"); - } - for (Path target : absdir.getDirectoryEntries()) { - PathFragment p = target.relativeTo(root); - if (!dirRootsMap.containsKey(p)) { - //LOG.finest("ln -s " + target + " " + linkRoot.getRelative(p)); - linkRoot.getRelative(p).createSymbolicLink(target); - } - } - } else { - LOG.fine("Symlink planting skipping dir '" + absdir + "'"); - } - } catch (IOException e) { - e.printStackTrace(); - } - // Otherwise its just an otherwise empty common parent dir. - } - } - } - - if (emptyPackagePath != null) { - // For the top-level directory, generate symlinks to everything in the directory instead of - // the directory itself. - for (Path target : emptyPackagePath.getDirectoryEntries()) { - String baseName = target.getBaseName(); - // Create any links that don't exist yet and don't start with bazel-. - if (!baseName.startsWith(productName + "-") - && !linkRoot.getRelative(baseName).exists()) { - linkRoot.getRelative(baseName).createSymbolicLink(target); - } - } - } - } - /**************************************************************************** * Whole-file I/O utilities for characters and bytes. These convenience * methods are not efficient and should not be used for large amounts of data! |