diff options
author | 2017-06-28 10:31:56 +0200 | |
---|---|---|
committer | 2017-06-28 15:21:50 +0200 | |
commit | ac51982b891d2f68ba4784f98ccd3d6ca4d49898 (patch) | |
tree | 933aff7184077e2c2938cd5cf79ae6141acca612 /src/main/java | |
parent | c2de5650c251bcdc3dd2dc80d6386d1e095c8480 (diff) |
Move verifyMarkerData into RepositoryFunction
And for new_XX_repository rules, add BUILD and WORKSPACE file into
markerData.
In markerData, key starting with FILE: can be an absolute label or an
absoulte path, but the latter one will be depracated in future.
Fixed https://github.com/bazelbuild/bazel/issues/3093
Change-Id: Ic3e16c123b3f1f781ab12c41d13f5e540b05686c
PiperOrigin-RevId: 160382024
Diffstat (limited to 'src/main/java')
7 files changed, 181 insertions, 138 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java index 967e26c7a7..f5d567a49e 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java @@ -42,7 +42,7 @@ public class NewGitRepositoryFunction extends GitRepositoryFunction { createDirectory(outputDirectory, rule); GitCloner.clone(rule, outputDirectory, env.getListener(), clientEnvironment, downloader); - fileHandler.finishFile(outputDirectory); + fileHandler.finishFile(rule, outputDirectory, markerData); return RepositoryDirectoryValue.builder().setPath(outputDirectory); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java index 7136596f5c..ba042bfd7d 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java @@ -62,7 +62,6 @@ public class NewHttpArchiveFunction extends HttpArchiveFunction { rule, outputDirectory, env.getListener(), clientEnvironment); // Decompress. - Path decompressed; WorkspaceAttributeMapper mapper = WorkspaceAttributeMapper.of(rule); String prefix = null; if (mapper.isAttributeValueExplicitlySpecified("strip_prefix")) { @@ -72,16 +71,17 @@ public class NewHttpArchiveFunction extends HttpArchiveFunction { throw new RepositoryFunctionException(e, Transience.PERSISTENT); } } - decompressed = DecompressorValue.decompress(DecompressorDescriptor.builder() - .setTargetKind(rule.getTargetKind()) - .setTargetName(rule.getName()) - .setArchivePath(downloadedPath) - .setRepositoryPath(outputDirectory) - .setPrefix(prefix) - .build()); + DecompressorValue.decompress( + DecompressorDescriptor.builder() + .setTargetKind(rule.getTargetKind()) + .setTargetName(rule.getName()) + .setArchivePath(downloadedPath) + .setRepositoryPath(outputDirectory) + .setPrefix(prefix) + .build()); // Finally, write WORKSPACE and BUILD files. - fileHandler.finishFile(outputDirectory); + fileHandler.finishFile(rule, outputDirectory, markerData); return RepositoryDirectoryValue.builder().setPath(outputDirectory); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java index 3ebfc4bb59..08dc59b527 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.bazel.repository.skylark; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.bazel.repository.DecompressorDescriptor; @@ -25,18 +24,17 @@ import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache.KeyT import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader; import com.google.devtools.build.lib.bazel.repository.downloader.HttpUtils; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.NativeClassObjectConstructor; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.SkylarkClassObject; +import com.google.devtools.build.lib.rules.repository.RepositoryFunction; import com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException; import com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper; import com.google.devtools.build.lib.skyframe.FileSymlinkException; import com.google.devtools.build.lib.skyframe.FileValue; import com.google.devtools.build.lib.skyframe.InconsistentFilesystemException; -import com.google.devtools.build.lib.skyframe.PackageLookupValue; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.ParamType; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; @@ -64,7 +62,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; /** Skylark API for the repository_rule's context. */ @SkylarkModule( @@ -688,34 +685,9 @@ public class SkylarkRepositoryContext { return "repository_ctx[" + rule.getLabel() + "]"; } - private static RootedPath getRootedPathFromLabel(Label label, Environment env) - throws InterruptedException, EvalException { - // Look for package. - if (label.getPackageIdentifier().getRepository().isDefault()) { - try { - label = Label.create(label.getPackageIdentifier().makeAbsolute(), label.getName()); - } catch (LabelSyntaxException e) { - throw new AssertionError(e); // Can't happen because the input label is valid - } - } - SkyKey pkgSkyKey = PackageLookupValue.key(label.getPackageIdentifier()); - PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(pkgSkyKey); - if (pkgLookupValue == null) { - throw SkylarkRepositoryFunction.restart(); - } - if (!pkgLookupValue.packageExists()) { - throw new EvalException(Location.BUILTIN, - "Unable to load package for " + label + ": not found."); - } - - // And now for the file - Path packageRoot = pkgLookupValue.getRoot(); - return RootedPath.toRootedPath(packageRoot, label.toPathFragment()); - } - // Resolve the label given by value into a file path. private SkylarkPath getPathFromLabel(Label label) throws EvalException, InterruptedException { - RootedPath rootedPath = getRootedPathFromLabel(label, env); + RootedPath rootedPath = RepositoryFunction.getRootedPathFromLabel(label, env); SkyKey fileSkyKey = FileValue.key(rootedPath); FileValue fileValue = null; try { @@ -726,7 +698,7 @@ public class SkylarkRepositoryContext { } if (fileValue == null) { - throw SkylarkRepositoryFunction.restart(); + throw RepositoryFunction.restart(); } if (!fileValue.isFile()) { throw new EvalException(Location.BUILTIN, @@ -738,40 +710,4 @@ public class SkylarkRepositoryContext { return new SkylarkPath(rootedPath.asPath()); } - private static boolean verifyLabelMarkerData(String key, String value, Environment env) - throws InterruptedException { - Preconditions.checkArgument(key.startsWith("FILE:")); - try { - Label label = Label.parseAbsolute(key.substring(5)); - RootedPath rootedPath = getRootedPathFromLabel(label, env); - SkyKey fileSkyKey = FileValue.key(rootedPath); - FileValue fileValue = (FileValue) env.getValueOrThrow(fileSkyKey, IOException.class, - FileSymlinkException.class, InconsistentFilesystemException.class); - - if (fileValue == null || !fileValue.isFile()) { - return false; - } - - return Objects.equals(value, Integer.toString(fileValue.realFileStateValue().hashCode())); - } catch (LabelSyntaxException e) { - throw new IllegalStateException( - "Key " + key + " is not a correct file key (should be in form FILE:label)", e); - } catch (IOException | FileSymlinkException | InconsistentFilesystemException - | EvalException e) { - // Consider those exception to be a cause for invalidation - return false; - } - } - - static boolean verifyMarkerDataForFiles(Map<String, String> markerData, Environment env) - throws InterruptedException { - for (Map.Entry<String, String> entry : markerData.entrySet()) { - if (entry.getKey().startsWith("FILE:")) { - if (!verifyLabelMarkerData(entry.getKey(), entry.getValue(), env)) { - return false; - } - } - } - return true; - } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java index b1c0992f6b..081a2a1f6a 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java @@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader; -import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue; import com.google.devtools.build.lib.rules.repository.RepositoryFunction; @@ -40,32 +39,12 @@ import javax.annotation.Nullable; */ public class SkylarkRepositoryFunction extends RepositoryFunction { - /** - * An exception thrown when a dependency is missing to notify the SkyFunction from a skylark - * evaluation. - */ - private static class SkylarkRepositoryMissingDependencyException extends EvalException { - - SkylarkRepositoryMissingDependencyException() { - super(Location.BUILTIN, "Internal exception"); - } - } - private final HttpDownloader httpDownloader; public SkylarkRepositoryFunction(HttpDownloader httpDownloader) { this.httpDownloader = httpDownloader; } - /** - * Skylark repository context functions can throw the result of this function to notify the - * SkylarkRepositoryFunction that a dependency was missing and the evaluation of the function must - * be restarted. - */ - static EvalException restart() { - return new SkylarkRepositoryMissingDependencyException(); - } - @Nullable @Override public RepositoryDirectoryValue.Builder fetch(Rule rule, Path outputDirectory, @@ -106,7 +85,7 @@ public class SkylarkRepositoryFunction extends RepositoryFunction { Transience.PERSISTENT); } } catch (EvalException e) { - if (e.getCause() instanceof SkylarkRepositoryMissingDependencyException) { + if (e.getCause() instanceof RepositoryMissingDependencyException) { // A dependency is missing, cleanup and returns null try { if (outputDirectory.exists()) { @@ -138,15 +117,6 @@ public class SkylarkRepositoryFunction extends RepositoryFunction { } @Override - public boolean verifyMarkerData(Rule rule, Map<String, String> markerData, Environment env) - throws InterruptedException { - if (verifyEnvironMarkerData(markerData, env, getEnviron(rule))) { - return SkylarkRepositoryContext.verifyMarkerDataForFiles(markerData, env); - } - return false; - } - - @Override protected boolean isLocal(Rule rule) { return (Boolean) rule.getAttributeContainer().getAttr("$local"); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java index 3670dcdd44..1e2a5317ae 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java @@ -117,7 +117,7 @@ public class NewLocalRepositoryFunction extends RepositoryFunction { return null; } - fileHandler.finishFile(outputDirectory); + fileHandler.finishFile(rule, outputDirectory, markerData); return RepositoryDirectoryValue.builder().setPath(outputDirectory).setSourceDir(directoryValue); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryFileHandler.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryFileHandler.java index 64c4502b71..094f5e5ec7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryFileHandler.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryFileHandler.java @@ -32,6 +32,7 @@ import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import java.io.IOException; +import java.util.Map; /** * Encapsulates the 2-step behavior of creating workspace and build files for the new_*_repository @@ -59,9 +60,10 @@ public class NewRepositoryFileHandler { return true; } - public void finishFile(Path outputDirectory) throws RepositoryFunctionException { - this.workspaceFileHandler.finishFile(outputDirectory); - this.buildFileHandler.finishFile(outputDirectory); + public void finishFile(Rule rule, Path outputDirectory, Map<String, String> markerData) + throws RepositoryFunctionException { + this.workspaceFileHandler.finishFile(rule, outputDirectory, markerData); + this.buildFileHandler.finishFile(rule, outputDirectory, markerData); } /** @@ -142,10 +144,21 @@ public class NewRepositoryFileHandler { * @throws IllegalStateException if {@link #prepareFile} was not called before this, or if * {@link #prepareFile} failed and this was called. */ - public void finishFile(Path outputDirectory) throws RepositoryFunctionException { + public void finishFile(Rule rule, Path outputDirectory, Map<String, String> markerData) + throws RepositoryFunctionException { if (fileValue != null) { // Link x/FILENAME to <build_root>/x.FILENAME. symlinkFile(fileValue, filename, outputDirectory); + String fileAttribute = getFileAttributeValue(rule); + String fileKey; + if (LabelValidator.isAbsolute(fileAttribute)) { + fileKey = getFileAttributeAsLabel(rule).toString(); + } else { + // TODO(pcloudy): Don't add absolute path into markerData once it's not supported + fileKey = fileValue.realRootedPath().asPath().getPathString(); + } + markerData.put( + "FILE:" + fileKey, Integer.toString(fileValue.realFileStateValue().hashCode())); } else if (fileContent != null) { RepositoryFunction.writeFile(outputDirectory, filename, fileContent); } else { @@ -153,8 +166,7 @@ public class NewRepositoryFileHandler { } } - private FileValue getFileValue(Rule rule, Environment env) - throws RepositoryFunctionException, InterruptedException { + private String getFileAttributeValue(Rule rule) throws RepositoryFunctionException { WorkspaceAttributeMapper mapper = WorkspaceAttributeMapper.of(rule); String fileAttribute; try { @@ -162,37 +174,49 @@ public class NewRepositoryFileHandler { } catch (EvalException e) { throw new RepositoryFunctionException(e, Transience.PERSISTENT); } + return fileAttribute; + } + + private Label getFileAttributeAsLabel(Rule rule) throws RepositoryFunctionException { + Label label; + try { + // Parse a label + label = Label.parseAbsolute(getFileAttributeValue(rule)); + } catch (LabelSyntaxException ex) { + throw new RepositoryFunctionException( + new EvalException( + rule.getLocation(), + String.format( + "In %s the '%s' attribute does not specify a valid label: %s", + rule, getFileAttrName(), ex.getMessage())), + Transience.PERSISTENT); + } + return label; + } + + private FileValue getFileValue(Rule rule, Environment env) + throws RepositoryFunctionException, InterruptedException { + String fileAttribute = getFileAttributeValue(rule); RootedPath rootedFile; if (LabelValidator.isAbsolute(fileAttribute)) { - try { - // Parse a label - Label label = Label.parseAbsolute(fileAttribute); - SkyKey pkgSkyKey = PackageLookupValue.key(label.getPackageIdentifier()); - PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(pkgSkyKey); - if (pkgLookupValue == null) { - return null; - } - if (!pkgLookupValue.packageExists()) { - throw new RepositoryFunctionException( - new EvalException( - rule.getLocation(), - "Unable to load package for " + fileAttribute + ": not found."), - Transience.PERSISTENT); - } - - // And now for the file - Path packageRoot = pkgLookupValue.getRoot(); - rootedFile = RootedPath.toRootedPath(packageRoot, label.toPathFragment()); - } catch (LabelSyntaxException ex) { + Label label = getFileAttributeAsLabel(rule); + SkyKey pkgSkyKey = PackageLookupValue.key(label.getPackageIdentifier()); + PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(pkgSkyKey); + if (pkgLookupValue == null) { + return null; + } + if (!pkgLookupValue.packageExists()) { throw new RepositoryFunctionException( new EvalException( rule.getLocation(), - String.format( - "In %s the '%s' attribute does not specify a valid label: %s", - rule, getFileAttrName(), ex.getMessage())), + "Unable to load package for " + fileAttribute + ": not found."), Transience.PERSISTENT); } + + // And now for the file + Path packageRoot = pkgLookupValue.getRoot(); + rootedFile = RootedPath.toRootedPath(packageRoot, label.toPathFragment()); } else { // TODO(dmarting): deprecate using a path for the workspace_file attribute. PathFragment file = PathFragment.create(fileAttribute); diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java index 16c29673ba..469eb61222 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java @@ -15,11 +15,16 @@ package com.google.devtools.build.lib.rules.repository; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.cmdline.LabelSyntaxException; +import com.google.devtools.build.lib.cmdline.LabelValidator; import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; +import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.Rule; @@ -28,6 +33,7 @@ import com.google.devtools.build.lib.skyframe.ActionEnvironmentFunction; import com.google.devtools.build.lib.skyframe.FileSymlinkException; import com.google.devtools.build.lib.skyframe.FileValue; import com.google.devtools.build.lib.skyframe.InconsistentFilesystemException; +import com.google.devtools.build.lib.skyframe.PackageLookupValue; import com.google.devtools.build.lib.skyframe.PackageLookupValue.BuildFileName; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.Type; @@ -118,6 +124,24 @@ public abstract class RepositoryFunction { } /** + * An exception thrown when a dependency is missing to notify the SkyFunction from an evaluation. + */ + protected static class RepositoryMissingDependencyException extends EvalException { + + RepositoryMissingDependencyException() { + super(Location.BUILTIN, "Internal exception"); + } + } + + /** + * repository functions can throw the result of this function to notify the RepositoryFunction + * that a dependency was missing and the evaluation of the function must be restarted. + */ + public static EvalException restart() { + return new RepositoryMissingDependencyException(); + } + + /** * Fetch the remote repository represented by the given rule. * * <p>When this method is called, it has already been determined that the repository is stale and @@ -152,6 +176,14 @@ public abstract class RepositoryFunction { Map<String, String> markerData) throws SkyFunctionException, InterruptedException; + @SuppressWarnings("unchecked") + private static Iterable<String> getEnviron(Rule rule) { + if (rule.isAttrDefined("$environ", Type.STRING_LIST)) { + return (Iterable<String>) rule.getAttributeContainer().getAttr("$environ"); + } + return ImmutableList.of(); + } + /** * Verify the data provided by the marker file to check if a refetch is needed. Returns true if * the data is up to date and no refetch is needed and false if the data is obsolete and a refetch @@ -159,10 +191,91 @@ public abstract class RepositoryFunction { */ @Nullable public boolean verifyMarkerData(Rule rule, Map<String, String> markerData, Environment env) + throws InterruptedException, RepositoryFunctionException { + return verifyEnvironMarkerData(markerData, env, getEnviron(rule)) + && verifyMarkerDataForFiles(rule, markerData, env); + } + + private static boolean verifyLabelMarkerData(Rule rule, String key, String value, Environment env) throws InterruptedException { + Preconditions.checkArgument(key.startsWith("FILE:")); + try { + RootedPath rootedPath; + String fileKey = key.substring(5); + if (LabelValidator.isAbsolute(fileKey)) { + rootedPath = getRootedPathFromLabel(Label.parseAbsolute(fileKey), env); + } else { + // TODO(pcloudy): Removing checking absolute path, they should all be absolute label. + PathFragment filePathFragment = PathFragment.create(fileKey); + Path file = rule.getPackage().getPackageDirectory().getRelative(filePathFragment); + rootedPath = + RootedPath.toRootedPath( + file.getParentDirectory(), PathFragment.create(file.getBaseName())); + } + + SkyKey fileSkyKey = FileValue.key(rootedPath); + FileValue fileValue = + (FileValue) + env.getValueOrThrow( + fileSkyKey, + IOException.class, + FileSymlinkException.class, + InconsistentFilesystemException.class); + + if (fileValue == null || !fileValue.isFile()) { + return false; + } + + return Objects.equals(value, Integer.toString(fileValue.realFileStateValue().hashCode())); + } catch (LabelSyntaxException e) { + throw new IllegalStateException( + "Key " + key + " is not a correct file key (should be in form FILE:label)", e); + } catch (IOException + | FileSymlinkException + | InconsistentFilesystemException + | EvalException e) { + // Consider those exception to be a cause for invalidation + return false; + } + } + + static boolean verifyMarkerDataForFiles( + Rule rule, Map<String, String> markerData, Environment env) throws InterruptedException { + for (Map.Entry<String, String> entry : markerData.entrySet()) { + if (entry.getKey().startsWith("FILE:")) { + if (!verifyLabelMarkerData(rule, entry.getKey(), entry.getValue(), env)) { + return false; + } + } + } return true; } + public static RootedPath getRootedPathFromLabel(Label label, Environment env) + throws InterruptedException, EvalException { + // Look for package. + if (label.getPackageIdentifier().getRepository().isDefault()) { + try { + label = Label.create(label.getPackageIdentifier().makeAbsolute(), label.getName()); + } catch (LabelSyntaxException e) { + throw new AssertionError(e); // Can't happen because the input label is valid + } + } + SkyKey pkgSkyKey = PackageLookupValue.key(label.getPackageIdentifier()); + PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(pkgSkyKey); + if (pkgLookupValue == null) { + throw RepositoryFunction.restart(); + } + if (!pkgLookupValue.packageExists()) { + throw new EvalException( + Location.BUILTIN, "Unable to load package for " + label + ": not found."); + } + + // And now for the file + Path packageRoot = pkgLookupValue.getRoot(); + return RootedPath.toRootedPath(packageRoot, label.toPathFragment()); + } + /** * A method that can be called from a implementation of * {@link #fetch(Rule, Path, BlazeDirectories, Environment, Map)} to declare a list of Skyframe |