Add managed_directories attribute to workspace() function.
This is only a part of the incrementally updated user-owned directory feature; that is why the parsed value is not yet used in computations.
- Under --experimental_allow_incremental_repository_updates flag.
- Parse results are put into WorkspaceFileValue map field.
PiperOrigin-RevId: 244819268
diff --git a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
index 08eeec2..7e2df6f 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
@@ -118,6 +118,7 @@
private static StarlarkSemanticsOptions buildRandomOptions(Random rand) throws Exception {
return parseOptions(
// <== Add new options here in alphabetic order ==>
+ "--experimental_allow_incremental_repository_updates=" + rand.nextBoolean(),
"--experimental_build_setting_api=" + rand.nextBoolean(),
"--experimental_cc_skylark_api_enabled_packages="
+ rand.nextDouble()
@@ -172,6 +173,7 @@
private static StarlarkSemantics buildRandomSemantics(Random rand) {
return StarlarkSemantics.builder()
// <== Add new options here in alphabetic order ==>
+ .experimentalAllowIncrementalRepositoryUpdates(rand.nextBoolean())
.experimentalBuildSettingApi(rand.nextBoolean())
.experimentalCcSkylarkApiEnabledPackages(
ImmutableList.of(String.valueOf(rand.nextDouble()), String.valueOf(rand.nextDouble())))
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
index e8754f7..a69e001 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
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.actions.FileStateValue;
@@ -32,6 +33,7 @@
import com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.WorkspaceFileValue;
+import com.google.devtools.build.lib.packages.WorkspaceFileValue.WorkspaceFileKey;
import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutor.WorkspaceFileHeaderListener;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
@@ -44,6 +46,7 @@
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.Injectable;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
@@ -306,6 +309,104 @@
}
@Test
+ public void testManagedDirectories() throws Exception {
+ PrecomputedValue precomputedValue =
+ (PrecomputedValue)
+ getEnv().getValue(PrecomputedValue.STARLARK_SEMANTICS.getKeyForTesting());
+ StarlarkSemantics semantics =
+ (StarlarkSemantics) Preconditions.checkNotNull(precomputedValue).get();
+ Injectable injectable = getSkyframeExecutor().injectable();
+ try {
+ StarlarkSemantics semanticsWithManagedDirectories =
+ StarlarkSemantics.builderWithDefaults()
+ .experimentalAllowIncrementalRepositoryUpdates(true)
+ .build();
+ PrecomputedValue.STARLARK_SEMANTICS.set(injectable, semanticsWithManagedDirectories);
+
+ WorkspaceFileValue workspaceFileValue =
+ parseWorkspaceFileValue(
+ "workspace(",
+ " name = 'rr',",
+ " managed_directories = {'@repo1': ['dir1', 'dir2'], '@repo2': ['dir3/dir1/..']}",
+ ")");
+ ImmutableMap<PathFragment, RepositoryName> managedDirectories =
+ workspaceFileValue.getManagedDirectories();
+ assertThat(managedDirectories).isNotNull();
+ assertThat(managedDirectories).hasSize(3);
+ assertThat(managedDirectories)
+ .containsExactly(
+ PathFragment.create("dir1"), RepositoryName.create("@repo1"),
+ PathFragment.create("dir2"), RepositoryName.create("@repo1"),
+ PathFragment.create("dir3"), RepositoryName.create("@repo2"));
+
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': 'dir1', '@repo2': ['dir3']}",
+ "managed_directories attribute value should be of the type attr.string_list_dict(),"
+ + " mapping repository name to the list of managed directories.");
+
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['dir1'], '@repo2': ['dir1']}",
+ "managed_directories attribute should not contain multiple (or duplicate) repository"
+ + " mappings for the same directory ('dir1').");
+
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['']}", "Expected managed directory path to be non-empty string.");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['/abc']}",
+ "Expected managed directory path ('/abc') to be relative to the workspace root.");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['../abc']}",
+ "Expected managed directory path ('../abc') to be under the workspace root.");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['a/b', 'a/b']}",
+ "managed_directories attribute should not contain multiple (or duplicate)"
+ + " repository mappings for the same directory ('a/b').");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': [], '@repo1': [] }", "Duplicated key \"@repo1\" when creating dictionary");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['a/b'], '@repo2': ['a/b/c/..'] }",
+ "managed_directories attribute should not contain multiple (or duplicate)"
+ + " repository mappings for the same directory ('a/b/c/..').");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['a'], '@repo2': ['a/b'] }",
+ "managed_directories attribute value can not contain nested mappings."
+ + " 'a/b' is a descendant of 'a'.");
+ assertManagedDirectoriesParsingError(
+ "{'@repo1': ['a/b'], '@repo2': ['a'] }",
+ "managed_directories attribute value can not contain nested mappings."
+ + " 'a/b' is a descendant of 'a'.");
+
+ assertManagedDirectoriesParsingError(
+ "{'repo1': []}",
+ "Cannot parse repository name 'repo1'. Repository name should start with '@'.");
+ } finally {
+ PrecomputedValue.STARLARK_SEMANTICS.set(injectable, semantics);
+ }
+ }
+
+ private void assertManagedDirectoriesParsingError(
+ String managedDirectoriesValue, String expectedError)
+ throws IOException, InterruptedException {
+ WorkspaceFileValue workspaceFileValue =
+ parseWorkspaceFileValue(
+ "workspace(",
+ " name = 'rr',",
+ " managed_directories = " + managedDirectoriesValue,
+ ")");
+ Package pkg = workspaceFileValue.getPackage();
+ assertThat(pkg.containsErrors()).isTrue();
+ MoreAsserts.assertContainsEvent(pkg.getEvents(), expectedError);
+ }
+
+ private WorkspaceFileValue parseWorkspaceFileValue(String... lines)
+ throws IOException, InterruptedException {
+ RootedPath workspaceFile = createWorkspaceFile(lines);
+ WorkspaceFileKey key = WorkspaceFileValue.key(workspaceFile);
+ EvaluationResult<WorkspaceFileValue> result = eval(key);
+ return result.get(key);
+ }
+
+ @Test
public void testInvalidRepo() throws Exception {
RootedPath workspacePath = createWorkspaceFile("workspace(name = 'foo$')");
PackageValue value =