Cleanup parent folders when deleting downloaded chapters (#776)

Currently, the download folder never gets cleaned up which leads to having a lot of empty folders (sources, mangas folders)
This commit is contained in:
schroda
2023-11-20 01:22:06 +01:00
committed by GitHub
parent 50cd0c4e10
commit 909bd76e08
3 changed files with 58 additions and 14 deletions

View File

@@ -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.ZipArchiveInputStream
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
import org.apache.commons.compress.archivers.zip.ZipFile 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.fileProvider.ChaptersFilesProvider
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath
import suwayomi.tachidesk.manga.impl.util.getMangaDownloadDir 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.File
import java.io.InputStream import java.io.InputStream
private val applicationDirs by DI.global.instance<ApplicationDirs>()
class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mangaId, chapterId) { class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mangaId, chapterId) {
override fun getImageImpl(index: Int): Pair<InputStream, String> { override fun getImageImpl(index: Int): Pair<InputStream, String> {
val cbzPath = getChapterCbzPath(mangaId, chapterId) val cbzPath = getChapterCbzPath(mangaId, chapterId)
@@ -67,8 +74,13 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
override fun delete(): Boolean { override fun delete(): Boolean {
val cbzFile = File(getChapterCbzPath(mangaId, chapterId)) val cbzFile = File(getChapterCbzPath(mangaId, chapterId))
if (cbzFile.exists()) return cbzFile.delete() if (!cbzFile.exists()) {
return false return true
}
val cbzDeleted = cbzFile.delete()
FileDeletionHelper.cleanupParentFoldersFor(cbzFile, applicationDirs.mangaDownloadsRoot)
return cbzDeleted
} }
private fun handleExistingCbzFile( private fun handleExistingCbzFile(

View File

@@ -1,14 +1,21 @@
package suwayomi.tachidesk.manga.impl.download.fileProvider.impl package suwayomi.tachidesk.manga.impl.download.fileProvider.impl
import kotlinx.coroutines.CoroutineScope 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.fileProvider.ChaptersFilesProvider
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath 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.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.InputStream import java.io.InputStream
private val applicationDirs by DI.global.instance<ApplicationDirs>()
/* /*
* Provides downloaded files when pages were downloaded into folders * 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 { override fun delete(): Boolean {
val chapterDir = getChapterDownloadPath(mangaId, chapterId) val chapterDirPath = getChapterDownloadPath(mangaId, chapterId)
return File(chapterDir).deleteRecursively() val chapterDir = File(chapterDirPath)
} if (!chapterDir.exists()) {
return true
}
private fun isExistingFile( val chapterDirDeleted = chapterDir.deleteRecursively()
folder: File, FileDeletionHelper.cleanupParentFoldersFor(chapterDir, applicationDirs.mangaDownloadsRoot)
fileName: String, return chapterDirDeleted
): Boolean {
val existingFile =
folder.listFiles { file ->
file.isFile && file.name.startsWith(fileName)
}?.firstOrNull()
return existingFile?.exists() == true
} }
} }

View File

@@ -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)
}
}