Create the output directory when invoking repository_ctx.download_and_extract

Fixes #1172.

--
MOS_MIGRATED_REVID=124122716
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index 35b4e71..95911d1 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -293,11 +293,11 @@
     return osObject;
   }
 
-  private void createOutputDirectory() throws RepositoryFunctionException {
+  private void createDirectory(Path directory) throws RepositoryFunctionException {
     try {
-      if (!outputDirectory.exists()) {
-        makeDirectories(outputDirectory);
-        outputDirectory.createDirectory();
+      if (!directory.exists()) {
+        makeDirectories(directory);
+        directory.createDirectory();
       }
     } catch (IOException e) {
       throw new RepositoryFunctionException(e, Transience.TRANSIENT);
@@ -315,7 +315,7 @@
   )
   public SkylarkExecutionResult execute(List<Object> arguments, Integer timeout,
       Map<String, String> environment) throws EvalException, RepositoryFunctionException {
-    createOutputDirectory();
+    createDirectory(outputDirectory);
     return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables())
         .addArguments(arguments)
         .setDirectory(outputDirectory.getPathFile())
@@ -327,7 +327,7 @@
   @SkylarkCallable(name = "execute", documented = false)
   public SkylarkExecutionResult execute(List<Object> arguments)
       throws EvalException, RepositoryFunctionException {
-    createOutputDirectory();
+    createDirectory(outputDirectory);
     return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables())
         .setDirectory(outputDirectory.getPathFile())
         .addArguments(arguments)
@@ -338,7 +338,7 @@
   @SkylarkCallable(name = "execute", documented = false)
   public SkylarkExecutionResult execute(List<Object> arguments, Integer timeout)
       throws EvalException, RepositoryFunctionException {
-    createOutputDirectory();
+    createDirectory(outputDirectory);
     return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables())
         .setDirectory(outputDirectory.getPathFile())
         .addArguments(arguments)
@@ -458,6 +458,7 @@
     // Download to outputDirectory and delete it after extraction
     SkylarkPath outputPath = getPath("download_and_extract()", output);
     checkInOutputDirectory(outputPath);
+    createDirectory(outputPath.getPath());
     Path downloadedPath = HttpDownloader
         .download(url, sha256, type, outputPath.getPath(), env.getListener(),
             osObject.getEnvironmentVariables());
diff --git a/src/test/shell/bazel/skylark_repository_test.sh b/src/test/shell/bazel/skylark_repository_test.sh
index 7d5f30b..51d738b 100755
--- a/src/test/shell/bazel/skylark_repository_test.sh
+++ b/src/test/shell/bazel/skylark_repository_test.sh
@@ -359,7 +359,6 @@
   expect_log "erf"
 }
 
-
 function test_skylark_repository_execute_env_and_workdir() {
   setup_skylark_repository
 
@@ -548,6 +547,8 @@
   repository_ctx.download_and_extract(
     "http://localhost:${fileserver_port}/download_and_extract2.zip", "", "")
   repository_ctx.download_and_extract(
+    "http://localhost:${fileserver_port}/download_and_extract1.tar.gz", "some/path")
+  repository_ctx.download_and_extract(
     "http://localhost:${fileserver_port}/download_and_extract3.zip", ".", "${file_sha256}", "", "")
 repo = repository_rule(implementation=_impl, local=False)
 EOF
@@ -559,21 +560,24 @@
   output_base="$(bazel info output_base)"
   # Test cleanup
   test -e "${output_base}/external/foo/server_dir/download_and_extract1.tar.gz" \
-    && fail "temp file is not deleted successfully" || true
+    && fail "temp file was not deleted successfully" || true
   test -e "${output_base}/external/foo/server_dir/download_and_extract2.zip" \
-    && fail "temp file is not deleted successfully" || true
+    && fail "temp file was not deleted successfully" || true
   test -e "${output_base}/external/foo/server_dir/download_and_extract3.zip" \
-    && fail "temp file is not deleted successfully" || true
+    && fail "temp file was not deleted successfully" || true
   # Test download_and_extract
   diff "${output_base}/external/foo/server_dir/download_and_extract1.txt" \
     "${file_prefix}1.txt" >/dev/null \
-    || fail "download_and_extract1.tar.gz is not extracted successfully"
+    || fail "download_and_extract1.tar.gz was not extracted successfully"
+  diff "${output_base}/external/foo/some/path/server_dir/download_and_extract1.txt" \
+    "${file_prefix}1.txt" >/dev/null \
+    || fail "download_and_extract1.tar.gz was not extracted successfully in some/path"
   diff "${output_base}/external/foo/server_dir/download_and_extract2.txt" \
     "${file_prefix}2.txt" >/dev/null \
-    || fail "download_and_extract2.zip is not extracted successfully"
+    || fail "download_and_extract2.zip was not extracted successfully"
   diff "${output_base}/external/foo/server_dir/download_and_extract3.txt" \
     "${file_prefix}3.txt" >/dev/null \
-    || fail "download_and_extract3.zip is not extracted successfully"
+    || fail "download_and_extract3.zip was not extracted successfully"
 }
 
 # Test native.bazel_version