From 6732cf4cadfbbab853793c6f3cb195091d9c2a39 Mon Sep 17 00:00:00 2001 From: Liplum Date: Wed, 20 Dec 2023 03:04:10 +0800 Subject: [PATCH] copyToTmpAndMove --- main/src/dsl/FileSystem.kt | 22 +++++++------- main/src/run/model/Mods.kt | 16 +++++++++- main/src/task/ResolveGame.kt | 13 +++----- main/src/task/ResolveMods.kt | 58 ++++++++++++++---------------------- 4 files changed, 53 insertions(+), 56 deletions(-) diff --git a/main/src/dsl/FileSystem.kt b/main/src/dsl/FileSystem.kt index 4ef7fca..d2e14e3 100644 --- a/main/src/dsl/FileSystem.kt +++ b/main/src/dsl/FileSystem.kt @@ -7,6 +7,7 @@ import org.gradle.api.Task import java.io.File import java.io.InputStream import java.net.URL +import java.nio.file.FileSystem import java.nio.file.Files /** @@ -14,24 +15,23 @@ import java.nio.file.Files * @receiver Caller has responsibility to close this stream */ internal -fun InputStream.copyTo(file: File): File { +fun InputStream.copyTo(file: File) { file.outputStream().use { this.copyTo(it) } - return file } -/** - * Copy data from this url to [file]. - * It will create the parent folder if it doesn't exist. - */ internal -fun URL.copyTo(file: File): File { - file.parentFile.mkdirs() - this.openStream().use { - it.copyTo(file) +fun InputStream.copyToTmpAndMove(file: File) { + val tmp = Files.createTempFile(file.name, null).toFile() + this.use { + it.copyTo(tmp) + } + tmp.renameTo(file) + // ignore the error when deleting the temp file + runCatching { + tmp.delete() } - return file } internal diff --git a/main/src/run/model/Mods.kt b/main/src/run/model/Mods.kt index a3a2f4e..6bbb45d 100644 --- a/main/src/run/model/Mods.kt +++ b/main/src/run/model/Mods.kt @@ -8,6 +8,7 @@ import java.io.File import java.io.Serializable import java.net.URL import java.security.MessageDigest +import kotlin.math.absoluteValue /** * An abstract mod file. @@ -216,4 +217,17 @@ fun tryReadGitHubModInfo(infoFi: File, logger: Logger? = null): GihHubModDownloa } else { writeAndGetDefault() } -} \ No newline at end of file +} + +fun IGitHubMod.isUpdateToDate(): Boolean { + val cacheFile = this.resolveCacheFile() + val infoFi = File("$cacheFile.$infoX") + if (!cacheFile.exists()) { + if (infoFi.exists()) infoFi.delete() + return false + } + val meta = tryReadGitHubModInfo(infoFi) + val curTime = System.currentTimeMillis() + // TODO: Configurable out-of-date time + return curTime - meta.lastUpdateTimestamp < R.outOfDataTime.absoluteValue +} diff --git a/main/src/task/ResolveGame.kt b/main/src/task/ResolveGame.kt index b9f52b2..137fd4b 100644 --- a/main/src/task/ResolveGame.kt +++ b/main/src/task/ResolveGame.kt @@ -1,7 +1,6 @@ package io.github.liplum.mindustry -import io.github.liplum.dsl.copyTo -import io.github.liplum.dsl.createSymbolicLinkOrCopyCache +import io.github.liplum.dsl.* import io.github.liplum.dsl.fileProp import io.github.liplum.dsl.prop import org.gradle.api.DefaultTask @@ -45,14 +44,10 @@ open class ResolveGame : DefaultTask() { fun IDownloadableGameLoc.download(cacheFile: File) { logger.lifecycle("Downloading $this -> $cacheFile...") try { - this.resolveDownloadSrc().openStream().use { - it.copyTo(cacheFile) - } - logger.lifecycle("${this.fileName4Local} was downloaded.") + this.resolveDownloadSrc().openStream().copyToTmpAndMove(cacheFile) + logger.info("$cacheFile was downloaded.") } catch (e: Exception) { - // now output is corrupted, delete it - cacheFile.delete() - throw e + logger.error("Failed to download $this", e) } } } \ No newline at end of file diff --git a/main/src/task/ResolveMods.kt b/main/src/task/ResolveMods.kt index 5ea208c..3f1450a 100644 --- a/main/src/task/ResolveMods.kt +++ b/main/src/task/ResolveMods.kt @@ -1,7 +1,6 @@ package io.github.liplum.mindustry import io.github.liplum.dsl.* -import io.github.liplum.dsl.copyTo import io.github.liplum.dsl.listProp import org.gradle.api.DefaultTask import org.gradle.api.GradleException @@ -9,7 +8,6 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputFiles import org.gradle.api.tasks.TaskAction import java.io.File -import kotlin.math.absoluteValue internal const val infoX = "info.json" @@ -47,43 +45,33 @@ open class ResolveMods : DefaultTask() { if (!cacheFile.exists()) { when (mod) { is LocalMod -> if (!cacheFile.isFile) throw GradleException("Local mod $cacheFile not found.") - is IGitHubMod -> mod.downloadOrUpdate(cacheFile) - is UrlMod -> mod.download(cacheFile) + is IGitHubMod -> { + if (!mod.isUpdateToDate()) { + logger.lifecycle("Updating $this -> $cacheFile...") + try { + mod.resolveDownloadSrc().openStream().copyToTmpAndMove(cacheFile) + logger.info("$cacheFile was downloaded.") + } catch (e: Exception) { + logger.error("Failed to update $this", e) + } + } + } + + is IDownloadableMod -> { + logger.lifecycle("Downloading $this -> $cacheFile...") + try { + mod.resolveDownloadSrc().openStream().copyToTmpAndMove(cacheFile) + logger.info("$cacheFile was downloaded.") + } catch (e: Exception) { + logger.error("Failed to download $this", e) + } + } + else -> {} } } createSymbolicLinkOrCopyCache(link = mod.resolveOutputFile(), target = cacheFile) } } - - fun IGitHubMod.downloadOrUpdate(cacheFile: File) { - if (!this.isUpdateToDate()) { - val temp = File.createTempFile(this.fileName4Local, null) - try { - this.resolveDownloadSrc().openStream().use { - it.copyTo(temp) - } - } catch (e: Exception) { - logger.warn("Failed to update $this", e) - } - temp.copyTo(cacheFile) - } - } - - fun IGitHubMod.isUpdateToDate(): Boolean { - val cacheFile = this.resolveCacheFile() - val infoFi = File("$cacheFile.$infoX") - if (!cacheFile.exists()) { - if (infoFi.exists()) infoFi.delete() - return false - } - val meta = tryReadGitHubModInfo(infoFi) - val curTime = System.currentTimeMillis() - // TODO: Configurable out-of-date time - return curTime - meta.lastUpdateTimestamp < R.outOfDataTime.absoluteValue - } - - fun UrlMod.download(cacheFile: File) { - url.copyTo(cacheFile) - } } +