-
Notifications
You must be signed in to change notification settings - Fork 3
#11: Re-implementation of version tracking #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 15 commits
ab47493
6905458
126d717
9775e6a
b7f3a0d
15c90df
8886ba2
26c811e
8dc86c0
1ba11cc
838b64c
69f56ae
0e7b176
42f9cf3
15add0b
f7df0b6
8256952
fecaa2f
01524d1
7654b46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # ARK Memo: Notes App by ARK Builders | ||
|
|
||
| _Implementation in progress_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,11 @@ | ||
| package dev.arkbuilders.arkmemo.models | ||
|
|
||
| import android.os.Parcelable | ||
| import dev.arkbuilders.arklib.data.index.Resource | ||
|
|
||
| interface Note { | ||
| interface Note: Parcelable { | ||
| val title: String | ||
| val description: String | ||
| var resource: Resource? | ||
| var isForked: Boolean | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package dev.arkbuilders.arkmemo.models | ||
|
|
||
| import dev.arkbuilders.arklib.ResourceId | ||
| import dev.arkbuilders.arkmemo.repo.versions.Version | ||
|
|
||
| data class VersionsResult ( | ||
| val versions: List<Version>, | ||
| val parents: Set<ResourceId>, | ||
| val children: List<ResourceId> | ||
| ) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,213 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package dev.arkbuilders.arkmemo.repo.versions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.util.Log | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import dev.arkbuilders.arklib.ResourceId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import dev.arkbuilders.arklib.arkFolder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import kotlinx.coroutines.Dispatchers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import kotlinx.coroutines.withContext | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import dev.arkbuilders.arkmemo.models.VersionsResult | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import space.taran.arkmemo.utils.arkVersions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.nio.file.Files | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.nio.file.Path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.nio.file.attribute.FileTime | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import kotlin.io.path.writeLines | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class RootVersionStorage(private val root: Path) : VersionStorage { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private val storageFile = root.arkFolder().arkVersions() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var lastModified = FileTime.fromMillis(0L) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private val versions = mutableListOf<Version>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private val parents = mutableSetOf<ResourceId>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private val children = mutableListOf<ResourceId>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| suspend fun init() = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| withContext(Dispatchers.IO) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(storageFile)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val result = readStorage() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastModified = Files.getLastModifiedTime(storageFile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log.d( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VERSIONS_STORAGE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "file $storageFile exists," + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| " last modified at $lastModified" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versions.addAll(result.versions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parents.addAll(result.parents) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children.addAll(result.children) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else Log.d( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VERSIONS_STORAGE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "file $storageFile doesn't exists" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override fun isLatestResourceVersion(id: ResourceId): Boolean = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| childrenNotParents().contains(id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun replace(oldVersion: Version, newVersion: Version) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val replaceIndex = versions.indexOf(oldVersion) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versions[replaceIndex] = newVersion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override fun contains(id: ResourceId): Boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return parents.contains(id) || children.contains(id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override suspend fun add(version: Version) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versions.add(version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parents.add(version.parent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children.add(version.child) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| persist() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override suspend fun forget(id: ResourceId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!parents.contains(id)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val myParents = parentsTreeByChild(id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| myParents[id]?.forEach { parent -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val version = versions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .find { it.parent == parent } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versions.remove(version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parents.remove(version?.parent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| children.remove(version?.child) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (parents.contains(id) && !children.contains(id)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val version = versions.find { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it.parent == id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versions.remove(version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parents.remove(id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (parents.contains(id) && children.contains(id)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val versionIdIsChild = versions.find { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it.child == id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val versionIdIsParent = versions.find { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it.parent == id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val newVersion = Version( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versionIdIsChild?.parent!!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| versionIdIsParent?.child!! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val newVersion = Version( | |
| versionIdIsChild?.parent!!, | |
| versionIdIsParent?.child!! | |
| if (versionIdIsChild == null || versionIdIsParent == null) { | |
| Log.e(VERSIONS_STORAGE, "Inconsistent version graph state for id: $id") | |
| return | |
| } | |
| val newVersion = Version( | |
| versionIdIsChild.parent, | |
| versionIdIsParent.child | |
| ) |
🤖 Prompt for AI Agents
In app/src/main/java/dev/arkbuilders/arkmemo/repo/versions/RootVersionStorage.kt
around lines 87 to 89, the code force-unwraps versionIdIsChild and
versionIdIsParent with !! which can throw an NPE when either is null; replace
the force-unwraps with null-safe handling: check both variables before
constructing the new Version, and if either is null return a controlled failure
(e.g. throw a clear IllegalStateException/IllegalArgumentException with
contextual message or return a Result/nullable value) so you avoid crashing on
corrupted or racing version graphs and log the offending state for debugging.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Inefficient parent tree traversal algorithm
The parentsTreeByChild function has nested loops that could be optimized. The outer loop iterates through all versions, but the inner logic only needs to traverse the parent chain once.
Optimize the traversal:
override fun parentsTreeByChild(
child: ResourceId
): Map<ResourceId, List<ResourceId>> {
var localChild = child
- var parent: ResourceId?
val parents = mutableListOf<ResourceId>()
- for (version in versions) {
- parent = versions.find {
- it.child == localChild
- }?.parent
+ while (true) {
+ val parent = versions.find { it.child == localChild }?.parent ?: break
if (parent != null && children.contains(parent))
localChild = parent
- if (parent != null) parents.add(parent)
- if (!children.contains(parent))
- break
+ parents.add(parent)
+ if (!children.contains(parent)) break
}
return mapOf(child to parents)
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/src/main/java/dev/arkbuilders/arkmemo/repo/versions/RootVersionStorage.kt
around lines 101 to 118, replace the current nested-loop traversal with a
single-parent-chain walk using a precomputed map: build a Map<ResourceId,
ResourceId?> from version.child -> version.parent once, then set localChild =
child and loop while true to lookup parent = map[localChild]; if parent is null
break; add parent to parents; if children.contains(parent) then set localChild =
parent and continue, otherwise break; return mapOf(child to parents). This
eliminates repeated versions.find calls and reduces complexity to O(n) for the
map build plus O(depth) per lookup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No error handling for malformed storage file
The readStorage() function could throw various exceptions (IndexOutOfBoundsException, IllegalArgumentException) if the storage file is corrupted or malformed.
Add proper error handling:
private suspend fun readStorage(): VersionsResult =
withContext(Dispatchers.IO) {
+ try {
val lines = Files.readAllLines(storageFile)
+ if (lines.isEmpty()) {
+ Log.w(VERSIONS_STORAGE, "Storage file is empty")
+ return@withContext VersionsResult(emptyList(), emptySet(), emptyList())
+ }
val storageVersion = lines.removeAt(0)
verifyVersion(storageVersion)
val versions = lines.map {
val parts = it.split(KEY_VALUE_SEPARATOR)
+ if (parts.size != 2) {
+ Log.e(VERSIONS_STORAGE, "Malformed version line: $it")
+ throw IllegalStateException("Malformed storage file")
+ }
val parent = ResourceId.fromString(parts[0])
val child = ResourceId.fromString(parts[1])
// ... rest of the code
}
// ... rest of the code
+ } catch (e: Exception) {
+ Log.e(VERSIONS_STORAGE, "Failed to read storage", e)
+ throw e
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private suspend fun readStorage(): VersionsResult = | |
| withContext(Dispatchers.IO) { | |
| val lines = Files.readAllLines(storageFile) | |
| val storageVersion = lines.removeAt(0) | |
| verifyVersion(storageVersion) | |
| val versions = lines.map { | |
| val parts = it.split(KEY_VALUE_SEPARATOR) | |
| val parent = ResourceId.fromString(parts[0]) | |
| val child = ResourceId.fromString(parts[1]) | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| it | |
| ) | |
| Version(parent, child) | |
| } | |
| val parents = versions.map { | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| "parent: ${it.parent}" | |
| ) | |
| it.parent | |
| }.toSet() | |
| val children = versions.map { | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| "child: ${it.child}" | |
| ) | |
| it.child | |
| } | |
| return@withContext VersionsResult( | |
| versions, | |
| parents, | |
| children | |
| ) | |
| } | |
| private suspend fun readStorage(): VersionsResult = | |
| withContext(Dispatchers.IO) { | |
| try { | |
| val lines = Files.readAllLines(storageFile) | |
| if (lines.isEmpty()) { | |
| Log.w(VERSIONS_STORAGE, "Storage file is empty") | |
| return@withContext VersionsResult(emptyList(), emptySet(), emptyList()) | |
| } | |
| val storageVersion = lines.removeAt(0) | |
| verifyVersion(storageVersion) | |
| val versions = lines.map { | |
| val parts = it.split(KEY_VALUE_SEPARATOR) | |
| if (parts.size != 2) { | |
| Log.e(VERSIONS_STORAGE, "Malformed version line: $it") | |
| throw IllegalStateException("Malformed storage file") | |
| } | |
| val parent = ResourceId.fromString(parts[0]) | |
| val child = ResourceId.fromString(parts[1]) | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| it | |
| ) | |
| Version(parent, child) | |
| } | |
| val parents = versions.map { | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| "parent: ${it.parent}" | |
| ) | |
| it.parent | |
| }.toSet() | |
| val children = versions.map { | |
| Log.d( | |
| VERSIONS_STORAGE, | |
| "child: ${it.child}" | |
| ) | |
| it.child | |
| } | |
| return@withContext VersionsResult( | |
| versions, | |
| parents, | |
| children | |
| ) | |
| } catch (e: Exception) { | |
| Log.e(VERSIONS_STORAGE, "Failed to read storage", e) | |
| throw e | |
| } | |
| } |
🤖 Prompt for AI Agents
In app/src/main/java/dev/arkbuilders/arkmemo/repo/versions/RootVersionStorage.kt
around lines 140 to 174, readStorage() currently assumes the file format is
correct and will throw on malformed input; wrap the file parsing in a try/catch
that catches IO and parsing-related exceptions (IndexOutOfBoundsException,
IllegalArgumentException, any exceptions from ResourceId.fromString), validate
the file has at least one line before removeAt(0), ensure each data line splits
into exactly two parts before using parts[0]/parts[1], handle or log malformed
lines (skip them) and either return an empty/safe VersionsResult or rethrow a
clear, custom exception with context; ensure errors are logged with details so
callers can react appropriately.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package dev.arkbuilders.arkmemo.repo.versions | ||
|
|
||
| import dev.arkbuilders.arklib.ResourceId | ||
| import dev.arkbuilders.arklib.arkFolder | ||
| import dev.arkbuilders.arklib.data.storage.FileStorage | ||
| import kotlinx.coroutines.CoroutineScope | ||
| import space.taran.arkmemo.utils.arkVersions | ||
| import java.nio.file.Path | ||
|
|
||
| class RootVersionsStorage( | ||
| private val scope: CoroutineScope, | ||
| private val root: Path | ||
| ): | ||
| FileStorage<Versions>("versions", scope, root.arkFolder().arkVersions(), VersionsMonoid), | ||
| VersionsStorage { | ||
|
|
||
| override fun valueFromString(raw: String): Versions = | ||
| raw.split(",").filter { it.isNotEmpty() }.map { | ||
| ResourceId.fromString(it) | ||
| }.toSet() | ||
|
Comment on lines
+16
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential parsing errors when converting strings to ResourceIds. The Add error handling to prevent crashes: override fun valueFromString(raw: String): Versions =
- raw.split(",").filter { it.isNotEmpty() }.map {
- ResourceId.fromString(it)
- }.toSet()
+ raw.split(",").filter { it.isNotEmpty() }.mapNotNull {
+ try {
+ ResourceId.fromString(it)
+ } catch (e: Exception) {
+ Log.e("RootVersionsStorage", "Failed to parse ResourceId: $it", e)
+ null
+ }
+ }.toSet()Don't forget to add the import: import android.util.Log🤖 Prompt for AI Agents |
||
|
|
||
| override fun valueToString(value: Versions): String = value.joinToString(",") | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package dev.arkbuilders.arkmemo.repo.versions | ||
|
|
||
| import dev.arkbuilders.arklib.ResourceId | ||
|
|
||
| typealias Version2 = ResourceId | ||
|
|
||
| data class Version( | ||
| val parent: ResourceId, | ||
| val child: ResourceId | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package dev.arkbuilders.arkmemo.repo.versions | ||
|
|
||
| import dev.arkbuilders.arklib.ResourceId | ||
| import dev.arkbuilders.arklib.data.storage.Storage | ||
|
|
||
| interface VersionStorage: Storage<Version2> { | ||
|
|
||
| suspend fun add(version: Version) | ||
|
|
||
| suspend fun forget(id: ResourceId) | ||
|
|
||
| fun versions(): List<Version> | ||
|
|
||
| fun contains(id: ResourceId): Boolean | ||
|
|
||
| fun parentsTreeByChild( | ||
| child: ResourceId | ||
| ): Map<ResourceId, List<ResourceId>> | ||
|
|
||
| fun childrenNotParents(): List<ResourceId> | ||
|
|
||
| fun isLatestResourceVersion(id: ResourceId): Boolean | ||
| } | ||
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Scope VersionStorageRepo as a Singleton and make the return type explicit
Without @singleton, Hilt may create multiple instances, defeating the cache-per-root behavior and increasing I/O. Also, adding an explicit return type improves DI clarity.
Apply this diff:
Additionally, add the missing import:
🤖 Prompt for AI Agents