Point updater at Forgejo releases and Wolfskin assets
Some checks failed
review/code-gpt Request changes: version equivalence and lost positive asset-selection coverage
Some checks failed
review/code-gpt Request changes: version equivalence and lost positive asset-selection coverage
This commit is contained in:
parent
7d6f041b55
commit
0f7a23faa8
5 changed files with 238 additions and 72 deletions
|
|
@ -576,7 +576,7 @@ sealed interface AppPreference<Pref, T> {
|
|||
val UpdateUrl =
|
||||
AppStringPreference<AppPreferences>(
|
||||
title = R.string.update_url,
|
||||
defaultValue = "https://api.github.com/repos/damontecres/Wholphin/releases/latest",
|
||||
defaultValue = "https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin/releases/latest",
|
||||
getter = { it.updateUrl },
|
||||
setter = { prefs, value ->
|
||||
prefs.update { updateUrl = value }
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class UpdateChecker
|
|||
@param:StandardOkHttpClient private val okHttpClient: OkHttpClient,
|
||||
) {
|
||||
companion object {
|
||||
const val ASSET_NAME = "Wholphin"
|
||||
const val ASSET_NAME = "Wolfskin"
|
||||
const val APK_NAME = "$ASSET_NAME.apk"
|
||||
|
||||
private const val APK_MIME_TYPE = "application/vnd.android.package-archive"
|
||||
|
|
@ -65,6 +65,52 @@ class UpdateChecker
|
|||
private val NOTE_REGEX = Regex("<!-- app-note:(.+) -->")
|
||||
|
||||
val ACTIVE = BuildConfig.UPDATING_ENABLED
|
||||
|
||||
private const val RELEASES_URL = "https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin/releases?limit=50"
|
||||
|
||||
/**
|
||||
* Find the release in a Forgejo release list whose name parses to the given version
|
||||
*/
|
||||
fun findReleaseByVersion(
|
||||
releases: JsonArray,
|
||||
version: Version,
|
||||
): JsonObject? =
|
||||
releases
|
||||
.firstOrNull { release ->
|
||||
Version.tryFromString(release.jsonObject["name"]?.jsonPrimitive?.contentOrNull) == version
|
||||
}?.jsonObject
|
||||
|
||||
/**
|
||||
* Parse a single release object (Forgejo or GitHub shape) into a [Release], or null if its name is not a version
|
||||
*/
|
||||
fun parseRelease(
|
||||
json: JsonObject,
|
||||
debug: Boolean,
|
||||
supportedABIs: List<String> = Build.SUPPORTED_ABIS.toList(),
|
||||
): Release? {
|
||||
val name = json["name"]?.jsonPrimitive?.contentOrNull
|
||||
val version = Version.tryFromString(name)
|
||||
if (version == null) {
|
||||
Timber.w("Update version parsing failed. name=$name")
|
||||
return null
|
||||
}
|
||||
val publishedAt = json["published_at"]?.jsonPrimitive?.contentOrNull
|
||||
val body = json["body"]?.jsonPrimitive?.contentOrNull
|
||||
val downloadUrl =
|
||||
json["assets"]?.jsonArray?.let { assets -> getDownloadUrl(assets, debug, supportedABIs) }
|
||||
Timber.v("version=$version, downloadUrl=$downloadUrl")
|
||||
val notes =
|
||||
if (body.isNotNullOrBlank()) {
|
||||
NOTE_REGEX
|
||||
.findAll(body)
|
||||
.map { m ->
|
||||
m.groupValues[1]
|
||||
}.toList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
return Release(version, downloadUrl, publishedAt, body, notes)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -127,17 +173,29 @@ class UpdateChecker
|
|||
return Version.fromString(pkgInfo.versionName!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the release whose name parses to the given version.
|
||||
*
|
||||
* Wolfskin releases are named by `git describe` (e.g. `v1.0.9-2-g3094fc8c`) rather than tagged `vX.Y.Z`,
|
||||
* so this searches the release list instead of fetching a tag.
|
||||
*/
|
||||
suspend fun getRelease(version: Version): Release? {
|
||||
val url =
|
||||
"https://api.github.com/repos/damontecres/Wholphin/releases/tags/v${version.major}.${version.minor}.${version.patch}"
|
||||
val request =
|
||||
Request
|
||||
.Builder()
|
||||
.url(RELEASES_URL)
|
||||
.get()
|
||||
.build()
|
||||
return withContext(WholphinDispatchers.IO) {
|
||||
val request =
|
||||
Request
|
||||
.Builder()
|
||||
.url(url)
|
||||
.get()
|
||||
.build()
|
||||
getRelease(request)
|
||||
okHttpClient.newCall(request).execute().use {
|
||||
if (it.isSuccessful) {
|
||||
val releases = Json.parseToJsonElement(it.body.string()).jsonArray
|
||||
findReleaseByVersion(releases, version)?.let { json -> parseRelease(json, BuildConfig.DEBUG) }
|
||||
} else {
|
||||
Timber.w("Release lookup failed ${it.code}: ${it.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,36 +216,11 @@ class UpdateChecker
|
|||
private fun getRelease(request: Request): Release? {
|
||||
return okHttpClient.newCall(request).execute().use {
|
||||
if (it.isSuccessful) {
|
||||
val result = Json.parseToJsonElement(it.body.string())
|
||||
val name = result.jsonObject["name"]?.jsonPrimitive?.contentOrNull
|
||||
val version = Version.tryFromString(name)
|
||||
val publishedAt =
|
||||
result.jsonObject["published_at"]?.jsonPrimitive?.contentOrNull
|
||||
val body = result.jsonObject["body"]?.jsonPrimitive?.contentOrNull
|
||||
val downloadUrl =
|
||||
result.jsonObject["assets"]
|
||||
?.jsonArray
|
||||
?.let { assets -> getDownloadUrl(assets, BuildConfig.DEBUG) }
|
||||
Timber.v("version=$version, downloadUrl=$downloadUrl")
|
||||
if (version != null) {
|
||||
val notes =
|
||||
if (body.isNotNullOrBlank()) {
|
||||
NOTE_REGEX
|
||||
.findAll(body)
|
||||
.map { m ->
|
||||
m.groupValues[1]
|
||||
}.toList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
return@use Release(version, downloadUrl, publishedAt, body, notes)
|
||||
} else {
|
||||
Timber.w("Update version parsing failed. name=$name")
|
||||
}
|
||||
parseRelease(Json.parseToJsonElement(it.body.string()).jsonObject, BuildConfig.DEBUG)
|
||||
} else {
|
||||
Timber.w("Update check failed ${it.code}: ${it.message}")
|
||||
null
|
||||
}
|
||||
return@use null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue