diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt index fa88d6d49..80f0bc1d1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt @@ -7,14 +7,21 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream import org.apache.commons.compress.archivers.zip.ZipFile +import org.kodein.di.DI +import org.kodein.di.conf.global +import org.kodein.di.instance import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath import suwayomi.tachidesk.manga.impl.util.getMangaDownloadDir +import suwayomi.tachidesk.manga.impl.util.storage.FileDeletionHelper +import suwayomi.tachidesk.server.ApplicationDirs import java.io.File import java.io.InputStream +private val applicationDirs by DI.global.instance() + class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mangaId, chapterId) { override fun getImageImpl(index: Int): Pair { val cbzPath = getChapterCbzPath(mangaId, chapterId) @@ -67,8 +74,13 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang override fun delete(): Boolean { val cbzFile = File(getChapterCbzPath(mangaId, chapterId)) - if (cbzFile.exists()) return cbzFile.delete() - return false + if (!cbzFile.exists()) { + return true + } + + val cbzDeleted = cbzFile.delete() + FileDeletionHelper.cleanupParentFoldersFor(cbzFile, applicationDirs.mangaDownloadsRoot) + return cbzDeleted } private fun handleExistingCbzFile( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt index 9035ad7d2..9c3b0b261 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt @@ -1,14 +1,21 @@ package suwayomi.tachidesk.manga.impl.download.fileProvider.impl import kotlinx.coroutines.CoroutineScope +import org.kodein.di.DI +import org.kodein.di.conf.global +import org.kodein.di.instance import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath +import suwayomi.tachidesk.manga.impl.util.storage.FileDeletionHelper +import suwayomi.tachidesk.server.ApplicationDirs import java.io.File import java.io.FileInputStream import java.io.InputStream +private val applicationDirs by DI.global.instance() + /* * Provides downloaded files when pages were downloaded into folders * */ @@ -42,18 +49,14 @@ class FolderProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(manga } override fun delete(): Boolean { - val chapterDir = getChapterDownloadPath(mangaId, chapterId) - return File(chapterDir).deleteRecursively() - } + val chapterDirPath = getChapterDownloadPath(mangaId, chapterId) + val chapterDir = File(chapterDirPath) + if (!chapterDir.exists()) { + return true + } - private fun isExistingFile( - folder: File, - fileName: String, - ): Boolean { - val existingFile = - folder.listFiles { file -> - file.isFile && file.name.startsWith(fileName) - }?.firstOrNull() - return existingFile?.exists() == true + val chapterDirDeleted = chapterDir.deleteRecursively() + FileDeletionHelper.cleanupParentFoldersFor(chapterDir, applicationDirs.mangaDownloadsRoot) + return chapterDirDeleted } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/FileDeletionHelper.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/FileDeletionHelper.kt new file mode 100644 index 000000000..b9dbee22f --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/FileDeletionHelper.kt @@ -0,0 +1,29 @@ +package suwayomi.tachidesk.manga.impl.util.storage + +import java.io.File + +object FileDeletionHelper { + /** + * Recursively deletes all parent folders for the given deleted file until the parent folder is not empty, or it's the root folder + */ + fun cleanupParentFoldersFor( + file: File, + rootPath: String, + ) { + val folder = file.parentFile + if (!folder.isDirectory) { + return + } + + if (folder.absolutePath == rootPath) { + return + } + + if (folder.listFiles()?.isEmpty() != true) { + return + } + + folder.delete() + cleanupParentFoldersFor(folder, rootPath) + } +}