From 95df07103473e7fd954186c0260f13e43f1faf12 Mon Sep 17 00:00:00 2001 From: memo Date: Mon, 21 Oct 2024 19:35:25 +0200 Subject: [PATCH] improve error message if channel build randomly fails This also improves error message in case input directory does not exist. Additionally, this prevents an error in case an empty channel is built. (resolves #6) --- CHANGELOG.md | 3 +++ src/main/scala/sc4pac/ChannelUtil.scala | 25 +++++++++++++++++++------ src/main/scala/sc4pac/cli.scala | 1 + src/main/scala/sc4pac/error.scala | 2 ++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4407b6c..87416cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased] +### Changed +- improved error message if channel-build fails randomly in case old files could not be removed + ## [0.4.5] - 2024-10-17 ### Fixed diff --git a/src/main/scala/sc4pac/ChannelUtil.scala b/src/main/scala/sc4pac/ChannelUtil.scala index 0d5d9df..6cf23e9 100644 --- a/src/main/scala/sc4pac/ChannelUtil.scala +++ b/src/main/scala/sc4pac/ChannelUtil.scala @@ -180,18 +180,31 @@ object ChannelUtil { // Finally, we are sure that everything was formatted correctly, so we can // move the temp folder to its final destination. - os.move.over(tempJsonDir / "metadata", outputDir / "metadata", createFolders = true) + try { + if (packages.nonEmpty) { // otherwise metadata folder does not exist (we still want channel contents file though) + os.move.over(tempJsonDir / "metadata", outputDir / "metadata", createFolders = true) + } + } catch { + case e: java.nio.file.DirectoryNotEmptyException => + throw new error.FileOpsFailure( + s"""Failed to overwrite folder ${outputDir / "metadata"}. If the problem persists, delete it manually and try again.""") + } os.move.over(tempJsonDir / JsonRepoUtil.channelContentsFilename, outputDir / JsonRepoUtil.channelContentsFilename, createFolders = true) System.err.println(s"Successfully wrote channel contents of ${packagesMap.size} packages and assets.") } val packagesTask: Task[Seq[JD.PackageAsset]] = ZIO.foreach(inputDirs) { inputDir => - ZIO.foreach(os.walk.stream(inputDir).filter(_.last.endsWith(".yaml")).toSeq) { path => - readAndParsePkgData(path, root = Some(inputDir)) - }.map(_.flatten) - }.map(_.flatten) - .mapError(error.YamlFormatIssue(_)) + ZIO.ifZIO(ZIO.attemptBlockingIO(os.exists(inputDir)))( + onFalse = ZIO.fail(new error.FileOpsFailure(s"$inputDir does not exist.")), + onTrue = ZIO.foreach(os.walk.stream(inputDir).filter(_.last.endsWith(".yaml")).toSeq) { path => + readAndParsePkgData(path, root = Some(inputDir)) + }.map(_.flatten) + ) + }.map(_.flatten).mapError { + case errStr: String => error.YamlFormatIssue(errStr) + case e: java.io.IOException => e + } // result ZIO.blocking { diff --git a/src/main/scala/sc4pac/cli.scala b/src/main/scala/sc4pac/cli.scala index afc9600..6de29d0 100644 --- a/src/main/scala/sc4pac/cli.scala +++ b/src/main/scala/sc4pac/cli.scala @@ -53,6 +53,7 @@ object Commands { case abort: error.Sc4pacTimeout => { System.err.println(Array("Operation aborted.", abort.getMessage).mkString(" ")); exit(1) } case abort: error.Sc4pacNotInteractive => { System.err.println(s"Operation aborted as terminal is non-interactive: ${abort.getMessage}"); exit(1) } case abort: error.SymlinkCreationFailed => { System.err.println(s"Operation aborted. ${abort.getMessage}"); exit(1) } // channel-build command + case abort: error.FileOpsFailure => { System.err.println(s"Operation aborted. ${abort.getMessage}"); exit(1) } // channel-build command case abort: error.YamlFormatIssue => { System.err.println(s"Operation aborted. ${abort.getMessage}"); exit(1) } // channel-build command case e => { e.printStackTrace(); exit(2) } }, diff --git a/src/main/scala/sc4pac/error.scala b/src/main/scala/sc4pac/error.scala index aeef9b6..ad3fd6a 100644 --- a/src/main/scala/sc4pac/error.scala +++ b/src/main/scala/sc4pac/error.scala @@ -32,4 +32,6 @@ final class NoChannelsAvailable(val title: String, val detail: String) extends j final class SymlinkCreationFailed(msg: String) extends java.io.IOException(msg) with Sc4pacErr +final class FileOpsFailure(msg: String) extends java.io.IOException(msg) with Sc4pacErr + final class YamlFormatIssue(msg: String) extends java.io.IOException(msg) with Sc4pacErr