Skip to content

Commit

Permalink
fix(gui): update check fixed to match current artifact naming
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Oct 17, 2024
1 parent 2498018 commit a43b328
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 210 deletions.
1 change: 1 addition & 0 deletions jadx-gui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {

implementation("org.jcommander:jcommander:2.0")
implementation("ch.qos.logback:logback-classic:1.5.11")
implementation("io.github.oshai:kotlin-logging-jvm:7.0.0")

implementation("com.fifesoft:rsyntaxtextarea:3.4.1")
implementation(files("libs/jfontchooser-1.0.5.jar"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,10 @@ private SettingsGroup makeOtherGroup() {
group.addRow(NLS.str("preferences.lineNumbersMode"), lineNumbersMode);
group.addRow(NLS.str("preferences.jumpOnDoubleClick"), jumpOnDoubleClick);
group.addRow(NLS.str("preferences.useAlternativeFileDialog"), useAltFileDialog);
group.addRow(NLS.str("preferences.check_for_updates"), update);
group.addRow(NLS.str("preferences.cfg"), cfg);
group.addRow(NLS.str("preferences.raw_cfg"), rawCfg);
group.addRow(NLS.str("preferences.xposed_codegen_language"), xposedCodegenLanguage);
group.addRow(NLS.str("preferences.check_for_updates"), update);
group.addRow(NLS.str("preferences.update_channel"), updateChannel);
return group;
}
Expand Down
131 changes: 53 additions & 78 deletions jadx-gui/src/main/java/jadx/gui/update/JadxUpdate.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
package jadx.gui.update

import com.google.gson.Gson
import com.google.gson.JsonParser
import com.google.gson.annotations.SerializedName
import io.github.oshai.kotlinlogging.KotlinLogging
import jadx.api.JadxDecompiler
import jadx.core.Jadx
import jadx.gui.settings.JadxUpdateChannel
import jadx.gui.update.data.Artifact
import jadx.gui.update.data.Release
import org.jetbrains.kotlin.konan.file.use
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.InputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Date
import java.net.URI
import kotlin.reflect.KClass

data class Release(val name: String)

data class ArtifactList(val artifacts: List<Artifact>)

data class Artifact(
val name: String,
@SerializedName("workflow_run") val workflowRun: WorkflowRun,
)

data class WorkflowRun(
@SerializedName("head_branch") val branch: String,
)

interface IUpdateCallback {
fun onUpdate(r: Release)
}

object JadxUpdate {
private val LOG: Logger = LoggerFactory.getLogger(JadxUpdate::class.java)
private val log = KotlinLogging.logger {}

const val JADX_ARTIFACTS_URL = "https://nightly.link/skylot/jadx/workflows/build-artifacts/master"
const val JADX_RELEASES_URL = "https://github.com/skylot/jadx/releases"

private const val GITHUB_API_URL = "https://api.github.com/repos/skylot/jadx"
private const val GITHUB_ARTIFACTS_URL = "$GITHUB_API_URL/actions/artifacts"
private const val GITHUB_LATEST_ARTIFACTS_URL = "$GITHUB_API_URL/actions/artifacts?per_page=5&page=1"
private const val GITHUB_LATEST_RELEASE_URL = "$GITHUB_API_URL/releases/latest"

@JvmStatic
Expand All @@ -37,7 +48,7 @@ object JadxUpdate {
callback.onUpdate(release)
}
} catch (e: Exception) {
LOG.debug("Jadx update error", e)
log.warn(e) { "Jadx update error" }
}
}.apply {
name = "Jadx update thread"
Expand All @@ -48,89 +59,53 @@ object JadxUpdate {

private fun checkForNewRelease(updateChannel: JadxUpdateChannel): Release? {
if (Jadx.isDevVersion()) {
LOG.debug("Ignore check for update: development version")
log.debug { "Ignore check for update: development version" }
return null
}

LOG.info("Checking for updates... Update channel: {}, current version: {}", updateChannel, JadxDecompiler.getVersion())

log.info {
"Checking for updates... Update channel: $updateChannel, current version: ${JadxDecompiler.getVersion()}"
}
return when (updateChannel) {
JadxUpdateChannel.STABLE -> checkForNewStableRelease()
JadxUpdateChannel.UNSTABLE -> checkForNewUnstableRelease()
}
}

private fun checkForNewStableRelease(): Release? {
val latestRelease = get(GITHUB_LATEST_RELEASE_URL)?.let { inputStream ->
InputStreamReader(inputStream).use {
Gson().fromJson(it, Release::class.java)
}
} ?: return null

val currentVersion = JadxDecompiler.getVersion()

if (currentVersion.equals(latestRelease.name, ignoreCase = true)) return null
if (currentVersion.startsWith("r")) {
// current version is 'unstable', but update channel set to 'stable'
log.info { "Skip update check: can't compare unstable and stable versions" }
return null
}
val latestRelease = getAndParse(GITHUB_LATEST_RELEASE_URL, Release::class) ?: return null
if (VersionComparator.checkAndCompare(currentVersion, latestRelease.name) >= 0) return null

LOG.info("Found new jadx version: {}", latestRelease)

log.info { "Found new jadx version: ${latestRelease.name}" }
return latestRelease
}

private fun checkForNewUnstableRelease(): Release? {
val artifacts = getArtifacts() ?: return null

val currentVersion = JadxDecompiler.getVersion()
val currentArtifactName = "jadx-$currentVersion"

var newestArtifact: Artifact? = null
var currentArtifact: Artifact? = null

for (artifact in artifacts) {
if (newestArtifact == null && artifact.name.startsWith("jadx-") && !artifact.name.startsWith("jadx-gui-")) {
newestArtifact = artifact
}
if (currentArtifact == null && artifact.name == currentArtifactName) {
currentArtifact = artifact
}
if (newestArtifact != null && currentArtifact != null) break
}

LOG.debug("Current artifact: {}, newest artifact: {}", currentArtifact, newestArtifact)

return if (currentArtifact != null && newestArtifact != null && newestArtifact.createdAt > currentArtifact.createdAt) {
newestArtifact.let { Release().apply { name = it.name } }
} else {
null
}
val artifacts = getAndParse(GITHUB_LATEST_ARTIFACTS_URL, ArtifactList::class)
?.artifacts
?.filter { it.workflowRun.branch == "master" }
?: return null
if (artifacts.isEmpty()) return null

val latestVersion = artifacts[0].name.removePrefix("jadx-gui-").removePrefix("jadx-").substringBefore('-')
if (VersionComparator.checkAndCompare(JadxDecompiler.getVersion(), latestVersion) >= 0) return null
log.info { "Found new unstable version: $latestVersion" }
return Release(latestVersion)
}

private fun getArtifacts(): List<Artifact>? {
return get(GITHUB_ARTIFACTS_URL)?.let { inputStream ->
InputStreamReader(inputStream).use { reader ->
val response = JsonParser.parseReader(reader).asJsonObject

val count = response.get("total_count").asInt
LOG.debug("Fetched $count artifacts...")

response.getAsJsonArray("artifacts").map {
val obj = it.asJsonObject
val name = obj.get("name").asString
val sizeInBytes = obj.get("size_in_bytes").asLong
val createdAt = obj.get("created_at").asString
val parsedCreatedAt = ZonedDateTime.parse(createdAt, DateTimeFormatter.ISO_ZONED_DATE_TIME)
Artifact(name, sizeInBytes, Date.from(parsedCreatedAt.toInstant()))
}
private fun <T : Any> getAndParse(url: String, klass: KClass<T>): T? {
val con = URI(url).toURL().openConnection() as? HttpURLConnection
if (con == null || con.responseCode != 200) {
return null
}
return con.inputStream.use { stream ->
InputStreamReader(stream).use { reader ->
Gson().fromJson(reader, klass.java)
}
}
}

private fun get(url: String): InputStream? {
val con = URL(url).openConnection() as HttpURLConnection
return if (con.responseCode == 200) con.inputStream else null
}

interface IUpdateCallback {
fun onUpdate(r: Release)
}
}
18 changes: 15 additions & 3 deletions jadx-gui/src/main/java/jadx/gui/update/VersionComparator.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,23 @@ private static String clean(String str) {
return "";
}
String result = str.trim().toLowerCase();
if (result.startsWith("jadx-gui-")) {
result = result.substring(9);
}
if (result.startsWith("jadx-")) {
result = result.substring(5);
}
if (result.charAt(0) == 'v') {
result = result.substring(1);
}
// treat package version as part of version
if (result.charAt(0) == 'r') {
result = result.substring(1);
int dot = result.indexOf('.');
if (dot != -1) {
result = result.substring(0, dot);
}
}
// treat a package version as part of version
result = result.replace('-', '.');
return result;
}
Expand Down Expand Up @@ -50,8 +63,7 @@ private static int compare(String str1, String str2) {

private static boolean isZeroTail(String[] arr, int pos) {
for (int i = pos; i < arr.length; i++) {
String s = arr[i];
if (Integer.valueOf(s) != 0) {
if (Integer.parseInt(arr[i]) != 0) {
return false;
}
}
Expand Down
9 changes: 0 additions & 9 deletions jadx-gui/src/main/java/jadx/gui/update/data/Artifact.kt

This file was deleted.

75 changes: 0 additions & 75 deletions jadx-gui/src/main/java/jadx/gui/update/data/Asset.java

This file was deleted.

44 changes: 0 additions & 44 deletions jadx-gui/src/main/java/jadx/gui/update/data/Release.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public void testCompare() {
checkCompare("1.3.3.1-1", "1.3.3", 1);
}

@Test
public void testCompareUnstable() {
checkCompare("r2190.ce527ed", "jadx-r2299.742d30d", -1);
}

private static void checkCompare(String a, String b, int result) {
assertThat(VersionComparator.checkAndCompare(a, b))
.as("Compare %s and %s expect %d", a, b, result)
Expand Down

0 comments on commit a43b328

Please sign in to comment.