| // Copyright 2015 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.pkgcache; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; | |
| import com.google.common.base.Joiner; | |
| 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.common.eventbus.EventBus; | |
| import com.google.devtools.build.lib.actions.ActionKeyContext; | |
| import com.google.devtools.build.lib.analysis.BlazeDirectories; | |
| import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; | |
| import com.google.devtools.build.lib.analysis.ServerDirectories; | |
| import com.google.devtools.build.lib.analysis.util.DefaultBuildOptionsForTesting; | |
| import com.google.devtools.build.lib.clock.BlazeClock; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import com.google.devtools.build.lib.events.Reporter; | |
| import com.google.devtools.build.lib.packages.ConstantRuleVisibility; | |
| import com.google.devtools.build.lib.packages.NoSuchPackageException; | |
| import com.google.devtools.build.lib.packages.NoSuchTargetException; | |
| import com.google.devtools.build.lib.packages.NoSuchThingException; | |
| import com.google.devtools.build.lib.packages.Package; | |
| import com.google.devtools.build.lib.packages.PackageFactory; | |
| import com.google.devtools.build.lib.packages.Rule; | |
| import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions; | |
| import com.google.devtools.build.lib.packages.Target; | |
| import com.google.devtools.build.lib.packages.util.LoadingMock; | |
| import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction; | |
| import com.google.devtools.build.lib.skyframe.BazelSkyframeExecutorConstants; | |
| import com.google.devtools.build.lib.skyframe.DiffAwareness; | |
| import com.google.devtools.build.lib.skyframe.PrecomputedValue; | |
| import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutor; | |
| import com.google.devtools.build.lib.skyframe.SkyframeExecutor; | |
| import com.google.devtools.build.lib.testutil.ManualClock; | |
| import com.google.devtools.build.lib.testutil.TestConstants; | |
| import com.google.devtools.build.lib.util.AbruptExitException; | |
| import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor; | |
| import com.google.devtools.build.lib.vfs.Dirent; | |
| import com.google.devtools.build.lib.vfs.FileStatus; | |
| import com.google.devtools.build.lib.vfs.FileSystem; | |
| import com.google.devtools.build.lib.vfs.FileSystemUtils; | |
| import com.google.devtools.build.lib.vfs.ModifiedFileSet; | |
| import com.google.devtools.build.lib.vfs.Path; | |
| import com.google.devtools.build.lib.vfs.PathFragment; | |
| import com.google.devtools.build.lib.vfs.Root; | |
| import com.google.devtools.build.lib.vfs.RootedPath; | |
| import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; | |
| import com.google.devtools.common.options.Options; | |
| import com.google.devtools.common.options.OptionsProvider; | |
| import java.io.FileNotFoundException; | |
| import java.io.IOException; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import java.util.UUID; | |
| import javax.annotation.Nullable; | |
| import org.junit.Before; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| /** | |
| * Tests for incremental loading; these cover both normal operation and diff awareness, for which a | |
| * list of modified / added / removed files is available. | |
| */ | |
| @RunWith(JUnit4.class) | |
| public class IncrementalLoadingTest { | |
| protected PackageCacheTester tester; | |
| private Path throwOnReaddir = null; | |
| private Path throwOnStat = null; | |
| @Before | |
| public final void createTester() throws Exception { | |
| ManualClock clock = new ManualClock(); | |
| FileSystem fs = | |
| new InMemoryFileSystem(clock) { | |
| @Override | |
| public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException { | |
| if (path.equals(throwOnReaddir)) { | |
| throw new FileNotFoundException(path.getPathString()); | |
| } | |
| return super.readdir(path, followSymlinks); | |
| } | |
| @Nullable | |
| @Override | |
| public FileStatus stat(Path path, boolean followSymlinks) throws IOException { | |
| if (path.equals(throwOnStat)) { | |
| throw new IOException("bork " + path.getPathString()); | |
| } | |
| return super.stat(path, followSymlinks); | |
| } | |
| }; | |
| tester = createTester(fs, clock); | |
| } | |
| protected PackageCacheTester createTester(FileSystem fs, ManualClock clock) throws Exception { | |
| return new PackageCacheTester(fs, clock); | |
| } | |
| @Test | |
| public void testNoChange() throws Exception { | |
| tester.addFile("base/BUILD", | |
| "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| assertThat(oldTarget).isNotNull(); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testModifyBuildFile() throws Exception { | |
| tester.addFile("base/BUILD", "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.modifyFile("base/BUILD", "filegroup(name = 'hello', srcs = ['bar.txt'])"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isNotSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testModifyNonBuildFile() throws Exception { | |
| tester.addFile("base/BUILD", "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.addFile("base/foo.txt", "nothing"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.modifyFile("base/foo.txt", "other"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testRemoveNonBuildFile() throws Exception { | |
| tester.addFile("base/BUILD", "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.addFile("base/foo.txt", "nothing"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.removeFile("base/foo.txt"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testModifySymlinkedFileSamePackage() throws Exception { | |
| tester.addSymlink("base/BUILD", "mybuild"); | |
| tester.addFile("base/mybuild", "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.modifyFile("base/mybuild", "filegroup(name = 'hello', srcs = ['bar.txt'])"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isNotSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testModifySymlinkedFileDifferentPackage() throws Exception { | |
| tester.addSymlink("base/BUILD", "../other/BUILD"); | |
| tester.addFile("other/BUILD", "filegroup(name = 'hello', srcs = ['foo.txt'])"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.modifyFile("other/BUILD", "filegroup(name = 'hello', srcs = ['bar.txt'])"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isNotSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testBUILDSymlinkModifiedThenChanges() throws Exception { | |
| // We need to ensure that the timestamps of "one" and "two" are different, because Blaze | |
| // currently does not recognize changes to symlinks if the timestamps of the old and the new | |
| // file pointed to by the symlink are the same. | |
| tester.addFile("one", "filegroup(name='a', srcs=['1'])"); | |
| tester.sync(); | |
| tester.addFile("two", "filegroup(name='a', srcs=['2'])"); | |
| tester.addSymlink("oldlink", "one"); | |
| tester.addSymlink("newlink", "one"); | |
| tester.addSymlink("a/BUILD", "../oldlink"); | |
| tester.sync(); | |
| Target a1 = tester.getTarget("//a:a"); | |
| tester.modifySymlink("a/BUILD", "../newlink"); | |
| tester.sync(); | |
| tester.getTarget("//a:a"); | |
| tester.modifySymlink("newlink", "two"); | |
| tester.sync(); | |
| Target a3 = tester.getTarget("//a:a"); | |
| assertThat(a3).isNotSameInstanceAs(a1); | |
| } | |
| @Test | |
| public void testBUILDFileIsExternalSymlinkAndChanges() throws Exception { | |
| tester.addFile("/nonroot/file", "filegroup(name='a', srcs=['file'])"); | |
| tester.addSymlink("a/BUILD", "/nonroot/file"); | |
| tester.sync(); | |
| Target a1 = tester.getTarget("//a:a"); | |
| tester.modifyFile("/nonroot/file", "filegroup(name='a', srcs=['file2'])"); | |
| tester.sync(); | |
| Target a2 = tester.getTarget("//a:a"); | |
| tester.sync(); | |
| assertThat(a2).isNotSameInstanceAs(a1); | |
| } | |
| @Test | |
| public void testLabelWithTwoSegmentsAndTotalInvalidation() throws Exception { | |
| tester.addFile("a/BUILD", "filegroup(name='fg', srcs=['b/c'])"); | |
| tester.addFile("a/b/BUILD"); | |
| tester.sync(); | |
| Target fg1 = tester.getTarget("//a:fg"); | |
| tester.everythingModified(); | |
| tester.sync(); | |
| Target fg2 = tester.getTarget("//a:fg"); | |
| assertThat(fg2).isSameInstanceAs(fg1); | |
| } | |
| @Test | |
| public void testAddGlobFile() throws Exception { | |
| tester.addFile("base/BUILD", "filegroup(name = 'hello', srcs = glob(['*.txt']))"); | |
| tester.addFile("base/foo.txt", "nothing"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.addFile("base/bar.txt", "also nothing"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isNotSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testRemoveGlobFile() throws Exception { | |
| tester.addFile("base/BUILD", "filegroup(name = 'hello', srcs = glob(['*.txt']))"); | |
| tester.addFile("base/foo.txt", "nothing"); | |
| tester.addFile("base/bar.txt", "also nothing"); | |
| tester.sync(); | |
| Target oldTarget = tester.getTarget("//base:hello"); | |
| tester.removeFile("base/bar.txt"); | |
| tester.sync(); | |
| Target newTarget = tester.getTarget("//base:hello"); | |
| assertThat(newTarget).isNotSameInstanceAs(oldTarget); | |
| } | |
| @Test | |
| public void testPackageNotInLastBuildReplaced() throws Exception { | |
| tester.addFile("a/BUILD", "filegroup(name='a', srcs=['bad.sh'])"); | |
| tester.sync(); | |
| Target a1 = tester.getTarget("//a:a"); | |
| tester.addFile("b/BUILD", "filegroup(name='b', srcs=['b.sh'])"); | |
| tester.modifyFile("a/BUILD", "filegroup(name='a', srcs=['good.sh'])"); | |
| tester.sync(); | |
| tester.getTarget("//b:b"); | |
| tester.sync(); | |
| Target a2 = tester.getTarget("//a:a"); | |
| assertThat(a2).isNotSameInstanceAs(a1); | |
| } | |
| @Test | |
| public void testBrokenSymlinkAddedThenFixed() throws Exception { | |
| tester.addFile("a/BUILD", "filegroup(name='a', srcs=glob(['**']))"); | |
| tester.sync(); | |
| Target a1 = tester.getTarget("//a:a"); | |
| tester.addSymlink("a/b", "../c"); | |
| tester.sync(); | |
| tester.getTarget("//a:a"); | |
| tester.addFile("c"); | |
| tester.sync(); | |
| Target a3 = tester.getTarget("//a:a"); | |
| assertThat(a3).isNotSameInstanceAs(a1); | |
| } | |
| @Test | |
| public void testBuildFileWithSyntaxError() throws Exception { | |
| tester.addFile("a/BUILD", "sh_library(xyz='a')"); | |
| tester.sync(); | |
| assertThrows(NoSuchThingException.class, () -> tester.getTarget("//a:a")); | |
| tester.modifyFile("a/BUILD", "sh_library(name='a')"); | |
| tester.sync(); | |
| tester.getTarget("//a:a"); | |
| } | |
| @Test | |
| public void testSymlinkedBuildFileWithSyntaxError() throws Exception { | |
| tester.addFile("a/BUILD.real", "sh_library(xyz='a')"); | |
| tester.addSymlink("a/BUILD", "BUILD.real"); | |
| tester.sync(); | |
| assertThrows(NoSuchThingException.class, () -> tester.getTarget("//a:a")); | |
| tester.modifyFile("a/BUILD.real", "sh_library(name='a')"); | |
| tester.sync(); | |
| tester.getTarget("//a:a"); | |
| } | |
| @Test | |
| public void testTransientErrorsInGlobbing() throws Exception { | |
| Path buildFile = tester.addFile("e/BUILD", "sh_library(name = 'e', data = glob(['*.txt']))"); | |
| Path parentDir = buildFile.getParentDirectory(); | |
| tester.addFile("e/data.txt"); | |
| throwOnReaddir = parentDir; | |
| tester.sync(); | |
| assertThrows(NoSuchPackageException.class, () -> tester.getTarget("//e:e")); | |
| throwOnReaddir = null; | |
| tester.sync(); | |
| Target target = tester.getTarget("//e:e"); | |
| assertThat(((Rule) target).containsErrors()).isFalse(); | |
| List<?> globList = (List<?>) ((Rule) target).getAttributeContainer().getAttr("data"); | |
| assertThat(globList).containsExactly(Label.parseAbsolute("//e:data.txt", ImmutableMap.of())); | |
| } | |
| @Test | |
| public void testIrrelevantFileInSubdirDoesntReloadPackage() throws Exception { | |
| tester.addFile("pkg/BUILD", "sh_library(name = 'pkg', srcs = glob(['**/*.sh']))"); | |
| tester.addFile("pkg/pkg.sh", "#!/bin/bash"); | |
| tester.addFile("pkg/bar/bar.sh", "#!/bin/bash"); | |
| Package pkg = tester.getTarget("//pkg:pkg").getPackage(); | |
| // Write file in directory to force reload of top-level glob. | |
| tester.addFile("pkg/irrelevant_file"); | |
| tester.addFile("pkg/bar/irrelevant_file"); // Subglob is also reloaded. | |
| assertThat(tester.getTarget("//pkg:pkg").getPackage()).isSameInstanceAs(pkg); | |
| } | |
| @Test | |
| public void testMissingPackages() throws Exception { | |
| tester.sync(); | |
| assertThrows(NoSuchThingException.class, () -> tester.getTarget("//a:a")); | |
| tester.addFile("a/BUILD", "sh_library(name='a')"); | |
| tester.sync(); | |
| tester.getTarget("//a:a"); | |
| } | |
| @Test | |
| public void testChangedExternalFile() throws Exception { | |
| tester.addFile("a/BUILD", | |
| "load('//a:b.bzl', 'b')", | |
| "b()"); | |
| tester.addFile("/b.bzl", | |
| "def b():", | |
| " pass"); | |
| tester.addSymlink("a/b.bzl", "/b.bzl"); | |
| tester.sync(); | |
| tester.getTarget("//a:BUILD"); | |
| tester.modifyFile("/b.bzl", "ERROR ERROR"); | |
| tester.sync(); | |
| assertThrows(NoSuchThingException.class, () -> tester.getTarget("//a:BUILD")); | |
| } | |
| static class PackageCacheTester { | |
| private class ManualDiffAwareness implements DiffAwareness { | |
| private View lastView; | |
| private View currentView; | |
| @Override | |
| public View getCurrentView(OptionsProvider options) { | |
| lastView = currentView; | |
| currentView = new View() {}; | |
| return currentView; | |
| } | |
| @Override | |
| public ModifiedFileSet getDiff(View oldView, View newView) { | |
| if (oldView == lastView && newView == currentView) { | |
| return Preconditions.checkNotNull(modifiedFileSet); | |
| } else { | |
| return ModifiedFileSet.EVERYTHING_MODIFIED; | |
| } | |
| } | |
| @Override | |
| public String name() { | |
| return "PackageCacheTester.DiffAwareness"; | |
| } | |
| @Override | |
| public void close() { | |
| } | |
| } | |
| private class ManualDiffAwarenessFactory implements DiffAwareness.Factory { | |
| @Nullable | |
| @Override | |
| public DiffAwareness maybeCreate(Root pathEntry) { | |
| return pathEntry.asPath().equals(workspace) ? new ManualDiffAwareness() : null; | |
| } | |
| } | |
| private final ManualClock clock; | |
| private final Path workspace; | |
| private final Path outputBase; | |
| private final Reporter reporter = new Reporter(new EventBus()); | |
| private final SkyframeExecutor skyframeExecutor; | |
| private final List<Path> changes = new ArrayList<>(); | |
| private boolean everythingModified = false; | |
| private ModifiedFileSet modifiedFileSet; | |
| private final ActionKeyContext actionKeyContext = new ActionKeyContext(); | |
| public PackageCacheTester(FileSystem fs, ManualClock clock) throws IOException { | |
| this.clock = clock; | |
| workspace = fs.getPath("/workspace"); | |
| workspace.createDirectory(); | |
| outputBase = fs.getPath("/output_base"); | |
| outputBase.createDirectory(); | |
| addFile("WORKSPACE"); | |
| LoadingMock loadingMock = LoadingMock.get(); | |
| BlazeDirectories directories = | |
| new BlazeDirectories( | |
| new ServerDirectories( | |
| fs.getPath("/install"), fs.getPath("/output"), fs.getPath("/userRoot")), | |
| workspace, | |
| /* defaultSystemJavabase= */ null, | |
| loadingMock.getProductName()); | |
| ConfiguredRuleClassProvider ruleClassProvider = loadingMock.createRuleClassProvider(); | |
| PackageFactory pkgFactory = | |
| loadingMock.getPackageFactoryBuilderForTesting(directories).build(ruleClassProvider, fs); | |
| skyframeExecutor = | |
| BazelSkyframeExecutorConstants.newBazelSkyframeExecutorBuilder() | |
| .setPkgFactory(pkgFactory) | |
| .setFileSystem(fs) | |
| .setDirectories(directories) | |
| .setActionKeyContext(actionKeyContext) | |
| .setDefaultBuildOptions( | |
| DefaultBuildOptionsForTesting.getDefaultBuildOptionsForTest(ruleClassProvider)) | |
| .setDiffAwarenessFactories(ImmutableList.of(new ManualDiffAwarenessFactory())) | |
| .build(); | |
| TestConstants.processSkyframeExecutorForTesting(skyframeExecutor); | |
| PackageCacheOptions packageCacheOptions = Options.getDefaults(PackageCacheOptions.class); | |
| packageCacheOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC; | |
| packageCacheOptions.showLoadingProgress = true; | |
| packageCacheOptions.globbingThreads = 7; | |
| skyframeExecutor.injectExtraPrecomputedValues( | |
| ImmutableList.of( | |
| PrecomputedValue.injected( | |
| RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE, | |
| Optional.<RootedPath>absent()))); | |
| skyframeExecutor.preparePackageLoading( | |
| new PathPackageLocator( | |
| outputBase, | |
| ImmutableList.of(Root.fromPath(workspace)), | |
| BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY), | |
| packageCacheOptions, | |
| Options.getDefaults(StarlarkSemanticsOptions.class), | |
| UUID.randomUUID(), | |
| ImmutableMap.<String, String>of(), | |
| new TimestampGranularityMonitor(BlazeClock.instance())); | |
| skyframeExecutor.setActionEnv(ImmutableMap.<String, String>of()); | |
| } | |
| Path addFile(String fileName, String... content) throws IOException { | |
| Path buildFile = workspace.getRelative(fileName); | |
| Preconditions.checkState(!buildFile.exists()); | |
| Path currentPath = buildFile; | |
| // Add the new file and all the directories that will be created by | |
| // createDirectoryAndParents() | |
| while (!currentPath.exists()) { | |
| changes.add(currentPath); | |
| currentPath = currentPath.getParentDirectory(); | |
| } | |
| FileSystemUtils.createDirectoryAndParents(buildFile.getParentDirectory()); | |
| FileSystemUtils.writeContentAsLatin1(buildFile, Joiner.on('\n').join(content)); | |
| return buildFile; | |
| } | |
| void addSymlink(String fileName, String target) throws IOException { | |
| Path path = workspace.getRelative(fileName); | |
| Preconditions.checkState(!path.exists()); | |
| FileSystemUtils.createDirectoryAndParents(path.getParentDirectory()); | |
| path.createSymbolicLink(PathFragment.create(target)); | |
| changes.add(path); | |
| } | |
| void removeFile(String fileName) throws IOException { | |
| Path path = workspace.getRelative(fileName); | |
| Preconditions.checkState(path.delete()); | |
| changes.add(path); | |
| } | |
| void modifyFile(String fileName, String... content) throws IOException { | |
| Path path = workspace.getRelative(fileName); | |
| Preconditions.checkState(path.exists()); | |
| Preconditions.checkState(path.delete()); | |
| FileSystemUtils.writeContentAsLatin1(path, Joiner.on('\n').join(content)); | |
| changes.add(path); | |
| } | |
| void modifySymlink(String fileName, String newTarget) throws IOException { | |
| Path symlink = workspace.getRelative(fileName); | |
| Preconditions.checkState(symlink.exists()); | |
| symlink.delete(); | |
| symlink.createSymbolicLink(PathFragment.create(newTarget)); | |
| changes.add(symlink); | |
| } | |
| void everythingModified() { | |
| everythingModified = true; | |
| } | |
| private ModifiedFileSet getModifiedFileSet() { | |
| if (everythingModified) { | |
| everythingModified = false; | |
| return ModifiedFileSet.EVERYTHING_MODIFIED; | |
| } | |
| ModifiedFileSet.Builder builder = ModifiedFileSet.builder(); | |
| for (Path path : changes) { | |
| if (!path.startsWith(workspace)) { | |
| continue; | |
| } | |
| PathFragment workspacePath = path.relativeTo(workspace); | |
| builder.modify(workspacePath); | |
| } | |
| return builder.build(); | |
| } | |
| void sync() throws InterruptedException, AbruptExitException { | |
| clock.advanceMillis(1); | |
| modifiedFileSet = getModifiedFileSet(); | |
| PackageCacheOptions packageCacheOptions = Options.getDefaults(PackageCacheOptions.class); | |
| packageCacheOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC; | |
| packageCacheOptions.showLoadingProgress = true; | |
| packageCacheOptions.globbingThreads = 7; | |
| skyframeExecutor.preparePackageLoading( | |
| new PathPackageLocator( | |
| outputBase, | |
| ImmutableList.of(Root.fromPath(workspace)), | |
| BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY), | |
| packageCacheOptions, | |
| Options.getDefaults(StarlarkSemanticsOptions.class), | |
| UUID.randomUUID(), | |
| ImmutableMap.<String, String>of(), | |
| new TimestampGranularityMonitor(BlazeClock.instance())); | |
| skyframeExecutor.setActionEnv(ImmutableMap.<String, String>of()); | |
| skyframeExecutor.invalidateFilesUnderPathForTesting( | |
| new Reporter(new EventBus()), modifiedFileSet, Root.fromPath(workspace)); | |
| ((SequencedSkyframeExecutor) skyframeExecutor) | |
| .handleDiffsForTesting(new Reporter(new EventBus())); | |
| changes.clear(); | |
| } | |
| Target getTarget(String targetName) | |
| throws NoSuchPackageException, NoSuchTargetException, InterruptedException { | |
| Label label = Label.parseAbsoluteUnchecked(targetName); | |
| return skyframeExecutor.getPackageManager().getTarget(reporter, label); | |
| } | |
| } | |
| } |