4
0
Fork 0
mirror of https://github.com/Anvilcraft/modpacktools synced 2024-06-11 06:59:28 +02:00

BuildTechnic.kt should work now

improved FileDownloader.kt
This commit is contained in:
LordMZTE 2020-08-15 16:59:52 +02:00
parent 069b2896e6
commit db1f46d728
5 changed files with 112 additions and 114 deletions

View file

@ -20,9 +20,7 @@ constructor(
ArgumentParsers.newFor(displayName) ArgumentParsers.newFor(displayName)
.build() .build()
.description(helpMessage) .description(helpMessage)
.apply { .apply {addArgs()}
addArgs()
}
} }
/** /**
@ -31,5 +29,5 @@ constructor(
* *
* @receiver the parser to add the args to * @receiver the parser to add the args to
*/ */
open fun ArgumentParser.addArgs() {} protected open fun ArgumentParser.addArgs() {}
} }

View file

@ -8,6 +8,7 @@ import ley.anvil.modpacktools.command.AbstractCommand
import ley.anvil.modpacktools.command.CommandReturn import ley.anvil.modpacktools.command.CommandReturn
import ley.anvil.modpacktools.command.CommandReturn.Companion.fail import ley.anvil.modpacktools.command.CommandReturn.Companion.fail
import ley.anvil.modpacktools.command.LoadCommand import ley.anvil.modpacktools.command.LoadCommand
import ley.anvil.modpacktools.util.FileToDownload
import ley.anvil.modpacktools.util.addonscript.installFile import ley.anvil.modpacktools.util.addonscript.installFile
import ley.anvil.modpacktools.util.downloadFiles import ley.anvil.modpacktools.util.downloadFiles
import ley.anvil.modpacktools.util.fPrintln import ley.anvil.modpacktools.util.fPrintln
@ -16,7 +17,6 @@ import net.sourceforge.argparse4j.inf.Namespace
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.net.URL
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
@LoadCommand @LoadCommand
@ -37,39 +37,51 @@ object BuildTechnic : AbstractCommand("BuildTechnic") {
} }
val fileList = mutableListOf<FileOrLink>() val fileList = mutableListOf<FileOrLink>()
val toDownload = mutableMapOf<URL, Pair<String, File>>() //Map of File to Installer
MPJH.asWrapper!!.defaultVersion.getRelations {"client" in it.options}.forEach { val toDownload = mutableMapOf<FileToDownload, String>()
if(it.hasFile())
fileList.add(it.file.get()) //RELATIONS
} fileList.addAll(
MPJH.asWrapper!!.defaultVersion.getRelations {"client" in it.options}.filter {it.hasFile()}
.map {it.file.get()}
)
//FILES
fileList.addAll(MPJH.asWrapper!!.defaultVersion.getFiles {true}.map {it.get()})
//FORGE
@Suppress("DEPRECATION") //no idea why this is deprecated. Too Bad!
val forge = MPJH.asWrapper!!.defaultVersion.getRelations {it.id.toLowerCase() == "forge"}.first().forgeUniversal
toDownload[
FileToDownload(
//Technic wants it to be called modpack.jar
File(download, "modpack.jar"),
forge.url
)
] = "internal.dir:bin"
fileList.forEach { fileList.forEach {
when { when {
it.isFile -> { !it.isURL -> {
if(!it.isASDirSet) if(!it.isASDirSet)
it.setASDir(srcDir) it.setASDir(srcDir)
if(it.file.exists()) if(it.file.exists())
installFile(it.installer, it.file, tmp).printf() installFile(it.installer, it.file, tmp).printf()
} }
it.isURL -> toDownload[it.url] = it.installer to download it.isURL -> toDownload[FileToDownload(download, it.url, true)] = it.installer
else -> return fail("${it.link} is neither a file nor an URL") else -> return fail("${it.link} is neither a file nor an URL")
} }
} }
downloadFiles( downloadFiles(toDownload.keys.toList()) {
toDownload.mapValues {it.value.second}, if(it.downloadedFile != null) {
{ fPrintln("${it.responseCode} ${it.responseMessage} ${it.file.url} ${it.downloadedFile}", TERMC.brightBlue)
if(it.exception == null) { //Use map of file to installer to get installer for given file
fPrintln("downloaded file ${it.file}", TERMC.brightBlue) installFile(toDownload[it.file]!!, it.downloadedFile, tmp).printf()
installFile(toDownload[it.url]!!.first, it.file, tmp).printf() } else if(it.exception != null) {
} else { fPrintln("ERROR DOWNLOADING ${it.file.url}")
fPrintln("ERROR DOWNLOADING ${it.url}") it.exception.printStackTrace()
it.exception.printStackTrace() }
} }
},
resolveFileName = true
)
fPrintln("Making Zip", TERMC.brightGreen) fPrintln("Making Zip", TERMC.brightGreen)
ZipOutputStream(FileOutputStream("build/${MPJH.asWrapper!!.json.id}-${MPJH.asWrapper!!.defaultVersion.versionName}-technic.zip")) ZipOutputStream(FileOutputStream("build/${MPJH.asWrapper!!.json.id}-${MPJH.asWrapper!!.defaultVersion.versionName}-technic.zip"))

View file

@ -8,6 +8,7 @@ import ley.anvil.modpacktools.command.CommandReturn
import ley.anvil.modpacktools.command.CommandReturn.Companion.fail import ley.anvil.modpacktools.command.CommandReturn.Companion.fail
import ley.anvil.modpacktools.command.CommandReturn.Companion.success import ley.anvil.modpacktools.command.CommandReturn.Companion.success
import ley.anvil.modpacktools.command.LoadCommand import ley.anvil.modpacktools.command.LoadCommand
import ley.anvil.modpacktools.util.FileToDownload
import ley.anvil.modpacktools.util.addonscript.installFile import ley.anvil.modpacktools.util.addonscript.installFile
import ley.anvil.modpacktools.util.arg import ley.anvil.modpacktools.util.arg
import ley.anvil.modpacktools.util.downloadFiles import ley.anvil.modpacktools.util.downloadFiles
@ -18,11 +19,9 @@ import net.sourceforge.argparse4j.impl.Arguments.storeTrue
import net.sourceforge.argparse4j.inf.ArgumentParser import net.sourceforge.argparse4j.inf.ArgumentParser
import net.sourceforge.argparse4j.inf.Namespace import net.sourceforge.argparse4j.inf.Namespace
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.apache.commons.io.FilenameUtils
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.FileWriter import java.io.FileWriter
import java.net.URL
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
@LoadCommand @LoadCommand
@ -45,7 +44,7 @@ object BuildTwitch : AbstractCommand("BuildTwitch") {
val ml = convertAStoManifest(wr) {args.getBoolean("all") || "required" in it.options} val ml = convertAStoManifest(wr) {args.getBoolean("all") || "required" in it.options}
val archiveName = "${wr.json.id}-${wr.defaultVersion.versionName}-twitch" val archiveName = "${wr.json.id}-${wr.defaultVersion.versionName}-twitch"
val dir = File("./build") val dir = File("./build")
val toDownload = mutableMapOf<URL, Pair<File, String>>() val toDownload = mutableMapOf<FileToDownload, String>()
val srcDir by lazy {File(CONFIG.config.pathOrException<String>("Locations/src"))} val srcDir by lazy {File(CONFIG.config.pathOrException<String>("Locations/src"))}
val overrides by lazy {File(tmp, "overrides")} val overrides by lazy {File(tmp, "overrides")}
dir.mkdirs() dir.mkdirs()
@ -67,21 +66,23 @@ object BuildTwitch : AbstractCommand("BuildTwitch") {
installFile(uf.value, file, overrides).printf() installFile(uf.value, file, overrides).printf()
} }
} else if(uf.key.isURL) { } else if(uf.key.isURL) {
val filePath = URL(uf.key.link) toDownload[FileToDownload(downloadDir, uf.key.url, true)] = uf.value
toDownload[filePath] = Pair(File(downloadDir, FilenameUtils.getName(filePath.toString())), uf.value)
} else { } else {
return fail("{$uf.key.link} is neither a file nor an URL") return fail("{$uf.key.link} is neither a file nor an URL")
} }
} }
downloadFiles( downloadFiles(
toDownload.mapValues {it.value.first}, toDownload.keys.toList()
{ ) {
fPrintln("downloaded file ${it.file}", TERMC.brightBlue) if(it.downloadedFile != null) {
installFile(toDownload[it.url]!!.second, it.file, overrides).printf() fPrintln("downloaded file ${it.file.url}", TERMC.brightBlue)
}, installFile(toDownload[it.file]!!, it.downloadedFile, overrides).printf()
false } else if(it.exception != null) {
) fPrintln("ERROR DOWNLOADING ${it.file}")
it.exception.printStackTrace()
}
}
fPrintln("Creating zip", TERMC.brightGreen) fPrintln("Creating zip", TERMC.brightGreen)
val zip = ZipOutputStream(FileOutputStream("${dir.path}/$archiveName.zip")) val zip = ZipOutputStream(FileOutputStream("${dir.path}/$archiveName.zip"))

View file

@ -6,7 +6,7 @@ import ley.anvil.modpacktools.command.AbstractCommand
import ley.anvil.modpacktools.command.CommandReturn import ley.anvil.modpacktools.command.CommandReturn
import ley.anvil.modpacktools.command.CommandReturn.Companion.success import ley.anvil.modpacktools.command.CommandReturn.Companion.success
import ley.anvil.modpacktools.command.LoadCommand import ley.anvil.modpacktools.command.LoadCommand
import ley.anvil.modpacktools.util.DownloadFileTask import ley.anvil.modpacktools.util.FileToDownload
import ley.anvil.modpacktools.util.arg import ley.anvil.modpacktools.util.arg
import ley.anvil.modpacktools.util.downloadFiles import ley.anvil.modpacktools.util.downloadFiles
import ley.anvil.modpacktools.util.fPrintln import ley.anvil.modpacktools.util.fPrintln
@ -15,8 +15,6 @@ import net.sourceforge.argparse4j.impl.type.FileArgumentType
import net.sourceforge.argparse4j.inf.ArgumentParser import net.sourceforge.argparse4j.inf.ArgumentParser
import net.sourceforge.argparse4j.inf.Namespace import net.sourceforge.argparse4j.inf.Namespace
import java.io.File import java.io.File
import java.net.URL
import java.util.stream.Collectors.toMap
@LoadCommand @LoadCommand
object DownloadMods : AbstractCommand("DownloadMods") { object DownloadMods : AbstractCommand("DownloadMods") {
@ -42,46 +40,36 @@ object DownloadMods : AbstractCommand("DownloadMods") {
override fun execute(args: Namespace): CommandReturn { override fun execute(args: Namespace): CommandReturn {
val json = MPJH.asWrapper val json = MPJH.asWrapper
val fileList = mutableListOf<FileOrLink>() val fileList = mutableListOf<FileOrLink>()
for( for(rel in json!!.defaultVersion!!.getRelations {"client" in it.options && (args.getBoolean("all") || it.type == "mod")})
rel in json!!.defaultVersion!!.getRelations {
"client" in it.options && (args.getBoolean("all") || it.type == "mod")
}
)
if(rel.hasFile()) if(rel.hasFile())
fileList.add(rel.file.get()) fileList.add(rel.file.get())
downloadFiles( downloadFiles(
fileList.stream() fileList
.filter {it.isURL} .filter {it.isURL}
.filter { .filter {
val (installer, dir) = it.installer.split(':') val (installer, dir) = it.installer.split(':')
installer == "internal.dir" && (args.getBoolean("all") || dir == "mods") installer == "internal.dir" && (args.getBoolean("all") || dir == "mods")
} }
.collect( .map {
toMap<FileOrLink, URL, File>( FileToDownload(
{URL(it.link)}, if(args.getBoolean("all"))
{ File(args.get<File>("dir"), it.installer.split(':')[1])
val dir = it.installer.split(':').last() else
args.get<File>("dir"),
if(args.getBoolean("all")) it.url,
File(args.get<File>("dir"), dir) true,
else !args.getBoolean("force")
args.get<File>("dir")
},
{_: File, f: File -> f}
) )
),
{r: DownloadFileTask.Return ->
println("${r.responseCode} ${r.responseMessage} ${r.url} ${r.file}")
if(r.exception != null) {
fPrintln("ERROR DOWNLOADING ${r.url}")
r.exception.printStackTrace()
} }
}, ) {
!args.getBoolean("force"), println("${it.responseCode} ${it.responseMessage} ${it.file.url} ${it.downloadedFile}")
true if(it.exception != null) {
) fPrintln("ERROR DOWNLOADING ${it.file.url}")
it.exception.printStackTrace()
}
}
return success() return success()
} }
} }

View file

@ -11,57 +11,58 @@ import java.io.IOException
import java.net.URL import java.net.URL
import java.nio.file.Paths import java.nio.file.Paths
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.stream.Collectors
private var latch: CountDownLatch? = null
/** /**
* Downloads all supplied urls to the given files * Downloads all supplied urls to the given files
* *
* @param files the files to download and the file to save them to * @param files the files to download
* @param callback the callback which will be called once a download finishes * @param callback the callback which will be called once a download finishes
* @param skipExistingFiles if true, files that already exist will not be downloaded
* @param resolveFileName if true, the file name will be resolved using the URL (target file will now serve as directory)
*/ */
@JvmOverloads
fun downloadFiles( fun downloadFiles(
files: Map<URL, File>, files: List<FileToDownload>,
callback: (DownloadFileTask.Return) -> Unit, callback: (DownloadFileTask.Return) -> Unit
skipExistingFiles: Boolean = false,
resolveFileName: Boolean = false
) { ) {
val tasks = files.entries.stream() val latch = CountDownLatch(files.size)
//remove if it should be skipped files.forEach {
.filter {!skipExistingFiles || !it.value.exists()} val req = DownloadFileTask(callback, latch, it)
.collect(Collectors.toList())
latch = CountDownLatch(tasks.size)
tasks.forEach {
val req = DownloadFileTask(it.key, it.value, callback, latch!!, resolveFileName)
HTTP_CLIENT.newCall(req.request).enqueue(req) HTTP_CLIENT.newCall(req.request).enqueue(req)
} }
latch!!.await() latch.await()
} }
/**
* A file that should be downloaded
*
* @param fileOrDir the file to save to
* @param url the url to download from
* @param shouldResolveFileName if true, the fileOrDir will be treated as directory and the file name will be resolved from the URL
*/
data class FileToDownload(
val fileOrDir: File,
val url: URL,
val shouldResolveFileName: Boolean = false,
val shouldSkipIfExists: Boolean = false
)
open class DownloadFileTask( open class DownloadFileTask(
protected open val url: URL,
protected open val file: File,
protected open val callback: (Return) -> Unit, protected open val callback: (Return) -> Unit,
protected open val latch: CountDownLatch, protected open val latch: CountDownLatch,
protected open val resolveFileName: Boolean protected open val file: FileToDownload
) : Callback { ) : Callback {
open val request = Request.Builder() open val request = Request.Builder()
.get() .get()
.url(url) .url(file.url)
.build() .build()
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {
callback( callback(
Return( Return(
url,
file, file,
null, null,
null, null,
e null,
e,
true
) )
) )
latch.countDown() latch.countDown()
@ -69,31 +70,28 @@ open class DownloadFileTask(
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
callback( callback(
try { run {
var wasSkipped = true
val outFile = val outFile =
if(resolveFileName) if(file.shouldResolveFileName)
file mergeTo Paths.get(response.request.url.toUri().path).fileName.toFile() file.fileOrDir mergeTo Paths.get(response.request.url.toUri().path).fileName.toFile()
else else
file file.fileOrDir
val stream = response.body?.byteStream() if(!file.shouldSkipIfExists || !outFile.exists()) {
FileUtils.copyInputStreamToFile(stream, outFile) response.body?.byteStream().use {
stream!!.close() FileUtils.copyInputStreamToFile(it, outFile)
}
wasSkipped = false
}
Return( Return(
url, file,
outFile, outFile,
response.code, response.code,
response.message, response.message,
null null,
) wasSkipped
} catch(e: NullPointerException) {
Return(
url,
file,
response.code,
response.message,
e
) )
} }
) )
@ -101,10 +99,11 @@ open class DownloadFileTask(
} }
data class Return( data class Return(
val url: URL, val file: FileToDownload,
val file: File, val downloadedFile: File?,
val responseCode: Int?, val responseCode: Int?,
val responseMessage: String?, val responseMessage: String?,
val exception: Exception? val exception: Exception?,
val wasSkipped: Boolean
) )
} }