Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ import androidx.room.Entity
import androidx.room.ForeignKey

@Entity(
primaryKeys = ["versionTagName", "name"],
primaryKeys = ["versionTagName", "repository", "name"],
foreignKeys = [ForeignKey(
entity = Version::class,
parentColumns = arrayOf("tagName"),
childColumns = arrayOf("versionTagName"),
parentColumns = arrayOf("tagName", "repository"),
childColumns = arrayOf("versionTagName", "repository"),
onDelete = ForeignKey.CASCADE
)]
)
data class Asset(

@ColumnInfo(index = true)
val versionTagName: String,
@ColumnInfo(index = true)
val repository: String,
val name: String,
val size: Long,
val downloadUrl: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package ca.cgagnier.wlednativeandroid.model
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
@Entity(
primaryKeys = ["tagName", "repository"]
)
data class Version(
@PrimaryKey
val tagName: String,
val repository: String,
val name: String,
val description: String,
val isPrerelease: Boolean,
Expand All @@ -18,6 +20,7 @@ data class Version(
fun getPreviewVersion(): Version {
return Version(
tagName = "v1.0.0",
repository = "wled/WLED",
name = "new version",
description = "this is a test version",
isPrerelease = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ data class Info(
@param:Json(name = "cn") val codeName: String? = null,
// Added in 0.15
@param:Json(name = "release") val release: String? = null,
// Added in 0.15.2
@param:Json(name = "repo") val repo: String? = null,
@param:Json(name = "name") val name: String,
@param:Json(name = "str") val syncToggleReceive: Boolean? = null,
@param:Json(name = "udpport") val udpPort: Int? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import ca.cgagnier.wlednativeandroid.model.Device
import ca.cgagnier.wlednativeandroid.model.Version
import ca.cgagnier.wlednativeandroid.repository.migrations.DbMigration7To8
import ca.cgagnier.wlednativeandroid.repository.migrations.DbMigration8To9
import ca.cgagnier.wlednativeandroid.repository.migrations.DbMigration9To10
import ca.cgagnier.wlednativeandroid.repository.migrations.DbMigration10To11

@Database(
entities = [
Device::class,
Version::class,
Asset::class,
],
version = 9,
version = 11,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 1, to = 2),
Expand All @@ -29,6 +31,8 @@ import ca.cgagnier.wlednativeandroid.repository.migrations.DbMigration8To9
AutoMigration(from = 6, to = 7),
AutoMigration(from = 7, to = 8, spec = DbMigration7To8::class),
AutoMigration(from = 8, to = 9, spec = DbMigration8To9::class),
AutoMigration(from = 9, to = 10, spec = DbMigration9To10::class),
AutoMigration(from = 10, to = 11, spec = DbMigration10To11::class),
]
)
@TypeConverters(Converters::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ interface VersionDao {
suspend fun deleteAll()

@Transaction
@Query("SELECT * FROM version WHERE isPrerelease = 0 AND tagName != '$IGNORED_TAG' ORDER BY publishedDate DESC LIMIT 1")
suspend fun getLatestStableVersionWithAssets(): VersionWithAssets?
@Query("SELECT * FROM version WHERE repository = :repository AND isPrerelease = 0 AND tagName != '$IGNORED_TAG' ORDER BY publishedDate DESC LIMIT 1")
suspend fun getLatestStableVersionWithAssets(repository: String): VersionWithAssets?

@Transaction
@Query("SELECT * FROM version WHERE tagName != '$IGNORED_TAG' ORDER BY publishedDate DESC LIMIT 1")
suspend fun getLatestBetaVersionWithAssets(): VersionWithAssets?
@Query("SELECT * FROM version WHERE repository = :repository AND tagName != '$IGNORED_TAG' ORDER BY publishedDate DESC LIMIT 1")
suspend fun getLatestBetaVersionWithAssets(repository: String): VersionWithAssets?

@Transaction
@Query("SELECT * FROM version WHERE tagName = :tagName LIMIT 1")
suspend fun getVersionByTagName(tagName: String): VersionWithAssets?
@Query("SELECT * FROM version WHERE repository = :repository AND tagName = :tagName LIMIT 1")
suspend fun getVersionByTagName(repository: String, tagName: String): VersionWithAssets?

@Transaction
@Query("SELECT * FROM version")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ class VersionWithAssetsRepository @Inject constructor(
}
}

suspend fun getLatestStableVersionWithAssets(): VersionWithAssets? {
return versionDao.getLatestStableVersionWithAssets()
suspend fun getLatestStableVersionWithAssets(repository: String): VersionWithAssets? {
return versionDao.getLatestStableVersionWithAssets(repository)
}

suspend fun getLatestBetaVersionWithAssets(): VersionWithAssets? {
return versionDao.getLatestBetaVersionWithAssets()
suspend fun getLatestBetaVersionWithAssets(repository: String): VersionWithAssets? {
return versionDao.getLatestBetaVersionWithAssets(repository)
}

suspend fun getVersionByTag(tagName: String): VersionWithAssets? {
return versionDao.getVersionByTagName(tagName)
suspend fun getVersionByTag(repository: String, tagName: String): VersionWithAssets? {
return versionDao.getVersionByTagName(repository, tagName)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ca.cgagnier.wlednativeandroid.repository.migrations

import androidx.room.DeleteTable
import androidx.room.migration.AutoMigrationSpec

/**
* Migration from 10->11 removes the old Version and Asset tables after data has been migrated
* to the new schema with repository tracking support.
*/
@DeleteTable(tableName = "Version_old")
@DeleteTable(tableName = "Asset_old")
class DbMigration10To11 : AutoMigrationSpec
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package ca.cgagnier.wlednativeandroid.repository.migrations

import android.util.Log
import androidx.room.RenameTable
import androidx.room.migration.AutoMigrationSpec
import androidx.sqlite.db.SupportSQLiteDatabase

private const val TAG = "DbMigration9To10"

/**
* Migration from 9->10 adds repository information to Version and Asset tables
* to support tracking releases from multiple WLED repositories/forks.
*
* We rename the old tables, create new ones with repository field,
* copy existing data with default repository "wled/WLED", then drop the old tables.
*/
@RenameTable(fromTableName = "Version", toTableName = "Version_old")
@RenameTable(fromTableName = "Asset", toTableName = "Asset_old")
class DbMigration9To10 : AutoMigrationSpec {
override fun onPostMigrate(db: SupportSQLiteDatabase) {
Log.i(TAG, "onPostMigrate starting - migrating Version and Asset data")

// Migrate Version table
val originalVersionCountCursor = db.query("SELECT COUNT(*) FROM Version_old")
var originalVersionCount = 0
if (originalVersionCountCursor.moveToFirst()) {
originalVersionCount = originalVersionCountCursor.getInt(0)
}
originalVersionCountCursor.close()
Log.i(TAG, "Total versions in old 'Version' table: $originalVersionCount")

// Copy data from Version_old to Version with default repository
db.execSQL(
"""
INSERT OR IGNORE INTO Version (
tagName,
repository,
name,
description,
isPrerelease,
publishedDate,
htmlUrl
)
SELECT
tagName,
'wled/WLED' AS repository,
name,
description,
isPrerelease,
publishedDate,
htmlUrl
FROM Version_old
""".trimIndent()
)

val migratedVersionCountCursor = db.query("SELECT COUNT(*) FROM Version")
var migratedVersionCount = 0
if (migratedVersionCountCursor.moveToFirst()) {
migratedVersionCount = migratedVersionCountCursor.getInt(0)
}
migratedVersionCountCursor.close()
Log.i(TAG, "Versions migrated to new table: $migratedVersionCount")

// Migrate Asset table
val originalAssetCountCursor = db.query("SELECT COUNT(*) FROM Asset_old")
var originalAssetCount = 0
if (originalAssetCountCursor.moveToFirst()) {
originalAssetCount = originalAssetCountCursor.getInt(0)
}
originalAssetCountCursor.close()
Log.i(TAG, "Total assets in old 'Asset' table: $originalAssetCount")

// Copy data from Asset_old to Asset with default repository
db.execSQL(
"""
INSERT OR IGNORE INTO Asset (
versionTagName,
repository,
name,
size,
downloadUrl,
assetId
)
SELECT
versionTagName,
'wled/WLED' AS repository,
name,
size,
downloadUrl,
assetId
FROM Asset_old
""".trimIndent()
)

val migratedAssetCountCursor = db.query("SELECT COUNT(*) FROM Asset")
var migratedAssetCount = 0
if (migratedAssetCountCursor.moveToFirst()) {
migratedAssetCount = migratedAssetCountCursor.getInt(0)
}
migratedAssetCountCursor.close()
Log.i(TAG, "Assets migrated to new table: $migratedAssetCount")

Log.i(TAG, "onPostMigrate done! Migration is complete.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import javax.inject.Singleton
@Singleton
class GithubApi @Inject constructor(private val apiEndpoints: GithubApiEndpoints) {

suspend fun getAllReleases(): Result<List<Release>> {
Log.d(TAG, "retrieving latest release")
suspend fun getAllReleases(repoOwner: String, repoName: String): Result<List<Release>> {
Log.d(TAG, "retrieving latest releases from $repoOwner/$repoName")
return try {
Result.success(apiEndpoints.getAllReleases(REPO_OWNER, REPO_NAME))
Result.success(apiEndpoints.getAllReleases(repoOwner, repoName))
} catch (e: Exception) {
Log.w(TAG, "Error retrieving releases: ${e.message}")
Log.w(TAG, "Error retrieving releases from $repoOwner/$repoName: ${e.message}")
Result.failure(e)
}
}
Expand All @@ -33,8 +33,9 @@ class GithubApi @Inject constructor(private val apiEndpoints: GithubApiEndpoints
): Flow<DownloadState> = flow {
try {
emit(DownloadState.Downloading(0))
val (repoOwner, repoName) = ca.cgagnier.wlednativeandroid.service.update.splitRepository(asset.repository)
val responseBody =
apiEndpoints.downloadReleaseBinary(REPO_OWNER, REPO_NAME, asset.assetId)
apiEndpoints.downloadReleaseBinary(repoOwner, repoName, asset.assetId)
emitAll(responseBody.saveFile(targetFile))
} catch (e: Exception) {
emit(DownloadState.Failed(e))
Expand Down Expand Up @@ -69,7 +70,5 @@ class GithubApi @Inject constructor(private val apiEndpoints: GithubApiEndpoints

companion object {
private const val TAG = "github-release"
const val REPO_OWNER = "Aircoookie"
const val REPO_NAME = "WLED"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,15 @@ class DeviceUpdateManager @Inject constructor(
.map { (info, branch, skipUpdateTag) ->
if (info == null) return@map null

val source = UpdateSourceRegistry.getSource(info) ?: return@map null
val repository = getRepositoryFromInfo(info)
Log.d(
TAG,
"Checking for software update for ${deviceWithState.device.macAddress} on ${source.githubOwner}:${source.githubRepo}"
"Checking for software update for ${deviceWithState.device.macAddress} on $repository"
)
releaseService.getNewerReleaseTag(
deviceInfo = info,
branch = branch,
ignoreVersion = skipUpdateTag,
updateSourceDefinition = source,
)
}
}
Expand Down
Loading