use of com.google.devtools.build.lib.cmdline.PackageIdentifier in project bazel by bazelbuild.
the class SymlinkForest method plantSymlinkForest.
void plantSymlinkForest() throws IOException {
deleteTreesBelowNotPrefixed(workspace, prefixes);
// 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<PackageIdentifier, Set<Path>> dirRootsMap = Maps.newTreeMap();
for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
PackageIdentifier pkgId = entry.getKey();
Path pkgRoot = entry.getValue();
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();
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<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
PackageIdentifier dir = entry.getKey();
if (!packageRoots.containsKey(dir)) {
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<PackageIdentifier, Set<Path>> entry : dirRootsMap.entrySet()) {
PackageIdentifier dir = entry.getKey();
if (!dir.getRepository().isMain()) {
FileSystemUtils.createDirectoryAndParents(workspace.getRelative(dir.getRepository().getPathUnderExecRoot()));
}
if (entry.getValue().size() > 1) {
if (LOG_FINER) {
LOG.finer("mkdir " + workspace.getRelative(dir.getPathUnderExecRoot()));
}
FileSystemUtils.createDirectoryAndParents(workspace.getRelative(dir.getPathUnderExecRoot()));
}
}
// Make dir links for single rooted dirs.
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.getPackageFragment().segmentCount() > 1 && dirRootsMap.get(getParent(dir)).size() == 1) {
// skip--an ancestor will link this one in from above
continue;
}
// This is the top-most dir that can be linked to a single root. Make it so.
// lone root in set
Path root = roots.iterator().next();
if (LOG_FINER) {
LOG.finer("ln -s " + root.getRelative(dir.getSourceRoot()) + " " + workspace.getRelative(dir.getPathUnderExecRoot()));
}
workspace.getRelative(dir.getPathUnderExecRoot()).createSymbolicLink(root.getRelative(dir.getSourceRoot()));
}
}
// Make links for dirs within packages, skip parent-only dirs.
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.
PackageIdentifier pkgId = longestPathPrefix(dir, packageRoots.keySet());
if (pkgId != null) {
Path root = packageRoots.get(pkgId);
try {
Path absdir = root.getRelative(dir.getSourceRoot());
if (absdir.isDirectory()) {
if (LOG_FINER) {
LOG.finer("ln -s " + absdir + "/* " + workspace.getRelative(dir.getSourceRoot()) + "/");
}
for (Path target : absdir.getDirectoryEntries()) {
PathFragment p = target.relativeTo(root);
if (!dirRootsMap.containsKey(createInRepo(pkgId, p))) {
//LOG.finest("ln -s " + target + " " + linkRoot.getRelative(p));
workspace.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.
}
}
}
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.getPathUnderExecRoot());
// 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.
Path sourceDirectory = entry.getValue().getRelative(pkgId.getSourceRoot());
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 + "-") && !execPath.exists()) {
execPath.createSymbolicLink(target);
}
}
}
symlinkCorrectWorkspaceName();
}
use of com.google.devtools.build.lib.cmdline.PackageIdentifier in project bazel by bazelbuild.
the class PreciseAspectResolver method computeBuildFileDependencies.
@Override
public Set<Label> computeBuildFileDependencies(Package pkg, BuildFileDependencyMode mode) throws InterruptedException {
Set<Label> result = new LinkedHashSet<>();
result.addAll(mode.getDependencies(pkg));
Set<PackageIdentifier> dependentPackages = new LinkedHashSet<>();
// Iterate over all rules...
for (Target target : pkg.getTargets()) {
if (!(target instanceof Rule)) {
continue;
}
// ...figure out which direct dependencies can possibly have aspects attached to them...
Multimap<Attribute, Label> depsWithPossibleAspects = ((Rule) target).getTransitions(new BinaryPredicate<Rule, Attribute>() {
@Override
public boolean apply(@Nullable Rule rule, Attribute attribute) {
for (Aspect aspectWithParameters : attribute.getAspects(rule)) {
if (!aspectWithParameters.getDefinition().getAttributes().isEmpty()) {
return true;
}
}
return false;
}
});
// ...and add the package of the aspect.
for (Label depLabel : depsWithPossibleAspects.values()) {
dependentPackages.add(depLabel.getPackageIdentifier());
}
}
// Then add all the subinclude labels of the packages thus found to the result.
for (PackageIdentifier packageIdentifier : dependentPackages) {
try {
result.add(Label.create(packageIdentifier, "BUILD"));
Package dependentPackage = packageProvider.getPackage(eventHandler, packageIdentifier);
result.addAll(mode.getDependencies(dependentPackage));
} catch (NoSuchPackageException e) {
// If the package is not found, just add its BUILD file, which is already done above.
// Hopefully this error is not raised when there is a syntax error in a subincluded file
// or something.
} catch (LabelSyntaxException e) {
throw new IllegalStateException(e);
}
}
return result;
}
use of com.google.devtools.build.lib.cmdline.PackageIdentifier in project bazel by bazelbuild.
the class GenQuery method constructPackageMap.
/**
* Precomputes the transitive closure of the scope. Returns two maps: one identifying the
* successful packages, and the other identifying the valid targets. Breaks in the transitive
* closure of the scope will cause the query to error out early.
*/
@Nullable
private static Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>> constructPackageMap(SkyFunction.Environment env, Collection<Target> scope) throws InterruptedException, BrokenQueryScopeException {
// It is not necessary for correctness to construct intermediate NestedSets; we could iterate
// over individual targets in scope immediately. However, creating a composite NestedSet first
// saves us from iterating over the same sub-NestedSets multiple times.
NestedSetBuilder<Label> validTargets = NestedSetBuilder.stableOrder();
NestedSetBuilder<PackageIdentifier> successfulPackageNames = NestedSetBuilder.stableOrder();
for (Target target : scope) {
SkyKey key = TransitiveTargetValue.key(target.getLabel());
TransitiveTargetValue transNode = (TransitiveTargetValue) env.getValue(key);
if (transNode == null) {
return null;
}
if (!transNode.getTransitiveUnsuccessfulPackages().isEmpty()) {
// path, as otherwise this configured target would have failed earlier. See b/34132681.
throw new BrokenQueryScopeException("errors were encountered while computing transitive closure of the scope.");
}
validTargets.addTransitive(transNode.getTransitiveTargets());
successfulPackageNames.addTransitive(transNode.getTransitiveSuccessfulPackages());
}
// Construct the package id to package map for all successful packages.
ImmutableMap.Builder<PackageIdentifier, Package> packageMapBuilder = ImmutableMap.builder();
for (PackageIdentifier pkgId : successfulPackageNames.build()) {
PackageValue pkg = (PackageValue) env.getValue(PackageValue.key(pkgId));
Preconditions.checkNotNull(pkg, "package %s not preloaded", pkgId);
Preconditions.checkState(!pkg.getPackage().containsErrors(), "package %s was found to both have and not have errors.", pkgId);
packageMapBuilder.put(pkg.getPackage().getPackageIdentifier(), pkg.getPackage());
}
ImmutableMap<PackageIdentifier, Package> packageMap = packageMapBuilder.build();
ImmutableMap.Builder<Label, Target> validTargetsMapBuilder = ImmutableMap.builder();
for (Label label : validTargets.build()) {
try {
Target target = packageMap.get(label.getPackageIdentifier()).getTarget(label.getName());
validTargetsMapBuilder.put(label, target);
} catch (NoSuchTargetException e) {
throw new IllegalStateException(e);
}
}
return Pair.of(packageMap, validTargetsMapBuilder.build());
}
use of com.google.devtools.build.lib.cmdline.PackageIdentifier in project bazel by bazelbuild.
the class GenQuery method executeQuery.
@Nullable
private byte[] executeQuery(RuleContext ruleContext, QueryOptions queryOptions, Set<Target> scope, String query) throws InterruptedException {
SkyFunction.Environment env = ruleContext.getAnalysisEnvironment().getSkyframeEnv();
Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>> closureInfo;
try {
closureInfo = constructPackageMap(env, scope);
if (closureInfo == null) {
return null;
}
} catch (BrokenQueryScopeException e) {
ruleContext.ruleError(e.getMessage());
return null;
}
ImmutableMap<PackageIdentifier, Package> packageMap = closureInfo.first;
ImmutableMap<Label, Target> validTargetsMap = closureInfo.second;
PackageProvider packageProvider = new PreloadedMapPackageProvider(packageMap, validTargetsMap);
TargetPatternEvaluator evaluator = new SkyframeEnvTargetPatternEvaluator(env);
Predicate<Label> labelFilter = Predicates.in(validTargetsMap.keySet());
return doQuery(queryOptions, packageProvider, labelFilter, evaluator, query, ruleContext);
}
use of com.google.devtools.build.lib.cmdline.PackageIdentifier in project bazel by bazelbuild.
the class ProcessPackageDirectory method getPackageExistenceAndSubdirDeps.
/**
* Examines {@code rootedPath} to see if it is the location of a package, and to see if it has any
* subdirectory children that should also be examined. Returns a {@link
* ProcessPackageDirectoryResult}, or {@code null} if required dependencies were missing.
*/
@Nullable
ProcessPackageDirectoryResult getPackageExistenceAndSubdirDeps(RootedPath rootedPath, RepositoryName repositoryName, SkyFunction.Environment env, Set<PathFragment> excludedPaths) throws InterruptedException {
PathFragment rootRelativePath = rootedPath.getRelativePath();
SkyKey fileKey = FileValue.key(rootedPath);
FileValue fileValue;
try {
fileValue = (FileValue) env.getValueOrThrow(fileKey, InconsistentFilesystemException.class, FileSymlinkException.class, IOException.class);
} catch (InconsistentFilesystemException | FileSymlinkException | IOException e) {
return reportErrorAndReturn("Failed to get information about path", e, rootRelativePath, env.getListener());
}
if (env.valuesMissing()) {
return null;
}
if (!fileValue.isDirectory()) {
return ProcessPackageDirectoryResult.EMPTY_RESULT;
}
PackageIdentifier packageId = PackageIdentifier.create(repositoryName, rootRelativePath);
if ((packageId.getRepository().isDefault() || packageId.getRepository().isMain()) && fileValue.isSymlink() && fileValue.getUnresolvedLinkTarget().startsWith(directories.getOutputBase().asFragment())) {
// somewhere in the directory tree manually.
return ProcessPackageDirectoryResult.EMPTY_RESULT;
}
SkyKey pkgLookupKey = PackageLookupValue.key(packageId);
SkyKey dirListingKey = DirectoryListingValue.key(rootedPath);
Map<SkyKey, ValueOrException4<NoSuchPackageException, InconsistentFilesystemException, FileSymlinkException, IOException>> pkgLookupAndDirectoryListingDeps = env.getValuesOrThrow(ImmutableList.of(pkgLookupKey, dirListingKey), NoSuchPackageException.class, InconsistentFilesystemException.class, FileSymlinkException.class, IOException.class);
if (env.valuesMissing()) {
return null;
}
PackageLookupValue pkgLookupValue;
try {
pkgLookupValue = (PackageLookupValue) Preconditions.checkNotNull(pkgLookupAndDirectoryListingDeps.get(pkgLookupKey).get(), "%s %s %s", rootedPath, repositoryName, pkgLookupKey);
} catch (NoSuchPackageException | InconsistentFilesystemException e) {
return reportErrorAndReturn("Failed to load package", e, rootRelativePath, env.getListener());
} catch (IOException | FileSymlinkException e) {
throw new IllegalStateException(e);
}
DirectoryListingValue dirListingValue;
try {
dirListingValue = (DirectoryListingValue) Preconditions.checkNotNull(pkgLookupAndDirectoryListingDeps.get(dirListingKey).get(), "%s %s %s", rootedPath, repositoryName, dirListingKey);
} catch (InconsistentFilesystemException | IOException e) {
return reportErrorAndReturn("Failed to list directory contents", e, rootRelativePath, env.getListener());
} catch (FileSymlinkException e) {
// be able to avoid throwing there but throw here.
throw new IllegalStateException("Symlink cycle found after not being found for \"" + rootedPath + "\"");
} catch (NoSuchPackageException e) {
throw new IllegalStateException(e);
}
return new ProcessPackageDirectoryResult(pkgLookupValue.packageExists() && pkgLookupValue.getRoot().equals(rootedPath.getRoot()), getSubdirDeps(dirListingValue, rootedPath, repositoryName, excludedPaths));
}
Aggregations