This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-5633-6723f074bc50f8e43f29e1e46bb7c665a0e032be in repository https://gitbox.apache.org/repos/asf/texera.git
commit ebaea080b5d64c5b19a2a91c18cbcd1ed33c8e50 Author: lie18uci <[email protected]> AuthorDate: Fri Jun 12 01:47:26 2026 -0700 fix(storage): close Files.walk stream in deleteRepo (#5633) ### What changes were proposed in this PR? This PR updates GitVersionControlLocalFileStorage.deleteRepo to close the stream returned by Files.walk(directoryPath) using try-with-resources. Files.walk(...) returns a closeable stream backed by directory resources. Wrapping it in try-with-resources ensures the stream is closed properly even if traversal or deletion throws. This keeps the existing deletion behavior unchanged while fixing the stream lifecycle. ### Any related issues, documentation, discussions? Closes #5548 ### How was this PR tested? Added GitVersionControlLocalFileStorageSpec, which creates a temporary nested repository directory, calls deleteRepo, and verifies that the repository directory is deleted recursively. Ran formatting locally: sbt scalafmtAll sbt scalafmtCheckAll scalafmtCheckAll passed successfully. Attempted to run the targeted test locally: sbt "WorkflowCore / testOnly org.apache.texera.amber.core.storage.util.dataset.GitVersionControlLocalFileStorageSpec" but my local backend setup could not generate jOOQ classes because PostgreSQL was not running on localhost:5432. The failure occurred before the test ran, due to missing generated org.apache.texera.dao.jooq.generated classes. I am relying on GitHub CI to run the backend test in the configured environment. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: ChatGPT --- .../dataset/GitVersionControlLocalFileStorage.java | 10 ++-- .../GitVersionControlLocalFileStorageSpec.scala | 59 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorage.java b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorage.java index 72566dd2d7..9208bad126 100644 --- a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorage.java +++ b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorage.java @@ -78,10 +78,12 @@ public class GitVersionControlLocalFileStorage { * @throws IOException If an I/O error occurs. */ public static void deleteRepo(Path directoryPath) throws IOException { - Files.walk(directoryPath) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); + try (var stream = Files.walk(directoryPath)) { + stream + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } } /** diff --git a/common/workflow-core/src/test/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorageSpec.scala b/common/workflow-core/src/test/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorageSpec.scala new file mode 100644 index 0000000000..1254efe297 --- /dev/null +++ b/common/workflow-core/src/test/scala/org/apache/texera/amber/core/storage/util/dataset/GitVersionControlLocalFileStorageSpec.scala @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.texera.amber.core.storage.util.dataset + +import org.scalatest.flatspec.AnyFlatSpec + +import java.nio.file.{Files, Path} +import scala.jdk.CollectionConverters._ +import scala.util.Using + +class GitVersionControlLocalFileStorageSpec extends AnyFlatSpec { + + private def deleteIfExists(path: Path): Unit = { + if (Files.exists(path)) { + Using.resource(Files.walk(path)) { stream => + stream.iterator().asScala.toSeq.reverse.foreach(Files.deleteIfExists) + } + } + } + + "GitVersionControlLocalFileStorage.deleteRepo" should "delete a repository directory recursively" in { + val repoDir = Files.createTempDirectory("texera-delete-repo-test") + + try { + val nestedDir = Files.createDirectories(repoDir.resolve("nested").resolve("child")) + val rootFile = Files.writeString(repoDir.resolve("root.txt"), "root") + val nestedFile = Files.writeString(nestedDir.resolve("data.txt"), "data") + + assert(Files.exists(repoDir)) + assert(Files.exists(rootFile)) + assert(Files.exists(nestedFile)) + + GitVersionControlLocalFileStorage.deleteRepo(repoDir) + + assert(!Files.exists(repoDir)) + } finally { + deleteIfExists(repoDir) + } + } +}
