Allow relative paths as arguments to `path.get_child`
This allows for usages such as:
```
some_path.get_child("nested", "directory")
relative_path = "user/provided"
some_path.get_child(relative_path)
```
RELNOTES: The `get_child` method of `path` now accepts an arbitrary
number of relative path strings as positional arguments.
Closes #15798.
PiperOrigin-RevId: 475519595
Change-Id: I92c317d7a0a0b02df6b392ab944c8a8cde5b2a93
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java
index 9489ec6..dc70f67 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java
@@ -18,13 +18,17 @@
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import javax.annotation.Nullable;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
+import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Printer;
+import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkValue;
+import net.starlark.java.eval.Tuple;
/**
* A Path object to be used into Starlark remote repository.
@@ -96,12 +100,19 @@
@StarlarkMethod(
name = "get_child",
- doc = "Append the given path to this path and return the resulted path.",
- parameters = {
- @Param(name = "child_path", doc = "The path to append to this path."),
- })
- public StarlarkPath getChild(String childPath) {
- return new StarlarkPath(path.getChild(childPath));
+ doc = "Returns the path obtained by joining this path with the given relative paths.",
+ extraPositionals =
+ @Param(
+ name = "relative_paths",
+ doc =
+ "Zero or more relative path strings to append to this path with path separators"
+ + "added as needed."))
+ public StarlarkPath getChild(Tuple relativePaths) throws EvalException {
+ return new StarlarkPath(
+ path.getRelative(
+ String.join(
+ Character.toString(PathFragment.SEPARATOR_CHAR),
+ Sequence.cast(relativePaths, String.class, "relative_paths"))));
}
@StarlarkMethod(
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD b/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD
index 0762c3c..3000579 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD
@@ -36,11 +36,13 @@
"//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+ "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
"//src/main/java/com/google/devtools/build/skyframe",
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
"//src/main/java/net/starlark/java/eval",
"//src/main/java/net/starlark/java/syntax",
"//src/test/java/com/google/devtools/build/lib/analysis/util",
+ "//src/test/java/com/google/devtools/build/lib/starlark/util",
"//src/test/java/com/google/devtools/build/lib/testutil",
"//third_party:guava",
"//third_party:jsr305",
@@ -82,11 +84,13 @@
"//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+ "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
"//src/main/java/com/google/devtools/build/skyframe",
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
"//src/main/java/net/starlark/java/eval",
"//src/main/java/net/starlark/java/syntax",
"//src/test/java/com/google/devtools/build/lib/analysis/util",
+ "//src/test/java/com/google/devtools/build/lib/starlark/util",
"//src/test/java/com/google/devtools/build/lib/testutil",
"//third_party:guava",
"//third_party:jsr305",
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPathTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPathTest.java
new file mode 100644
index 0000000..e6ebb59
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPathTest.java
@@ -0,0 +1,50 @@
+// Copyright 2014 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.bazel.repository.starlark;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.starlark.util.BazelEvaluationTestCase;
+import com.google.devtools.build.lib.vfs.DigestHashFunction;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for complex functions of {@link StarlarkPath}. */
+@RunWith(JUnit4.class)
+public class StarlarkPathTest {
+
+ private final BazelEvaluationTestCase ev = new BazelEvaluationTestCase();
+ private final FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
+ private final Path wd = FileSystemUtils.getWorkingDirectory(fs);
+
+ @Before
+ public void setup() throws Exception {
+ ev.update("wd", new StarlarkPath(wd));
+ }
+
+ @Test
+ public void testStarlarkPathGetChild() throws Exception {
+ assertThat(ev.eval("wd.get_child()")).isEqualTo(new StarlarkPath(wd));
+ assertThat(ev.eval("wd.get_child('foo')")).isEqualTo(new StarlarkPath(wd.getChild("foo")));
+ assertThat(ev.eval("wd.get_child('a','b/c','/d/')"))
+ .isEqualTo(new StarlarkPath(wd.getRelative("a/b/c/d")));
+ }
+}
diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl
index 146a88b..2691c7e 100644
--- a/tools/cpp/windows_cc_configure.bzl
+++ b/tools/cpp/windows_cc_configure.bzl
@@ -298,7 +298,7 @@
# By checking the source code of VCVARSALL.BAT in VC 2015, we know that
# when devenv.exe or wdexpress.exe exists, VCVARSALL.BAT supports Windows SDK selection.
- vc_common_ide = repository_ctx.path(vc_path).dirname.get_child("Common7").get_child("IDE")
+ vc_common_ide = repository_ctx.path(vc_path).dirname.get_child("Common7", "IDE")
for tool in ["devenv.exe", "wdexpress.exe"]:
if vc_common_ide.get_child(tool).exists:
return True
diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl
index 336b794d..05686c7 100644
--- a/tools/jdk/local_java_repository.bzl
+++ b/tools/jdk/local_java_repository.bzl
@@ -125,7 +125,7 @@
)
extension = ".exe" if repository_ctx.os.name.find("windows") != -1 else ""
- java_bin = java_home_path.get_child("bin").get_child("java" + extension)
+ java_bin = java_home_path.get_child("bin", "java" + extension)
if not java_bin.exists:
# Java binary does not exist