Merge pull request from eikek/fix/2650-addon-extract

FIx extracting addons with only a single file
This commit is contained in:
mergify[bot] 2024-05-27 18:56:56 +00:00 committed by GitHub
commit 2bbeec677a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 21 additions and 7 deletions
modules
addonlib/src
main/scala/docspell/addons
test
common/src/main/scala/docspell/common/util

@ -38,9 +38,9 @@ final case class AddonArchive(url: LenientUri, name: String, version: String) {
Files[F].createDirectories(target) *> Files[F].createDirectories(target) *>
reader(url) reader(url)
.through(Zip[F](logger.some).unzip(glob = glob, targetDir = target.some)) .through(Zip[F](logger.some).unzip(glob = glob, targetDir = target.some))
.evalTap(_ => Directory.unwrapSingle[F](logger, target))
.compile .compile
.drain .drain
.flatTap(_ => Directory.unwrapSingle[F](logger, target))
.as(target) .as(target)
} }
} }

@ -9,7 +9,7 @@ package docspell.addons
import cats.effect._ import cats.effect._
import cats.syntax.option._ import cats.syntax.option._
import docspell.common.UrlReader import docspell.common._
import docspell.logging.TestLoggingConfig import docspell.logging.TestLoggingConfig
import munit._ import munit._
@ -42,10 +42,20 @@ class AddonArchiveTest extends CatsEffectSuite with TestLoggingConfig with Fixtu
} yield () } yield ()
} }
tempDir.test("read archive from zip with yaml only") { dir =>
for {
aa <- AddonArchive.read[IO](singleFileAddonUrl, UrlReader.defaultReader[IO], None)
_ = assertEquals(aa.version, "0.7.0")
path <- aa.extractTo(UrlReader.defaultReader[IO], dir)
read <- AddonArchive.read[IO](aa.url, UrlReader.defaultReader[IO], path.some)
_ = assertEquals(aa, read)
} yield ()
}
tempDir.test("Read generated addon from path") { dir => tempDir.test("Read generated addon from path") { dir =>
AddonGenerator.successAddon("mini-addon").use { addon => AddonGenerator.successAddon("mini-addon").use { addon =>
for { for {
archive <- IO(AddonArchive(addon.url, "", "")) archive <- IO(AddonArchive(addon.url, "test-addon", "0.1.0"))
path <- archive.extractTo[IO](UrlReader.defaultReader[IO], dir) path <- archive.extractTo[IO](UrlReader.defaultReader[IO], dir)
read <- AddonArchive.read[IO](addon.url, UrlReader.defaultReader[IO], path.some) read <- AddonArchive.read[IO](addon.url, UrlReader.defaultReader[IO], path.some)

@ -31,6 +31,9 @@ trait Fixtures extends TestLoggingConfig { self: CatsEffectSuite =>
val miniAddonUrl = val miniAddonUrl =
LenientUri.fromJava(getClass.getResource("/minimal-addon.zip")) LenientUri.fromJava(getClass.getResource("/minimal-addon.zip"))
val singleFileAddonUrl =
LenientUri.fromJava(getClass.getResource("/docspell-addon-single-file.zip"))
val dummyAddonMeta = val dummyAddonMeta =
AddonMeta( AddonMeta(
meta = meta =

@ -6,6 +6,7 @@
package docspell.common.util package docspell.common.util
import cats.data.OptionT
import cats.effect._ import cats.effect._
import cats.syntax.all._ import cats.syntax.all._
import cats.{Applicative, Monad} import cats.{Applicative, Monad}
@ -26,10 +27,10 @@ object Directory {
(dir :: dirs.toList).traverse_(Files[F].createDirectories(_)) (dir :: dirs.toList).traverse_(Files[F].createDirectories(_))
def nonEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] = def nonEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] =
List( OptionT
Files[F].isDirectory(dir), .whenM(Files[F].isDirectory(dir))(Files[F].list(dir).take(1).compile.toList)
Files[F].list(dir).take(1).compile.last.map(_.isDefined) .map(_.nonEmpty)
).sequence.map(_.forall(identity)) .isDefined
def isEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] = def isEmpty[F[_]: Files: Sync](dir: Path): F[Boolean] =
nonEmpty(dir).map(b => !b) nonEmpty(dir).map(b => !b)