Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1 | // Copyright 2014 Google Inc. All rights reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.skyframe; |
| 15 | |
| 16 | import com.google.common.base.Preconditions; |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 17 | import com.google.common.cache.Cache; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 18 | import com.google.common.collect.ImmutableList; |
| 19 | import com.google.common.collect.ImmutableMap; |
| 20 | import com.google.common.collect.ImmutableSet; |
| 21 | import com.google.common.collect.Iterables; |
| 22 | import com.google.common.collect.Lists; |
| 23 | import com.google.common.collect.Sets; |
Kristina Chodorow | 73fa203 | 2015-08-28 17:57:46 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
| 25 | import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 26 | import com.google.devtools.build.lib.events.Event; |
| 27 | import com.google.devtools.build.lib.events.EventHandler; |
| 28 | import com.google.devtools.build.lib.events.Location; |
| 29 | import com.google.devtools.build.lib.events.Reporter; |
| 30 | import com.google.devtools.build.lib.events.StoredEventHandler; |
| 31 | import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException; |
| 32 | import com.google.devtools.build.lib.packages.BuildFileNotFoundException; |
| 33 | import com.google.devtools.build.lib.packages.CachingPackageLocator; |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 34 | import com.google.devtools.build.lib.packages.ExternalPackage; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 35 | import com.google.devtools.build.lib.packages.InvalidPackageNameException; |
| 36 | import com.google.devtools.build.lib.packages.NoSuchPackageException; |
| 37 | import com.google.devtools.build.lib.packages.Package; |
| 38 | import com.google.devtools.build.lib.packages.PackageFactory; |
| 39 | import com.google.devtools.build.lib.packages.PackageFactory.Globber; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 40 | import com.google.devtools.build.lib.packages.Preprocessor; |
| 41 | import com.google.devtools.build.lib.packages.RuleVisibility; |
| 42 | import com.google.devtools.build.lib.packages.Target; |
| 43 | import com.google.devtools.build.lib.profiler.Profiler; |
| 44 | import com.google.devtools.build.lib.profiler.ProfilerTask; |
| 45 | import com.google.devtools.build.lib.skyframe.ASTFileLookupValue.ASTLookupInputException; |
| 46 | import com.google.devtools.build.lib.skyframe.GlobValue.InvalidGlobPatternException; |
| 47 | import com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException; |
| 48 | import com.google.devtools.build.lib.syntax.BuildFileAST; |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 49 | import com.google.devtools.build.lib.syntax.Environment.Extension; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 50 | import com.google.devtools.build.lib.syntax.EvalException; |
| 51 | import com.google.devtools.build.lib.syntax.Label; |
| 52 | import com.google.devtools.build.lib.syntax.ParserInputSource; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 53 | import com.google.devtools.build.lib.syntax.Statement; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 54 | import com.google.devtools.build.lib.util.Pair; |
| 55 | import com.google.devtools.build.lib.vfs.Path; |
| 56 | import com.google.devtools.build.lib.vfs.PathFragment; |
| 57 | import com.google.devtools.build.lib.vfs.RootedPath; |
| 58 | import com.google.devtools.build.skyframe.SkyFunction; |
| 59 | import com.google.devtools.build.skyframe.SkyFunctionException; |
| 60 | import com.google.devtools.build.skyframe.SkyFunctionException.Transience; |
| 61 | import com.google.devtools.build.skyframe.SkyKey; |
| 62 | import com.google.devtools.build.skyframe.SkyValue; |
| 63 | import com.google.devtools.build.skyframe.ValueOrException3; |
| 64 | import com.google.devtools.build.skyframe.ValueOrException4; |
| 65 | |
| 66 | import java.io.IOException; |
| 67 | import java.util.Collection; |
| 68 | import java.util.HashMap; |
| 69 | import java.util.List; |
| 70 | import java.util.Map; |
| 71 | import java.util.Map.Entry; |
| 72 | import java.util.Set; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 73 | import java.util.concurrent.atomic.AtomicBoolean; |
| 74 | import java.util.concurrent.atomic.AtomicInteger; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 75 | |
| 76 | import javax.annotation.Nullable; |
| 77 | |
| 78 | /** |
| 79 | * A SkyFunction for {@link PackageValue}s. |
| 80 | */ |
| 81 | public class PackageFunction implements SkyFunction { |
| 82 | |
| 83 | private final EventHandler reporter; |
| 84 | private final PackageFactory packageFactory; |
| 85 | private final CachingPackageLocator packageLocator; |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 86 | private final Cache<PackageIdentifier, Package.LegacyBuilder> packageFunctionCache; |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 87 | private final Cache<PackageIdentifier, Preprocessor.Result> preprocessCache; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 88 | private final AtomicBoolean showLoadingProgress; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 89 | private final AtomicInteger numPackagesLoaded; |
| 90 | private final Profiler profiler = Profiler.instance(); |
| 91 | |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 92 | private final PathFragment preludePath; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 93 | |
| 94 | static final String DEFAULTS_PACKAGE_NAME = "tools/defaults"; |
| 95 | public static final String EXTERNAL_PACKAGE_NAME = "external"; |
| 96 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 97 | public PackageFunction(Reporter reporter, PackageFactory packageFactory, |
| 98 | CachingPackageLocator pkgLocator, AtomicBoolean showLoadingProgress, |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 99 | Cache<PackageIdentifier, Package.LegacyBuilder> packageFunctionCache, |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 100 | Cache<PackageIdentifier, Preprocessor.Result> preprocessCache, |
Eric Fellheimer | 670a75a | 2015-05-18 13:18:58 +0000 | [diff] [blame] | 101 | AtomicInteger numPackagesLoaded) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 102 | this.reporter = reporter; |
| 103 | |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 104 | // Can be null in tests. |
| 105 | this.preludePath = packageFactory == null |
| 106 | ? null |
| 107 | : packageFactory.getRuleClassProvider().getPreludePath(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 108 | this.packageFactory = packageFactory; |
| 109 | this.packageLocator = pkgLocator; |
| 110 | this.showLoadingProgress = showLoadingProgress; |
| 111 | this.packageFunctionCache = packageFunctionCache; |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 112 | this.preprocessCache = preprocessCache; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 113 | this.numPackagesLoaded = numPackagesLoaded; |
| 114 | } |
| 115 | |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 116 | private static void maybeThrowFilesystemInconsistency(PackageIdentifier packageIdentifier, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 117 | Exception skyframeException, boolean packageWasInError) |
| 118 | throws InternalInconsistentFilesystemException { |
| 119 | if (!packageWasInError) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 120 | throw new InternalInconsistentFilesystemException(packageIdentifier, "Encountered error '" |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 121 | + skyframeException.getMessage() + "' but didn't encounter it when doing the same thing " |
| 122 | + "earlier in the build"); |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Marks the given dependencies, and returns those already present. Ignores any exception |
| 128 | * thrown while building the dependency, except for filesystem inconsistencies. |
| 129 | * |
| 130 | * <p>We need to mark dependencies implicitly used by the legacy package loading code, but we |
| 131 | * don't care about any skyframe errors since the package knows whether it's in error or not. |
| 132 | */ |
| 133 | private static Pair<? extends Map<PathFragment, PackageLookupValue>, Boolean> |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 134 | getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions( |
| 135 | PackageIdentifier packageIdentifier, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 136 | Iterable<SkyKey> depKeys, Environment env, boolean packageWasInError) |
| 137 | throws InternalInconsistentFilesystemException { |
| 138 | Preconditions.checkState( |
| 139 | Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.PACKAGE_LOOKUP)), depKeys); |
| 140 | boolean packageShouldBeInError = packageWasInError; |
| 141 | ImmutableMap.Builder<PathFragment, PackageLookupValue> builder = ImmutableMap.builder(); |
| 142 | for (Map.Entry<SkyKey, ValueOrException3<BuildFileNotFoundException, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 143 | InconsistentFilesystemException, FileSymlinkException>> entry : |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 144 | env.getValuesOrThrow(depKeys, BuildFileNotFoundException.class, |
| 145 | InconsistentFilesystemException.class, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 146 | FileSymlinkException.class).entrySet()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 147 | PathFragment pkgName = ((PackageIdentifier) entry.getKey().argument()).getPackageFragment(); |
| 148 | try { |
| 149 | PackageLookupValue value = (PackageLookupValue) entry.getValue().get(); |
| 150 | if (value != null) { |
| 151 | builder.put(pkgName, value); |
| 152 | } |
| 153 | } catch (BuildFileNotFoundException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 154 | maybeThrowFilesystemInconsistency(packageIdentifier, e, packageWasInError); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 155 | } catch (InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 156 | throw new InternalInconsistentFilesystemException(packageIdentifier, e); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 157 | } catch (FileSymlinkException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 158 | // Legacy doesn't detect symlink cycles. |
| 159 | packageShouldBeInError = true; |
| 160 | } |
| 161 | } |
| 162 | return Pair.of(builder.build(), packageShouldBeInError); |
| 163 | } |
| 164 | |
| 165 | private static boolean markFileDepsAndPropagateInconsistentFilesystemExceptions( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 166 | PackageIdentifier packageIdentifier, Iterable<SkyKey> depKeys, Environment env, |
| 167 | boolean packageWasInError) throws InternalInconsistentFilesystemException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 168 | Preconditions.checkState( |
| 169 | Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.FILE)), depKeys); |
| 170 | boolean packageShouldBeInError = packageWasInError; |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 171 | for (Map.Entry<SkyKey, ValueOrException3<IOException, FileSymlinkException, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 172 | InconsistentFilesystemException>> entry : env.getValuesOrThrow(depKeys, IOException.class, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 173 | FileSymlinkException.class, InconsistentFilesystemException.class).entrySet()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 174 | try { |
| 175 | entry.getValue().get(); |
| 176 | } catch (IOException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 177 | maybeThrowFilesystemInconsistency(packageIdentifier, e, packageWasInError); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 178 | } catch (FileSymlinkException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 179 | // Legacy doesn't detect symlink cycles. |
| 180 | packageShouldBeInError = true; |
| 181 | } catch (InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 182 | throw new InternalInconsistentFilesystemException(packageIdentifier, e); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 183 | } |
| 184 | } |
| 185 | return packageShouldBeInError; |
| 186 | } |
| 187 | |
| 188 | private static boolean markGlobDepsAndPropagateInconsistentFilesystemExceptions( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 189 | PackageIdentifier packageIdentifier, Iterable<SkyKey> depKeys, Environment env, |
| 190 | boolean packageWasInError) throws InternalInconsistentFilesystemException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 191 | Preconditions.checkState( |
| 192 | Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.GLOB)), depKeys); |
| 193 | boolean packageShouldBeInError = packageWasInError; |
| 194 | for (Map.Entry<SkyKey, ValueOrException4<IOException, BuildFileNotFoundException, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 195 | FileSymlinkException, InconsistentFilesystemException>> entry : |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 196 | env.getValuesOrThrow(depKeys, IOException.class, BuildFileNotFoundException.class, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 197 | FileSymlinkException.class, InconsistentFilesystemException.class).entrySet()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 198 | try { |
| 199 | entry.getValue().get(); |
| 200 | } catch (IOException | BuildFileNotFoundException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 201 | maybeThrowFilesystemInconsistency(packageIdentifier, e, packageWasInError); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 202 | } catch (FileSymlinkException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 203 | // Legacy doesn't detect symlink cycles. |
| 204 | packageShouldBeInError = true; |
| 205 | } catch (InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 206 | throw new InternalInconsistentFilesystemException(packageIdentifier, e); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 207 | } |
| 208 | } |
| 209 | return packageShouldBeInError; |
| 210 | } |
| 211 | |
| 212 | /** |
| 213 | * Marks dependencies implicitly used by legacy package loading code, after the fact. Note that |
| 214 | * the given package might already be in error. |
| 215 | * |
| 216 | * <p>Any skyframe exceptions encountered here are ignored, as similar errors should have |
| 217 | * already been encountered by legacy package loading (if not, then the filesystem is |
| 218 | * inconsistent). |
| 219 | */ |
| 220 | private static boolean markDependenciesAndPropagateInconsistentFilesystemExceptions( |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 221 | Environment env, |
| 222 | Collection<Pair<String, Boolean>> globPatterns, |
| 223 | Map<Label, Path> subincludes, |
| 224 | PackageIdentifier packageIdentifier, |
| 225 | boolean containsErrors) |
| 226 | throws InternalInconsistentFilesystemException { |
| 227 | boolean packageShouldBeInError = containsErrors; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 228 | |
| 229 | // TODO(bazel-team): This means that many packages will have to be preprocessed twice. Ouch! |
| 230 | // We need a better continuation mechanism to avoid repeating work. [skyframe-loading] |
| 231 | |
| 232 | // TODO(bazel-team): It would be preferable to perform I/O from the package preprocessor via |
| 233 | // Skyframe rather than add (potentially incomplete) dependencies after the fact. |
| 234 | // [skyframe-loading] |
| 235 | |
| 236 | Set<SkyKey> subincludePackageLookupDepKeys = Sets.newHashSet(); |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 237 | for (Label label : subincludes.keySet()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 238 | // Declare a dependency on the package lookup for the package giving access to the label. |
Lukacs Berki | f445ea1 | 2015-07-09 07:16:41 +0000 | [diff] [blame] | 239 | subincludePackageLookupDepKeys.add(PackageLookupValue.key(label.getPackageIdentifier())); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 240 | } |
| 241 | Pair<? extends Map<PathFragment, PackageLookupValue>, Boolean> subincludePackageLookupResult = |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 242 | getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions( |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 243 | packageIdentifier, subincludePackageLookupDepKeys, env, containsErrors); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 244 | Map<PathFragment, PackageLookupValue> subincludePackageLookupDeps = |
| 245 | subincludePackageLookupResult.getFirst(); |
Mark Schaller | 6fc9f88 | 2015-06-12 17:53:57 +0000 | [diff] [blame] | 246 | packageShouldBeInError |= subincludePackageLookupResult.getSecond(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 247 | List<SkyKey> subincludeFileDepKeys = Lists.newArrayList(); |
| 248 | for (Entry<Label, Path> subincludeEntry : subincludes.entrySet()) { |
| 249 | // Ideally, we would have a direct dependency on the target with the given label, but then |
| 250 | // subincluding a file from the same package will cause a dependency cycle, since targets |
| 251 | // depend on their containing packages. |
| 252 | Label label = subincludeEntry.getKey(); |
| 253 | PackageLookupValue subincludePackageLookupValue = |
| 254 | subincludePackageLookupDeps.get(label.getPackageFragment()); |
| 255 | if (subincludePackageLookupValue != null) { |
| 256 | // Declare a dependency on the actual file that was subincluded. |
| 257 | Path subincludeFilePath = subincludeEntry.getValue(); |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 258 | if (subincludeFilePath != null && !subincludePackageLookupValue.packageExists()) { |
| 259 | // Legacy blaze puts a non-null path when only when the package does indeed exist. |
| 260 | throw new InternalInconsistentFilesystemException( |
| 261 | packageIdentifier, |
| 262 | String.format( |
| 263 | "Unexpected package in %s. Was it modified during the build?", |
| 264 | subincludeFilePath)); |
| 265 | } |
| 266 | if (subincludePackageLookupValue.packageExists()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 267 | // Sanity check for consistency of Skyframe and legacy blaze. |
| 268 | Path subincludeFilePathSkyframe = |
| 269 | subincludePackageLookupValue.getRoot().getRelative(label.toPathFragment()); |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 270 | if (subincludeFilePath != null |
| 271 | && !subincludeFilePathSkyframe.equals(subincludeFilePath)) { |
| 272 | throw new InternalInconsistentFilesystemException( |
| 273 | packageIdentifier, |
| 274 | String.format( |
| 275 | "Inconsistent package location for %s: '%s' vs '%s'. " |
| 276 | + "Was the source tree modified during the build?", |
| 277 | label.getPackageFragment(), |
| 278 | subincludeFilePathSkyframe, |
| 279 | subincludeFilePath)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 280 | } |
| 281 | // The actual file may be under a different package root than the package being |
| 282 | // constructed. |
| 283 | SkyKey subincludeSkyKey = |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 284 | FileValue.key( |
| 285 | RootedPath.toRootedPath( |
| 286 | subincludePackageLookupValue.getRoot(), |
| 287 | label.getPackageFragment().getRelative(label.getName()))); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 288 | subincludeFileDepKeys.add(subincludeSkyKey); |
| 289 | } |
| 290 | } |
| 291 | } |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 292 | packageShouldBeInError |= |
| 293 | markFileDepsAndPropagateInconsistentFilesystemExceptions( |
| 294 | packageIdentifier, subincludeFileDepKeys, env, containsErrors); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 295 | |
| 296 | // TODO(bazel-team): In the long term, we want to actually resolve the glob patterns within |
| 297 | // Skyframe. For now, just logging the glob requests provides correct incrementality and |
| 298 | // adequate performance. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 299 | List<SkyKey> globDepKeys = Lists.newArrayList(); |
| 300 | for (Pair<String, Boolean> globPattern : globPatterns) { |
| 301 | String pattern = globPattern.getFirst(); |
| 302 | boolean excludeDirs = globPattern.getSecond(); |
| 303 | SkyKey globSkyKey; |
| 304 | try { |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 305 | globSkyKey = |
| 306 | GlobValue.key(packageIdentifier, pattern, excludeDirs, PathFragment.EMPTY_FRAGMENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 307 | } catch (InvalidGlobPatternException e) { |
| 308 | // Globs that make it to pkg.getGlobPatterns() should already be filtered for errors. |
| 309 | throw new IllegalStateException(e); |
| 310 | } |
| 311 | globDepKeys.add(globSkyKey); |
| 312 | } |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 313 | packageShouldBeInError |= |
| 314 | markGlobDepsAndPropagateInconsistentFilesystemExceptions( |
| 315 | packageIdentifier, globDepKeys, env, containsErrors); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 316 | return packageShouldBeInError; |
| 317 | } |
| 318 | |
| 319 | /** |
| 320 | * Adds a dependency on the WORKSPACE file, representing it as a special type of package. |
| 321 | * @throws PackageFunctionException if there is an error computing the workspace file or adding |
| 322 | * its rules to the //external package. |
| 323 | */ |
| 324 | private SkyValue getExternalPackage(Environment env, Path packageLookupPath) |
| 325 | throws PackageFunctionException { |
| 326 | RootedPath workspacePath = RootedPath.toRootedPath( |
| 327 | packageLookupPath, new PathFragment("WORKSPACE")); |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 328 | SkyKey workspaceKey = PackageValue.workspaceKey(workspacePath); |
| 329 | PackageValue workspace = null; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 330 | try { |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 331 | workspace = (PackageValue) env.getValueOrThrow(workspaceKey, IOException.class, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 332 | FileSymlinkException.class, InconsistentFilesystemException.class, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 333 | EvalException.class); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 334 | } catch (IOException | FileSymlinkException | InconsistentFilesystemException |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 335 | | EvalException e) { |
| 336 | throw new PackageFunctionException(new BadWorkspaceFileException(e.getMessage()), |
| 337 | Transience.PERSISTENT); |
| 338 | } |
| 339 | if (workspace == null) { |
| 340 | return null; |
| 341 | } |
| 342 | |
| 343 | Package pkg = workspace.getPackage(); |
| 344 | Event.replayEventsOn(env.getListener(), pkg.getEvents()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 345 | |
| 346 | return new PackageValue(pkg); |
| 347 | } |
| 348 | |
| 349 | @Override |
| 350 | public SkyValue compute(SkyKey key, Environment env) throws PackageFunctionException, |
| 351 | InterruptedException { |
| 352 | PackageIdentifier packageId = (PackageIdentifier) key.argument(); |
| 353 | PathFragment packageNameFragment = packageId.getPackageFragment(); |
| 354 | String packageName = packageNameFragment.getPathString(); |
| 355 | |
| 356 | SkyKey packageLookupKey = PackageLookupValue.key(packageId); |
| 357 | PackageLookupValue packageLookupValue; |
| 358 | try { |
| 359 | packageLookupValue = (PackageLookupValue) |
| 360 | env.getValueOrThrow(packageLookupKey, BuildFileNotFoundException.class, |
| 361 | InconsistentFilesystemException.class); |
| 362 | } catch (BuildFileNotFoundException e) { |
| 363 | throw new PackageFunctionException(e, Transience.PERSISTENT); |
| 364 | } catch (InconsistentFilesystemException e) { |
| 365 | // This error is not transient from the perspective of the PackageFunction. |
| 366 | throw new PackageFunctionException( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 367 | new InternalInconsistentFilesystemException(packageId, e), Transience.PERSISTENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 368 | } |
| 369 | if (packageLookupValue == null) { |
| 370 | return null; |
| 371 | } |
| 372 | |
| 373 | if (!packageLookupValue.packageExists()) { |
| 374 | switch (packageLookupValue.getErrorReason()) { |
| 375 | case NO_BUILD_FILE: |
| 376 | case DELETED_PACKAGE: |
| 377 | case NO_EXTERNAL_PACKAGE: |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 378 | throw new PackageFunctionException(new BuildFileNotFoundException(packageId, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 379 | packageLookupValue.getErrorMsg()), Transience.PERSISTENT); |
| 380 | case INVALID_PACKAGE_NAME: |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 381 | throw new PackageFunctionException(new InvalidPackageNameException(packageId, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 382 | packageLookupValue.getErrorMsg()), Transience.PERSISTENT); |
| 383 | default: |
| 384 | // We should never get here. |
Ulf Adams | 07dba94 | 2015-03-05 14:47:37 +0000 | [diff] [blame] | 385 | throw new IllegalStateException(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 386 | } |
| 387 | } |
| 388 | |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 389 | if (packageId.equals(ExternalPackage.PACKAGE_IDENTIFIER)) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 390 | return getExternalPackage(env, packageLookupValue.getRoot()); |
| 391 | } |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 392 | SkyKey externalPackageKey = PackageValue.key(ExternalPackage.PACKAGE_IDENTIFIER); |
| 393 | PackageValue externalPackage = (PackageValue) env.getValue(externalPackageKey); |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 394 | if (externalPackage == null) { |
| 395 | return null; |
| 396 | } |
| 397 | Package externalPkg = externalPackage.getPackage(); |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 398 | if (externalPkg.containsErrors()) { |
| 399 | throw new PackageFunctionException( |
| 400 | new BuildFileContainsErrorsException(ExternalPackage.PACKAGE_IDENTIFIER), |
| 401 | Transience.PERSISTENT); |
| 402 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 403 | |
Googler | 9f212f7 | 2015-02-09 14:42:21 +0000 | [diff] [blame] | 404 | PathFragment buildFileFragment = packageNameFragment.getChild("BUILD"); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 405 | RootedPath buildFileRootedPath = RootedPath.toRootedPath(packageLookupValue.getRoot(), |
Googler | 9f212f7 | 2015-02-09 14:42:21 +0000 | [diff] [blame] | 406 | buildFileFragment); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 407 | FileValue buildFileValue; |
| 408 | try { |
| 409 | buildFileValue = (FileValue) env.getValueOrThrow(FileValue.key(buildFileRootedPath), |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 410 | IOException.class, FileSymlinkException.class, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 411 | InconsistentFilesystemException.class); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 412 | } catch (IOException | FileSymlinkException | InconsistentFilesystemException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 413 | throw new IllegalStateException("Package lookup succeeded but encountered error when " |
| 414 | + "getting FileValue for BUILD file directly.", e); |
| 415 | } |
| 416 | if (buildFileValue == null) { |
| 417 | return null; |
| 418 | } |
| 419 | Preconditions.checkState(buildFileValue.exists(), |
| 420 | "Package lookup succeeded but BUILD file doesn't exist"); |
| 421 | Path buildFilePath = buildFileRootedPath.asPath(); |
| 422 | |
| 423 | String replacementContents = null; |
| 424 | if (packageName.equals(DEFAULTS_PACKAGE_NAME)) { |
| 425 | replacementContents = PrecomputedValue.DEFAULTS_PACKAGE_CONTENTS.get(env); |
| 426 | if (replacementContents == null) { |
| 427 | return null; |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | RuleVisibility defaultVisibility = PrecomputedValue.DEFAULT_VISIBILITY.get(env); |
| 432 | if (defaultVisibility == null) { |
| 433 | return null; |
| 434 | } |
| 435 | |
| 436 | ASTFileLookupValue astLookupValue = null; |
Ulf Adams | 3ab82f7 | 2015-09-04 12:10:53 +0000 | [diff] [blame] | 437 | SkyKey astLookupKey = ASTFileLookupValue.key( |
| 438 | PackageIdentifier.createInDefaultRepo(preludePath)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 439 | try { |
| 440 | astLookupValue = (ASTFileLookupValue) env.getValueOrThrow(astLookupKey, |
| 441 | ErrorReadingSkylarkExtensionException.class, InconsistentFilesystemException.class); |
| 442 | } catch (ErrorReadingSkylarkExtensionException | InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 443 | throw new PackageFunctionException(new BadPreludeFileException(packageId, e.getMessage()), |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 444 | Transience.PERSISTENT); |
| 445 | } |
| 446 | if (astLookupValue == null) { |
| 447 | return null; |
| 448 | } |
Nathan Harmata | 8da263c | 2015-02-24 01:10:22 +0000 | [diff] [blame] | 449 | List<Statement> preludeStatements = astLookupValue.getAST() == null |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 450 | ? ImmutableList.<Statement>of() : astLookupValue.getAST().getStatements(); |
| 451 | |
| 452 | // Load the BUILD file AST and handle Skylark dependencies. This way BUILD files are |
| 453 | // only loaded twice if there are unavailable Skylark or package dependencies or an |
| 454 | // IOException occurs. Note that the BUILD files are still parsed two times. |
| 455 | ParserInputSource inputSource; |
| 456 | try { |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 457 | if (showLoadingProgress.get() && packageFunctionCache.getIfPresent(packageId) == null) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 458 | // TODO(bazel-team): don't duplicate the loading message if there are unavailable |
| 459 | // Skylark dependencies. |
| 460 | reporter.handle(Event.progress("Loading package: " + packageName)); |
| 461 | } |
Nathan Harmata | 7f24022 | 2015-09-13 02:03:26 +0000 | [diff] [blame] | 462 | inputSource = ParserInputSource.create(buildFilePath, buildFileValue.getSize()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 463 | } catch (IOException e) { |
| 464 | env.getListener().handle(Event.error(Location.fromFile(buildFilePath), e.getMessage())); |
| 465 | // Note that we did this work, so we should conservatively report this error as transient. |
| 466 | throw new PackageFunctionException(new BuildFileContainsErrorsException( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 467 | packageId, e.getMessage()), Transience.TRANSIENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 468 | } |
Lukacs Berki | f445ea1 | 2015-07-09 07:16:41 +0000 | [diff] [blame] | 469 | |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 470 | Package.LegacyBuilder legacyPkgBuilder = |
| 471 | loadPackage( |
| 472 | externalPkg, |
| 473 | inputSource, |
| 474 | replacementContents, |
| 475 | packageId, |
| 476 | buildFilePath, |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 477 | buildFileFragment, |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 478 | defaultVisibility, |
| 479 | preludeStatements, |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 480 | env); |
| 481 | if (legacyPkgBuilder == null) { |
| 482 | return null; |
| 483 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 484 | legacyPkgBuilder.buildPartial(); |
| 485 | try { |
| 486 | handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions( |
| 487 | packageLookupValue.getRoot(), packageId, legacyPkgBuilder, env); |
| 488 | } catch (InternalInconsistentFilesystemException e) { |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 489 | packageFunctionCache.invalidate(packageId); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 490 | throw new PackageFunctionException(e, |
| 491 | e.isTransient() ? Transience.TRANSIENT : Transience.PERSISTENT); |
| 492 | } |
| 493 | if (env.valuesMissing()) { |
| 494 | // The package we just loaded will be in the {@code packageFunctionCache} next when this |
| 495 | // SkyFunction is called again. |
| 496 | return null; |
| 497 | } |
| 498 | Collection<Pair<String, Boolean>> globPatterns = legacyPkgBuilder.getGlobPatterns(); |
| 499 | Map<Label, Path> subincludes = legacyPkgBuilder.getSubincludes(); |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 500 | Event.replayEventsOn(env.getListener(), legacyPkgBuilder.getEvents()); |
Mark Schaller | 6fc9f88 | 2015-06-12 17:53:57 +0000 | [diff] [blame] | 501 | boolean packageShouldBeConsideredInError; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 502 | try { |
| 503 | packageShouldBeConsideredInError = |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 504 | markDependenciesAndPropagateInconsistentFilesystemExceptions( |
| 505 | env, globPatterns, subincludes, packageId, legacyPkgBuilder.containsErrors()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 506 | } catch (InternalInconsistentFilesystemException e) { |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 507 | packageFunctionCache.invalidate(packageId); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 508 | throw new PackageFunctionException(e, |
| 509 | e.isTransient() ? Transience.TRANSIENT : Transience.PERSISTENT); |
| 510 | } |
| 511 | |
| 512 | if (env.valuesMissing()) { |
| 513 | return null; |
| 514 | } |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 515 | |
| 516 | if (packageShouldBeConsideredInError) { |
| 517 | legacyPkgBuilder.setContainsErrors(); |
| 518 | } |
| 519 | Package pkg = legacyPkgBuilder.finishBuild(); |
| 520 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 521 | // We know this SkyFunction will not be called again, so we can remove the cache entry. |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 522 | packageFunctionCache.invalidate(packageId); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 523 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 524 | return new PackageValue(pkg); |
| 525 | } |
| 526 | |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 527 | // TODO(bazel-team): this should take the AST so we don't parse the file twice. |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 528 | @Nullable |
| 529 | private SkylarkImportResult discoverSkylarkImports( |
| 530 | Path buildFilePath, |
| 531 | PathFragment buildFileFragment, |
| 532 | PackageIdentifier packageId, |
| 533 | Environment env, |
| 534 | ParserInputSource inputSource, |
| 535 | List<Statement> preludeStatements) |
| 536 | throws PackageFunctionException { |
| 537 | StoredEventHandler eventHandler = new StoredEventHandler(); |
| 538 | BuildFileAST buildFileAST = |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 539 | BuildFileAST.parseBuildFile( |
| 540 | inputSource, |
| 541 | preludeStatements, |
| 542 | eventHandler, |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 543 | /* parse python */ false); |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 544 | SkylarkImportResult importResult; |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 545 | if (eventHandler.hasErrors()) { |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 546 | importResult = |
| 547 | new SkylarkImportResult( |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 548 | ImmutableMap.<PathFragment, Extension>of(), |
| 549 | ImmutableList.<Label>of()); |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 550 | } else { |
| 551 | importResult = |
| 552 | fetchImportsFromBuildFile(buildFilePath, buildFileFragment, packageId, buildFileAST, env); |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 553 | } |
| 554 | |
| 555 | return importResult; |
| 556 | } |
| 557 | |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 558 | /** |
| 559 | * Fetch the skylark loads for this BUILD file. If any of them haven't been computed yet, |
| 560 | * returns null. |
| 561 | */ |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 562 | @Nullable |
| 563 | private SkylarkImportResult fetchImportsFromBuildFile( |
| 564 | Path buildFilePath, |
| 565 | PathFragment buildFileFragment, |
| 566 | PackageIdentifier packageId, |
| 567 | BuildFileAST buildFileAST, |
| 568 | Environment env) |
Lukacs Berki | f445ea1 | 2015-07-09 07:16:41 +0000 | [diff] [blame] | 569 | throws PackageFunctionException { |
Lukacs Berki | 145b701 | 2015-08-27 14:20:57 +0000 | [diff] [blame] | 570 | ImmutableMap<Location, PathFragment> imports = buildFileAST.getImports(); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 571 | Map<PathFragment, Extension> importMap = new HashMap<>(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 572 | ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder(); |
| 573 | try { |
Lukacs Berki | 145b701 | 2015-08-27 14:20:57 +0000 | [diff] [blame] | 574 | for (Map.Entry<Location, PathFragment> entry : imports.entrySet()) { |
| 575 | PathFragment importFile = entry.getValue(); |
| 576 | // HACK: The prelude sometimes contains load() statements, which need to be resolved |
| 577 | // relative to the prelude file. However, we don't have a good way to tell "this should come |
| 578 | // from the main repository" in a load() statement, and we don't have a good way to tell if |
| 579 | // a load() statement comes from the prelude, since we just prepend those statements before |
| 580 | // the actual BUILD file. So we use this evil .endsWith() statement to figure it out. |
| 581 | RepositoryName repository = |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 582 | entry.getKey().getPath().endsWith(preludePath) |
Lukacs Berki | 145b701 | 2015-08-27 14:20:57 +0000 | [diff] [blame] | 583 | ? PackageIdentifier.DEFAULT_REPOSITORY_NAME : packageId.getRepository(); |
| 584 | SkyKey importsLookupKey = SkylarkImportLookupValue.key( |
| 585 | repository, buildFileFragment, importFile); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 586 | SkylarkImportLookupValue importLookupValue = (SkylarkImportLookupValue) |
| 587 | env.getValueOrThrow(importsLookupKey, SkylarkImportFailedException.class, |
| 588 | InconsistentFilesystemException.class, ASTLookupInputException.class, |
| 589 | BuildFileNotFoundException.class); |
| 590 | if (importLookupValue != null) { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 591 | importMap.put(importFile, importLookupValue.getEnvironmentExtension()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 592 | fileDependencies.add(importLookupValue.getDependency()); |
| 593 | } |
| 594 | } |
| 595 | } catch (SkylarkImportFailedException e) { |
| 596 | env.getListener().handle(Event.error(Location.fromFile(buildFilePath), e.getMessage())); |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 597 | throw new PackageFunctionException( |
| 598 | new BuildFileContainsErrorsException(packageId, e.getMessage()), Transience.PERSISTENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 599 | } catch (InconsistentFilesystemException e) { |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 600 | throw new PackageFunctionException( |
| 601 | new InternalInconsistentFilesystemException(packageId, e), Transience.PERSISTENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 602 | } catch (ASTLookupInputException e) { |
| 603 | // The load syntax is bad in the BUILD file so BuildFileContainsErrorsException is OK. |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 604 | throw new PackageFunctionException( |
| 605 | new BuildFileContainsErrorsException(packageId, e.getMessage()), Transience.PERSISTENT); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 606 | } catch (BuildFileNotFoundException e) { |
| 607 | throw new PackageFunctionException(e, Transience.PERSISTENT); |
| 608 | } |
| 609 | if (env.valuesMissing()) { |
| 610 | // There are unavailable Skylark dependencies. |
| 611 | return null; |
| 612 | } |
| 613 | return new SkylarkImportResult(importMap, transitiveClosureOfLabels(fileDependencies.build())); |
| 614 | } |
| 615 | |
| 616 | private ImmutableList<Label> transitiveClosureOfLabels( |
| 617 | ImmutableList<SkylarkFileDependency> immediateDeps) { |
| 618 | Set<Label> transitiveClosure = Sets.newHashSet(); |
| 619 | transitiveClosureOfLabels(immediateDeps, transitiveClosure); |
| 620 | return ImmutableList.copyOf(transitiveClosure); |
| 621 | } |
| 622 | |
| 623 | private void transitiveClosureOfLabels( |
| 624 | ImmutableList<SkylarkFileDependency> immediateDeps, Set<Label> transitiveClosure) { |
| 625 | for (SkylarkFileDependency dep : immediateDeps) { |
Ulf Adams | 07dba94 | 2015-03-05 14:47:37 +0000 | [diff] [blame] | 626 | if (transitiveClosure.add(dep.getLabel())) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 627 | transitiveClosureOfLabels(dep.getDependencies(), transitiveClosure); |
| 628 | } |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | @Nullable |
| 633 | @Override |
| 634 | public String extractTag(SkyKey skyKey) { |
| 635 | return null; |
| 636 | } |
| 637 | |
| 638 | private static void handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions( |
| 639 | Path pkgRoot, PackageIdentifier pkgId, Package.LegacyBuilder pkgBuilder, Environment env) |
| 640 | throws InternalInconsistentFilesystemException { |
| 641 | Set<SkyKey> containingPkgLookupKeys = Sets.newHashSet(); |
| 642 | Map<Target, SkyKey> targetToKey = new HashMap<>(); |
| 643 | for (Target target : pkgBuilder.getTargets()) { |
| 644 | PathFragment dir = target.getLabel().toPathFragment().getParentDirectory(); |
| 645 | PackageIdentifier dirId = new PackageIdentifier(pkgId.getRepository(), dir); |
| 646 | if (dir.equals(pkgId.getPackageFragment())) { |
| 647 | continue; |
| 648 | } |
| 649 | SkyKey key = ContainingPackageLookupValue.key(dirId); |
| 650 | targetToKey.put(target, key); |
| 651 | containingPkgLookupKeys.add(key); |
| 652 | } |
| 653 | Map<Label, SkyKey> subincludeToKey = new HashMap<>(); |
| 654 | for (Label subincludeLabel : pkgBuilder.getSubincludeLabels()) { |
| 655 | PathFragment dir = subincludeLabel.toPathFragment().getParentDirectory(); |
| 656 | PackageIdentifier dirId = new PackageIdentifier(pkgId.getRepository(), dir); |
| 657 | if (dir.equals(pkgId.getPackageFragment())) { |
| 658 | continue; |
| 659 | } |
| 660 | SkyKey key = ContainingPackageLookupValue.key(dirId); |
| 661 | subincludeToKey.put(subincludeLabel, key); |
| 662 | containingPkgLookupKeys.add(ContainingPackageLookupValue.key(dirId)); |
| 663 | } |
| 664 | Map<SkyKey, ValueOrException3<BuildFileNotFoundException, InconsistentFilesystemException, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 665 | FileSymlinkException>> containingPkgLookupValues = env.getValuesOrThrow( |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 666 | containingPkgLookupKeys, BuildFileNotFoundException.class, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 667 | InconsistentFilesystemException.class, FileSymlinkException.class); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 668 | if (env.valuesMissing()) { |
| 669 | return; |
| 670 | } |
| 671 | for (Target target : ImmutableSet.copyOf(pkgBuilder.getTargets())) { |
| 672 | SkyKey key = targetToKey.get(target); |
| 673 | if (!containingPkgLookupValues.containsKey(key)) { |
| 674 | continue; |
| 675 | } |
| 676 | ContainingPackageLookupValue containingPackageLookupValue = |
| 677 | getContainingPkgLookupValueAndPropagateInconsistentFilesystemExceptions( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 678 | pkgId, containingPkgLookupValues.get(key), env); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 679 | if (maybeAddEventAboutLabelCrossingSubpackage(pkgBuilder, pkgRoot, target.getLabel(), |
| 680 | target.getLocation(), containingPackageLookupValue)) { |
| 681 | pkgBuilder.removeTarget(target); |
| 682 | pkgBuilder.setContainsErrors(); |
| 683 | } |
| 684 | } |
| 685 | for (Label subincludeLabel : pkgBuilder.getSubincludeLabels()) { |
| 686 | SkyKey key = subincludeToKey.get(subincludeLabel); |
| 687 | if (!containingPkgLookupValues.containsKey(key)) { |
| 688 | continue; |
| 689 | } |
| 690 | ContainingPackageLookupValue containingPackageLookupValue = |
| 691 | getContainingPkgLookupValueAndPropagateInconsistentFilesystemExceptions( |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 692 | pkgId, containingPkgLookupValues.get(key), env); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 693 | if (maybeAddEventAboutLabelCrossingSubpackage(pkgBuilder, pkgRoot, subincludeLabel, |
| 694 | /*location=*/null, containingPackageLookupValue)) { |
| 695 | pkgBuilder.setContainsErrors(); |
| 696 | } |
| 697 | } |
| 698 | } |
| 699 | |
| 700 | @Nullable |
| 701 | private static ContainingPackageLookupValue |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 702 | getContainingPkgLookupValueAndPropagateInconsistentFilesystemExceptions( |
| 703 | PackageIdentifier packageIdentifier, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 704 | ValueOrException3<BuildFileNotFoundException, InconsistentFilesystemException, |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 705 | FileSymlinkException> containingPkgLookupValueOrException, Environment env) |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 706 | throws InternalInconsistentFilesystemException { |
| 707 | try { |
| 708 | return (ContainingPackageLookupValue) containingPkgLookupValueOrException.get(); |
Nathan Harmata | ad81050 | 2015-07-29 01:33:49 +0000 | [diff] [blame] | 709 | } catch (BuildFileNotFoundException | FileSymlinkException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 710 | env.getListener().handle(Event.error(null, e.getMessage())); |
| 711 | return null; |
| 712 | } catch (InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 713 | throw new InternalInconsistentFilesystemException(packageIdentifier, e); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 714 | } |
| 715 | } |
| 716 | |
| 717 | private static boolean maybeAddEventAboutLabelCrossingSubpackage( |
| 718 | Package.LegacyBuilder pkgBuilder, Path pkgRoot, Label label, @Nullable Location location, |
| 719 | @Nullable ContainingPackageLookupValue containingPkgLookupValue) { |
| 720 | if (containingPkgLookupValue == null) { |
| 721 | return true; |
| 722 | } |
| 723 | if (!containingPkgLookupValue.hasContainingPackage()) { |
| 724 | // The missing package here is a problem, but it's not an error from the perspective of |
| 725 | // PackageFunction. |
| 726 | return false; |
| 727 | } |
| 728 | PackageIdentifier containingPkg = containingPkgLookupValue.getContainingPackageName(); |
| 729 | if (containingPkg.equals(label.getPackageIdentifier())) { |
| 730 | // The label does not cross a subpackage boundary. |
| 731 | return false; |
| 732 | } |
Kristina Chodorow | 1782a8f | 2015-08-12 11:35:07 +0000 | [diff] [blame] | 733 | if (!containingPkg.getPathFragment().startsWith( |
| 734 | label.getPackageIdentifier().getPathFragment())) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 735 | // This label is referencing an imaginary package, because the containing package should |
| 736 | // extend the label's package: if the label is //a/b:c/d, the containing package could be |
| 737 | // //a/b/c or //a/b, but should never be //a. Usually such errors will be caught earlier, but |
| 738 | // in some exceptional cases (such as a Python-aware BUILD file catching its own io |
| 739 | // exceptions), it reaches here, and we tolerate it. |
| 740 | return false; |
| 741 | } |
| 742 | PathFragment labelNameFragment = new PathFragment(label.getName()); |
| 743 | String message = String.format("Label '%s' crosses boundary of subpackage '%s'", |
| 744 | label, containingPkg); |
| 745 | Path containingRoot = containingPkgLookupValue.getContainingPackageRoot(); |
| 746 | if (pkgRoot.equals(containingRoot)) { |
| 747 | PathFragment labelNameInContainingPackage = labelNameFragment.subFragment( |
| 748 | containingPkg.getPackageFragment().segmentCount() |
| 749 | - label.getPackageFragment().segmentCount(), |
| 750 | labelNameFragment.segmentCount()); |
| 751 | message += " (perhaps you meant to put the colon here: " |
| 752 | + "'//" + containingPkg + ":" + labelNameInContainingPackage + "'?)"; |
| 753 | } else { |
| 754 | message += " (have you deleted " + containingPkg + "/BUILD? " |
| 755 | + "If so, use the --deleted_packages=" + containingPkg + " option)"; |
| 756 | } |
| 757 | pkgBuilder.addEvent(Event.error(location, message)); |
| 758 | return true; |
| 759 | } |
| 760 | |
| 761 | /** |
| 762 | * Constructs a {@link Package} object for the given package using legacy package loading. |
| 763 | * Note that the returned package may be in error. |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 764 | * |
| 765 | * <p>May return null if the computation has to be restarted. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 766 | */ |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 767 | @Nullable |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 768 | private Package.LegacyBuilder loadPackage( |
| 769 | Package externalPkg, |
| 770 | ParserInputSource inputSource, |
| 771 | @Nullable String replacementContents, |
| 772 | PackageIdentifier packageId, |
| 773 | Path buildFilePath, |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 774 | PathFragment buildFileFragment, |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 775 | RuleVisibility defaultVisibility, |
| 776 | List<Statement> preludeStatements, |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 777 | Environment env) |
Han-Wen Nienhuys | dab4313 | 2015-08-06 16:44:44 +0000 | [diff] [blame] | 778 | throws InterruptedException, PackageFunctionException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 779 | ParserInputSource replacementSource = replacementContents == null ? null |
Lukacs Berki | 4833822 | 2015-06-12 11:37:46 +0000 | [diff] [blame] | 780 | : ParserInputSource.create(replacementContents, buildFilePath.asFragment()); |
Eric Fellheimer | 35e57cf | 2015-05-27 14:31:11 +0000 | [diff] [blame] | 781 | Package.LegacyBuilder pkgBuilder = packageFunctionCache.getIfPresent(packageId); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 782 | if (pkgBuilder == null) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 783 | profiler.startTask(ProfilerTask.CREATE_PACKAGE, packageId.toString()); |
| 784 | try { |
| 785 | Globber globber = packageFactory.createLegacyGlobber(buildFilePath.getParentDirectory(), |
| 786 | packageId, packageLocator); |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 787 | Preprocessor.Result preprocessingResult = preprocessCache.getIfPresent(packageId); |
| 788 | if (preprocessingResult == null) { |
Janak Ramakrishnan | ac023bb | 2015-09-15 19:37:11 +0000 | [diff] [blame] | 789 | try { |
| 790 | preprocessingResult = |
| 791 | replacementSource == null |
| 792 | ? packageFactory.preprocess(packageId, inputSource, globber) |
| 793 | : Preprocessor.Result.noPreprocessing(replacementSource); |
| 794 | } catch (IOException e) { |
| 795 | env |
| 796 | .getListener() |
| 797 | .handle( |
| 798 | Event.error( |
| 799 | Location.fromFile(buildFilePath), |
| 800 | "preprocessing failed: " + e.getMessage())); |
| 801 | throw new PackageFunctionException( |
| 802 | new BuildFileContainsErrorsException(packageId, "preprocessing failed", e), |
| 803 | Transience.TRANSIENT); |
| 804 | } |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 805 | preprocessCache.put(packageId, preprocessingResult); |
| 806 | } |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 807 | |
| 808 | SkylarkImportResult importResult = |
| 809 | discoverSkylarkImports( |
| 810 | buildFilePath, |
| 811 | buildFileFragment, |
| 812 | packageId, |
| 813 | env, |
| 814 | preprocessingResult.result, |
| 815 | preludeStatements); |
| 816 | if (importResult == null) { |
| 817 | return null; |
| 818 | } |
Ulf Adams | d9b5121 | 2015-09-04 15:14:22 +0000 | [diff] [blame] | 819 | preprocessCache.invalidate(packageId); |
Han-Wen Nienhuys | 0648018 | 2015-08-07 15:22:35 +0000 | [diff] [blame] | 820 | |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 821 | pkgBuilder = packageFactory.createPackageFromPreprocessingResult(externalPkg, packageId, |
Ulf Adams | 14f8c25 | 2015-09-09 14:56:35 +0000 | [diff] [blame] | 822 | buildFilePath, preprocessingResult, preprocessingResult.events, preludeStatements, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 823 | importResult.importMap, importResult.fileDependencies, packageLocator, |
| 824 | defaultVisibility, globber); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 825 | numPackagesLoaded.incrementAndGet(); |
| 826 | packageFunctionCache.put(packageId, pkgBuilder); |
| 827 | } finally { |
| 828 | profiler.completeTask(ProfilerTask.CREATE_PACKAGE); |
| 829 | } |
| 830 | } |
| 831 | return pkgBuilder; |
| 832 | } |
| 833 | |
| 834 | private static class InternalInconsistentFilesystemException extends NoSuchPackageException { |
| 835 | private boolean isTransient; |
| 836 | |
| 837 | /** |
| 838 | * Used to represent a filesystem inconsistency discovered outside the |
| 839 | * {@link PackageFunction}. |
| 840 | */ |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 841 | public InternalInconsistentFilesystemException(PackageIdentifier packageIdentifier, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 842 | InconsistentFilesystemException e) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 843 | super(packageIdentifier, e.getMessage(), e); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 844 | // This is not a transient error from the perspective of the PackageFunction. |
| 845 | this.isTransient = false; |
| 846 | } |
| 847 | |
| 848 | /** Used to represent a filesystem inconsistency discovered by the {@link PackageFunction}. */ |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 849 | public InternalInconsistentFilesystemException(PackageIdentifier packageIdentifier, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 850 | String inconsistencyMessage) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 851 | this(packageIdentifier, new InconsistentFilesystemException(inconsistencyMessage)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 852 | this.isTransient = true; |
| 853 | } |
| 854 | |
| 855 | public boolean isTransient() { |
| 856 | return isTransient; |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | private static class BadWorkspaceFileException extends NoSuchPackageException { |
| 861 | private BadWorkspaceFileException(String message) { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 862 | super(ExternalPackage.PACKAGE_IDENTIFIER, |
| 863 | "Error encountered while dealing with the WORKSPACE file: " + message); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 864 | } |
| 865 | } |
| 866 | |
| 867 | private static class BadPreludeFileException extends NoSuchPackageException { |
Kristina Chodorow | e121dd9 | 2015-06-17 14:24:35 +0000 | [diff] [blame] | 868 | private BadPreludeFileException(PackageIdentifier packageIdentifier, String message) { |
| 869 | super(packageIdentifier, "Error encountered while reading the prelude file: " + message); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 870 | } |
| 871 | } |
| 872 | |
| 873 | /** |
| 874 | * Used to declare all the exception types that can be wrapped in the exception thrown by |
| 875 | * {@link PackageFunction#compute}. |
| 876 | */ |
| 877 | private static class PackageFunctionException extends SkyFunctionException { |
| 878 | public PackageFunctionException(NoSuchPackageException e, Transience transience) { |
| 879 | super(e, transience); |
| 880 | } |
| 881 | } |
| 882 | |
| 883 | /** A simple value class to store the result of the Skylark imports.*/ |
| 884 | private static final class SkylarkImportResult { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 885 | private final Map<PathFragment, Extension> importMap; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 886 | private final ImmutableList<Label> fileDependencies; |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 887 | private SkylarkImportResult( |
| 888 | Map<PathFragment, Extension> importMap, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 889 | ImmutableList<Label> fileDependencies) { |
| 890 | this.importMap = importMap; |
| 891 | this.fileDependencies = fileDependencies; |
| 892 | } |
| 893 | } |
| 894 | } |