Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions src/main/kotlin/io/github/sculk_cli/commands/AddByUrl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,18 @@ class AddByUrl :
}

val existingManifest = ctx.pack.getManifest("$dir/$transformedSlug.sculk.json")
val hashes = FileManifestHashes(
sha1 = contents.digestSha1(),
sha512 = contents.digestSha512(),
murmur2 = contents.digestMurmur2()
)
val fileManifest = if (existingManifest != null) {
if (existingManifest.hashes.sha1 != contents.digestSha1() || existingManifest.hashes.sha512 != contents.digestSha512()) {
error("File hashes do not match for $filename")
}

existingManifest.sources.url = FileManifestUrlSource(url.toString())
existingManifest.sources.url = FileManifestUrlSource(url.toString(), hashes)
existingManifest
} else {
FileManifest(
filename = filename, side = side, hashes = FileManifestHashes(
sha1 = contents.digestSha1(),
sha512 = contents.digestSha512(),
murmur2 = contents.digestMurmur2()
), fileSize = contents.size, sources = FileManifestSources(
curseforge = null, modrinth = null, url = FileManifestUrlSource(url.toString())
filename = filename, side = side, fileSize = contents.size, sources = FileManifestSources(
curseforge = null, modrinth = null, url = FileManifestUrlSource(url.toString(), hashes)
)
)
}
Expand Down
13 changes: 11 additions & 2 deletions src/main/kotlin/io/github/sculk_cli/commands/ExportModrinth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import io.github.sculk_cli.util.toModrinthEnvClientSupport
import io.github.sculk_cli.util.toModrinthEnvServerSupport
import io.github.sculk_cli.modrinth.*
import io.github.sculk_cli.modrinth.models.ModrinthVersionFileHashes
import io.github.sculk_cli.pack.FileManifestHashes
import java.io.File
import java.nio.file.Paths

Expand Down Expand Up @@ -42,13 +43,16 @@ class ExportModrinth :

for ((path, fileManifest) in ctx.pack.getManifests().entries) {
val downloadUrls = mutableListOf<String>()
var hashes: FileManifestHashes? = null

if (fileManifest.sources.modrinth != null) {
downloadUrls += fileManifest.sources.modrinth!!.fileUrl
hashes = fileManifest.sources.modrinth!!.hashes
}

if (fileManifest.sources.url != null) {
downloadUrls += fileManifest.sources.url!!.url
hashes = hashes ?: fileManifest.sources.url!!.hashes
}

val filteredDownloadUrls = downloadUrls
Expand All @@ -61,11 +65,16 @@ class ExportModrinth :
continue
}

if (hashes == null) {
terminal.warning("File $path will not be included as it does not have hashes")
continue
}

files += ModrinthPackFile(
path = File(path).resolveSibling(fileManifest.filename).toString(),
hashes = ModrinthVersionFileHashes(
sha1 = fileManifest.hashes.sha1,
sha512 = fileManifest.hashes.sha512
sha1 = hashes.sha1,
sha512 = hashes.sha512
),
env = ModrinthPackFileEnv(
clientSupport = fileManifest.side.toModrinthEnvClientSupport(),
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/io/github/sculk_cli/commands/ImportCurseforge.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,17 @@ class ImportCurseforge :
val fileManifest = FileManifest(
filename = cfFile.fileName,
side = cfFile.getSide().toSide(),
hashes = FileManifestHashes(
sha1 = tempFile.digestSha1(),
sha512 = tempFile.digestSha512(),
murmur2 = tempFile.digestMurmur2()
),
fileSize = tempFile.size,
sources = FileManifestSources(
curseforge = FileManifestCurseforgeSource(
projectId = mod.id,
fileId = file.fileId,
fileUrl = cfFile.downloadUrl!!
fileUrl = cfFile.downloadUrl!!,
hashes = FileManifestHashes(
sha1 = tempFile.digestSha1(),
sha512 = tempFile.digestSha512(),
murmur2 = tempFile.digestMurmur2()
),
),
modrinth = null,
url = null
Expand Down
32 changes: 19 additions & 13 deletions src/main/kotlin/io/github/sculk_cli/commands/ImportModrinth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import io.github.sculk_cli.util.toModLoader
import io.github.sculk_cli.util.toSide
import io.github.sculk_cli.modrinth.getLoaderVersionPair
import io.github.sculk_cli.modrinth.importModrinthPack
import io.github.sculk_cli.util.digestSha1
import io.github.sculk_cli.util.digestSha512
import java.io.File
import java.nio.file.Paths
import kotlin.collections.plusAssign
Expand Down Expand Up @@ -75,11 +77,6 @@ class ImportModrinth :
val fileManifest = FileManifest(
filename = File(file.path).name,
side = file.env?.toSide() ?: Side.Both,
hashes = FileManifestHashes(
sha1 = file.hashes.sha1,
sha512 = file.hashes.sha512,
murmur2 = -1, // Updated later in the loop
),
fileSize = file.fileSizeInBytes,
sources = FileManifestSources(
curseforge = null,
Expand All @@ -93,27 +90,36 @@ class ImportModrinth :
for (downloadUrl in file.downloadUrls) {
progress.advance(1)
progress.update { context = downloadUrl }

if (fileManifest.hashes.murmur2 == -1L) {
val file = downloadFileTemp(parseUrl(downloadUrl))
fileManifest.hashes.murmur2 = file.readBytes().digestMurmur2()
}
val file = downloadFileTemp(parseUrl(downloadUrl))
val bytes = file.readBytes()
val sha1 = bytes.digestSha1()
val sha512 = bytes.digestSha512()
val murmur2 = bytes.digestMurmur2()

if (parseUrl(downloadUrl).host == "cdn.modrinth.com") {
val version = ctx.modrinth.getVersionFromHash(file.hashes.sha1)
val version = ctx.modrinth.getVersionFromHash(sha1)
?: run {
terminal.warning("File ${file.path} includes a Modrinth file that does not seem to exist")
null
} ?: continue

fileManifest.sources.modrinth = FileManifestModrinthSource(
projectId = version.projectId,
fileUrl = downloadUrl
fileUrl = downloadUrl,
hashes = FileManifestHashes(
sha1 = sha1,
sha512 = sha512,
murmur2 = murmur2,
),
)

slug = ctx.modrinth.getProject(version.projectId)!!.slug
} else if (fileManifest.sources.url == null) {
fileManifest.sources.url = FileManifestUrlSource(downloadUrl)
fileManifest.sources.url = FileManifestUrlSource(downloadUrl, FileManifestHashes(
sha1 = sha1,
sha512 = sha512,
murmur2 = murmur2,
))
} else {
terminal.warning("File ${file.path} has multiple valid URL sources; only the first will be included")
}
Expand Down
26 changes: 18 additions & 8 deletions src/main/kotlin/io/github/sculk_cli/commands/Install.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,6 @@ class Install :

installedItems += fileFile.path.toString()

if (fileFile.exists()) {
if (fileFile.readBytes().digestSha512() == fileManifest.hashes.sha512) {
terminal.info("Skipping ${file.path} because it's already downloaded")
return@launch
}
}

val downloadLink = if (fileManifest.sources.url != null) {
fileManifest.sources.url.url
} else if (fileManifest.sources.modrinth != null) {
Expand All @@ -119,6 +112,23 @@ class Install :
error("No valid source found for ${file.path}")
}

val hashes = if (fileManifest.sources.url != null) {
fileManifest.sources.url.hashes
} else if (fileManifest.sources.modrinth != null) {
fileManifest.sources.modrinth.hashes
} else if (fileManifest.sources.curseforge != null) {
fileManifest.sources.curseforge.hashes
} else {
error("No valid hashes found for ${file.path}")
}

if (fileFile.exists()) {
if (fileFile.readBytes().digestSha512() == hashes.sha512) {
terminal.info("Skipping ${file.path} because it's already downloaded")
return@launch
}
}

fileFile.parentFile.mkdirs()
val request = ctx.client.get(downloadLink) {
timeout {
Expand All @@ -128,7 +138,7 @@ class Install :
}
fileFile.writeBytes(request.readRawBytes())

if (fileFile.readBytes().digestSha512() != fileManifest.hashes.sha512) {
if (fileFile.readBytes().digestSha512() != hashes.sha512) {
error("Downloaded file for ${file.path} was corrupted or hash was incorrect")
}

Expand Down
14 changes: 12 additions & 2 deletions src/main/kotlin/io/github/sculk_cli/commands/Link.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,19 @@ class Link : CliktCommand(
ctx: Context,
manifest: Map.Entry<String, FileManifest>
) {
val hashes = if (manifest.value.sources.url != null) {
manifest.value.sources.url!!.hashes
} else if (manifest.value.sources.modrinth != null) {
manifest.value.sources.modrinth!!.hashes
} else if (manifest.value.sources.curseforge != null) {
manifest.value.sources.curseforge!!.hashes
} else {
error("No valid hashes found for ${manifest.key}")
}

when (target) {
Target.Curseforge -> {
val matches = ctx.curseforge.getFingerprintMatches(manifest.value.hashes.murmur2)
val matches = ctx.curseforge.getFingerprintMatches(hashes.murmur2)

if (matches.isEmpty()) {
terminal.info("No match found for ${manifest.key}")
Expand Down Expand Up @@ -85,7 +95,7 @@ class Link : CliktCommand(

Target.Modrinth -> {
val version = ctx.modrinth.getVersionFromHash(
manifest.value.hashes.sha512,
hashes.sha512,
ModrinthHashAlgorithm.SHA512
)

Expand Down
23 changes: 14 additions & 9 deletions src/main/kotlin/io/github/sculk_cli/pack/InMemory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ data class PackManifestFile(
data class FileManifest(
var filename: String,
var side: Side,
var hashes: FileManifestHashes,
var fileSize: Int,
var sources: FileManifestSources
)
Expand All @@ -189,15 +188,15 @@ data class FileManifestSources(
)

data class FileManifestCurseforgeSource(
var projectId: Int, var fileUrl: String, var fileId: Int,
var projectId: Int, var fileUrl: String, var fileId: Int, var hashes: FileManifestHashes,
)

data class FileManifestModrinthSource(
var projectId: String, var fileUrl: String,
var projectId: String, var fileUrl: String, var hashes: FileManifestHashes,
)

data class FileManifestUrlSource(
var url: String
var url: String, var hashes: FileManifestHashes,
)

fun PackManifest.toSerial(): SerialPackManifest {
Expand Down Expand Up @@ -232,31 +231,37 @@ fun FileManifest.toSerial(): SerialFileManifest {
return SerialFileManifest(
filename = filename,
side = side,
hashes = SerialFileManifestHashes(
sha1 = hashes.sha1,
sha512 = hashes.sha512,
murmur2 = hashes.murmur2,
),
fileSize = fileSize,
sources = SerialFileManifestSources(
curseforge = sources.curseforge?.let {
SerialFileManifestCurseforgeSource(
projectId = it.projectId,
fileUrl = it.fileUrl,
fileId = it.fileId,
hashes = it.hashes.toSerial(),
)
},
modrinth = sources.modrinth?.let {
SerialFileManifestModrinthSource(
projectId = it.projectId,
fileUrl = it.fileUrl,
hashes = it.hashes.toSerial(),
)
},
url = sources.url?.let {
SerialFileManifestUrlSource(
url = it.url,
hashes = it.hashes.toSerial(),
)
},
)
)
}

fun FileManifestHashes.toSerial(): SerialFileManifestHashes {
return SerialFileManifestHashes(
sha1 = sha1,
sha512 = sha512,
murmur2 = murmur2,
)
}
24 changes: 15 additions & 9 deletions src/main/kotlin/io/github/sculk_cli/pack/Serial.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ data class SerialPackManifestFile(
data class SerialFileManifest(
val filename: String,
val side: Side,
val hashes: SerialFileManifestHashes,
val fileSize: Int,
val sources: SerialFileManifestSources
)
Expand All @@ -55,17 +54,17 @@ data class SerialFileManifestSources(

@Serializable
data class SerialFileManifestCurseforgeSource(
val projectId: Int, val fileUrl: String, val fileId: Int,
val projectId: Int, val fileUrl: String, val fileId: Int, val hashes: SerialFileManifestHashes,
)

@Serializable
data class SerialFileManifestModrinthSource(
val projectId: String, val fileUrl: String,
val projectId: String, val fileUrl: String, val hashes: SerialFileManifestHashes,
)

@Serializable
data class SerialFileManifestUrlSource(
var url: String
var url: String, val hashes: SerialFileManifestHashes,
)

fun SerialPackManifest.load(): PackManifest {
Expand Down Expand Up @@ -98,29 +97,36 @@ fun SerialPackManifest.load(): PackManifest {

fun SerialFileManifest.load(): FileManifest {
return FileManifest(
filename = filename, side = side, hashes = FileManifestHashes(
sha1 = hashes.sha1,
sha512 = hashes.sha512,
murmur2 = hashes.murmur2,
), fileSize = fileSize, sources = FileManifestSources(
filename = filename, side = side, fileSize = fileSize, sources = FileManifestSources(
curseforge = sources.curseforge?.let {
FileManifestCurseforgeSource(
projectId = it.projectId,
fileUrl = it.fileUrl,
fileId = it.fileId,
hashes = it.hashes.load(),
)
},
modrinth = sources.modrinth?.let {
FileManifestModrinthSource(
projectId = it.projectId,
fileUrl = it.fileUrl,
hashes = it.hashes.load(),
)
},
url = sources.url?.let {
FileManifestUrlSource(
url = it.url,
hashes = it.hashes.load(),
)
},
)
)
}

fun SerialFileManifestHashes.load(): FileManifestHashes {
return FileManifestHashes(
sha1 = sha1,
sha512 = sha512,
murmur2 = murmur2,
)
}
Loading
Loading