[index] First prototype

This commit is contained in:
Torsten Grote 2022-02-10 16:35:32 -03:00
parent 123be3af3f
commit 802deb43eb
No known key found for this signature in database
GPG Key ID: 3E5F77D92CF891FF
28 changed files with 1590 additions and 7 deletions

View File

@ -97,7 +97,7 @@ android {
getByName("androidTest").java.srcDir(file("src/androidAndroidTest/kotlin"))
}
defaultConfig {
minSdkVersion 22
minSdkVersion 21
targetSdkVersion 25
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
testInstrumentationRunnerArguments disableAnalytics: 'true'

View File

@ -4,8 +4,6 @@ android.useAndroidX=true
kotlin.code.style=official
kotlin.mpp.stability.nowarn=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
# Gradle Maven Publish Info below (https://github.com/vanniktech/gradle-maven-publish-plugin)
# These are common for all libraries in gradle submodules.

View File

@ -1,9 +1,10 @@
ktlint {
version = "0.43.2"
version = "0.45.2"
android = true
enableExperimentalRules = false
verbose = true
disabledRules = [
"wrapping",
"import-ordering",
"no-blank-line-before-rbrace",
]

View File

@ -147,6 +147,11 @@
<trusting group="com.google.guava" name="listenablefuture"/>
<trusting group="com.google.guava" name="listenablefuture" version="9999.0-empty-to-avoid-conflict-with-guava"/>
</trusted-key>
<trusted-key id="c7be5bcc9fec15518cfda882b0f3710fa64900e7">
<trusting group="com.google.auto.value"/>
<trusting group="com.google.auto.value" name="auto-value-annotations"/>
<trusting group="^com[.]google[.]auto($|([.].*))" regex="true"/>
</trusted-key>
<trusted-key id="c7be5bcc9fec15518cfda882b0f3710fa64900e7">
<trusting group="com.google.auto.value"/>
<trusting group="^com[.]google[.]auto($|([.].*))" regex="true"/>
@ -837,11 +842,21 @@
<sha256 value="a97209d75a9a85815fa8934f5a4a320de1163ffe94e2f0b328c0c98a59660690" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="androidx.test.ext" name="junit" version="1.1.3">
<artifact name="junit-1.1.3.aar">
<sha256 value="a97209d75a9a85815fa8934f5a4a320de1163ffe94e2f0b328c0c98a59660690" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="androidx.test.services" name="storage" version="1.4.0">
<artifact name="storage-1.4.0.aar">
<sha256 value="35cfbf442abb83e5876cd5deb9de02ae047459f18f831097c5caa76d626bc38a" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="androidx.test.ext" name="junit" version="1.1.3">
<artifact name="junit-1.1.3.aar">
<sha256 value="a97209d75a9a85815fa8934f5a4a320de1163ffe94e2f0b328c0c98a59660690" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="androidx.test.uiautomator" name="uiautomator" version="2.2.0">
<artifact name="uiautomator-2.2.0.aar">
<sha256 value="2838e9d961dbffefbbd229a2bd4f6f82ac4fb2462975862a9e75e9ed325a3197" origin="Generated by Gradle because artifact wasn't signed"/>
@ -973,6 +988,11 @@
<sha256 value="056b300701b7cb53e22315b29103d1cd6e7346b04b47655448675c1fa71916a5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="ch.qos.logback" name="logback-classic" version="1.2.9">
<artifact name="logback-classic-1.2.9.jar">
<sha256 value="ad745cc243805800d1ebbf5b7deba03b37c95885e6bce71335a73f7d6d0f14ee" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="ch.qos.logback" name="logback-core" version="1.2.10">
<artifact name="logback-core-1.2.10.jar">
<sha256 value="ba51a3fe56691f9dd7fe742e4a73c3ab4aaaa32202c73409ba56f18687399a08" origin="Generated by Gradle"/>
@ -983,6 +1003,11 @@
<sha256 value="fc98d2d927bd2991d5f45d0ccd9039a08d162c6d0611e2f71172deae9dbe122c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="ch.qos.logback" name="logback-core" version="1.2.9">
<artifact name="logback-core-1.2.9.jar">
<sha256 value="4a9ef7ed809b1fbc6992bf87d404087c247e7a9766e25bb84377b58ed5c9eb58" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="classworlds" name="classworlds" version="1.1-alpha-2">
<artifact name="classworlds-1.1-alpha-2.jar">
<sha256 value="2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3" origin="Generated by Gradle because artifact wasn't signed"/>
@ -1926,6 +1951,21 @@
<sha256 value="68c2a5aa6e8f345743093e52b5b9e0190ba4d5a5215c0a59b4d7d33647208cbb" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.goncalossilva" name="resources" version="0.2.1">
<artifact name="resources-library-metadata-0.2.1-all.jar">
<sha256 value="d668dfc7fa22605eda00bf23c0de7ed199c08f086f7be3267079bee4bdb772ac" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="com.goncalossilva" name="resources-jvm" version="0.2.1">
<artifact name="resources-library-jvm-0.2.1.jar">
<sha256 value="1c23299bf34a8b7ca06e63f2ba8aff9c815f0b4d925976433ff8dd837e228776" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="com.goncalossilva" name="resources-linuxX64" version="0.2.1">
<artifact name="resources-library.klib">
<sha256 value="6547c74b29706eae5ac48b6635c97a835009b5923ab6bfe418a9d6a314853501" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="com.google" name="google" version="1">
<artifact name="google-1.pom">
<sha256 value="cd6db17a11a31ede794ccbd1df0e4d9750f640234731f21cff885a9997277e81" origin="Generated by Gradle because artifact wasn't signed"/>
@ -1970,6 +2010,12 @@
<sha256 value="bd60cd7a423b00fb824c27bdd0293aaf4781be1daba6ed256311103fb4b84108" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.auto" name="auto-common" version="0.11">
<artifact name="auto-common-0.11.jar">
<pgp value="3288b8be8512d6c0ca185268c51e6cbc7ff46f0b"/>
<sha256 value="ec668cd50a3a66a5def17e6ae67423542e514181c0e9ab5b11959c0ac9c4222a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.auto" name="auto-common" version="0.8">
<artifact name="auto-common-0.8.jar">
<pgp value="92d3e6630b4b92cb2ef124994786cbe7d4906b68"/>
@ -2036,6 +2082,11 @@
<sha256 value="1c76cd462fc96e7aa96dc70ce82f0d54063d6df16db35c9c7d9cc0d1a99d3fff" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.auto.value" name="auto-value-annotations" version="1.6.3">
<artifact name="auto-value-annotations-1.6.3.jar">
<sha256 value="0e951fee8c31f60270bc46553a8586001b7b93dbb12aec06373aa99a150392c0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.auto.value" name="auto-value-annotations" version="1.7.4">
<artifact name="auto-value-annotations-1.7.4.jar">
<sha256 value="fedd59b0b4986c342f6ab2d182f2a4ee9fceb2c7e2d5bdc4dc764c92394a23d3" origin="Generated by Gradle"/>
@ -2084,6 +2135,12 @@
<sha256 value="19889dbdf1b254b2601a5ee645b8147a974644882297684c798afe5d63d78dfe" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.code.gson" name="gson" version="2.8.0">
<artifact name="gson-2.8.0.jar">
<pgp value="9e84765a7aa3e3d3d5598a408e3f0de7ae354651"/>
<sha256 value="c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.code.gson" name="gson" version="2.8.5">
<artifact name="gson-2.8.5.jar">
<pgp value="afcc4c7594d09e2182c60e0f7a01b0f236e5430f"/>
@ -2479,6 +2536,23 @@
<sha256 value="a0700d84efe7cc3103557bd0522f9443681b96ba9559c4bb7f9dc9bf35243485" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.intellij" name="annotations" version="12.0">
<artifact name="annotations-12.0.jar">
<sha256 value="f8ab13b14be080fe2f617f90e55599760e4a1b4deeea5c595df63d0d6375ed6d" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="com.jakewharton.android.repackaged" name="dalvik-dx" version="9.0.0_r3">
<artifact name="dalvik-dx-9.0.0_r3.jar">
<pgp value="47bf592261cd1a8a69b703b4e0cb7823cfd00fbf"/>
<sha256 value="b29c1c21e52ed6238cd3fed39d880a17ecf2360118604548cea8821be6801e1c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.linkedin.dexmaker" name="dexmaker" version="2.28.1">
<artifact name="dexmaker-2.28.1.jar">
<pgp value="8df3b0aa23ed78be5233f6c2dea3d207428ef16d"/>
<sha256 value="824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.ibm.icu" name="icu4j" version="70.1">
<artifact name="icu4j-70.1.jar">
<pgp value="cb3190ca7842439e57f3712e44ce7bf2825ea2cd"/>
@ -2499,56 +2573,111 @@
<sha256 value="99ec69ef0628695c24dbbc2cc4b8d7c61a754697d624f5233fc65f43faf2d235" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest" name="ktlint" version="0.45.2">
<artifact name="ktlint-0.45.2.jar">
<sha256 value="279905d78118e9db41182ce214ac27e00a88c228537633175a27bc36671e0296" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-core" version="0.43.2">
<artifact name="ktlint-core-0.43.2.jar">
<sha256 value="401515a76b780a32ef9dfeaf69f77316934c4bb90f339488638311789eca7a1a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-core" version="0.45.2">
<artifact name="ktlint-core-0.45.2.jar">
<sha256 value="383e463ee7d1b082db7928110522925cc06389af1bec65da526a52d113d393f6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-baseline" version="0.43.2">
<artifact name="ktlint-reporter-baseline-0.43.2.jar">
<sha256 value="733ee7e2cadb321d6597b3501c70c7da73117adaa0c6bc084dfc16c455d68806" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-baseline" version="0.45.2">
<artifact name="ktlint-reporter-baseline-0.45.2.jar">
<sha256 value="05262e8ab61191abf36ab481d2cde0fdd5b4e620ddde8e4c547af5937b9c60e0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-checkstyle" version="0.43.2">
<artifact name="ktlint-reporter-checkstyle-0.43.2.jar">
<sha256 value="becafb4006b9f2e82c99749864a1a8de340ee84ac7271631a68981a44f51e808" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-checkstyle" version="0.45.2">
<artifact name="ktlint-reporter-checkstyle-0.45.2.jar">
<sha256 value="f587225e2a0a16673184e96aa7e52bebd1bb838376d683b602509da43841dd34" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-html" version="0.43.2">
<artifact name="ktlint-reporter-html-0.43.2.jar">
<sha256 value="800392e150d3266e72ca53c6ccca3136d4e26445dd9216c6ac6cfc1ba3afafe5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-html" version="0.45.2">
<artifact name="ktlint-reporter-html-0.45.2.jar">
<sha256 value="c3f8cc9dacc1e0d2816c6a23b66b3e4af742f3aad11f882924d2807502aea71b" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-json" version="0.43.2">
<artifact name="ktlint-reporter-json-0.43.2.jar">
<sha256 value="9d4a94190d96d671000a06a50c9d1ce111d0dcf629bef8b4f0221a9e3f3699a0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-json" version="0.45.2">
<artifact name="ktlint-reporter-json-0.45.2.jar">
<sha256 value="7dc12cd16914f42255b376fae5b176b2d80bb2957a05b501a27b8d3e9f464bdc" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-plain" version="0.43.2">
<artifact name="ktlint-reporter-plain-0.43.2.jar">
<sha256 value="1cab63f431ec4e9463df7a767f131ccfa8d76259c01fecc63a4c000063e8ee43" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-plain" version="0.45.2">
<artifact name="ktlint-reporter-plain-0.45.2.jar">
<sha256 value="d957c8647146fc79493fca30df84d26c532a71e1ad312f31f50b8fcd00f2fbd3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-sarif" version="0.43.2">
<artifact name="ktlint-reporter-sarif-0.43.2.jar">
<sha256 value="ed0046aaa4a2e4544197bfdccf88d472ef413a55ad05b6dc8aae41338e9d3748" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-sarif" version="0.45.2">
<artifact name="ktlint-reporter-sarif-0.45.2.jar">
<sha256 value="c2c8cb17e778516d57851ef8b1f604d472c07ecb635ef2115ed40de1fc63eb2e" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-experimental" version="0.43.2">
<artifact name="ktlint-ruleset-experimental-0.43.2.jar">
<sha256 value="d89e0edcdca0ae375c090565e323520ab5d424d82fd6ac6290ea986d360f0b11" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-experimental" version="0.45.2">
<artifact name="ktlint-ruleset-experimental-0.45.2.jar">
<sha256 value="f9c886d091adbeb33317027a5b4ad8afd0bacdf902341925d75de698f9dd3f80" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-standard" version="0.43.2">
<artifact name="ktlint-ruleset-standard-0.43.2.jar">
<sha256 value="6774dc9d42aa7c7fdd4a7f3732b56fdab99ba78ce0c4eb5159036525657d0014" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-standard" version="0.45.2">
<artifact name="ktlint-ruleset-standard-0.45.2.jar">
<sha256 value="68efb16811780b6060120834a8d75ebd609d487824612f4bfff80ba02066e61c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-test" version="0.43.2">
<artifact name="ktlint-ruleset-test-0.43.2.jar">
<sha256 value="7270c4d98b2cda268c25397a02b7dea0ab8cb923958cb3853121e0d9366ce797" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-test" version="0.45.2">
<artifact name="ktlint-ruleset-test-0.45.2.jar">
<sha256 value="6660e92d94041b887e85b9620e4b7427d14c18724284092b3b35b2abebe879c1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.puppycrawl.tools" name="checkstyle" version="7.2">
<artifact name="checkstyle-7.2.jar">
<pgp value="06d34ed6ff73de368a772a781063fe98bcecb758"/>
@ -2600,6 +2729,12 @@
<sha256 value="2570fab55515cbf881d7a4ceef49fc515490bc027057e666776a2832465aeca0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.squareup" name="kotlinpoet" version="1.8.0">
<artifact name="kotlinpoet-1.8.0.jar">
<pgp value="afa2b1823fc021bfd08c211fd5f4c07a434ab3da"/>
<sha256 value="a4f7f1f1306a97740b2c18c6089cddf65626764c4cd848aa83363681268e57f0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.squareup.okhttp3" name="okhttp" version="4.9.2">
<artifact name="okhttp-4.9.2.jar">
<sha256 value="3b2ee1b768c1df28c30d2fe6b38dda4d2c519210e30ca3d27950618c563c92de" origin="Generated by Gradle"/>
@ -3594,6 +3729,106 @@
<sha256 value="ed80b79d2426ec0f1fb900691dc61de64d83f649d0d0ad9f545413d6435cf9ff" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="io.mockk" name="mockk" version="1.12.3">
<artifact name="mockk-1.12.3.jar">
<sha256 value="dd39be18d38ba8c157d752f8e26aeb05ef80354f73f05faaac9f98c2f3c35496" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-agent-android" version="1.12.3">
<artifact name="mockk-agent-android-1.12.3.aar">
<sha256 value="3a14b27b3888370a8e6e8af62979efdd87f31451c798a41eca741f68ce7772ab" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-agent-api" version="1.12.3">
<artifact name="mockk-agent-api-1.12.3.jar">
<sha256 value="c9de731e90bbd7a27ed13e5370e7a10ab44b4fe1e85137bc15568494213aade3" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-agent-common" version="1.12.3">
<artifact name="mockk-agent-common-1.12.3.jar">
<sha256 value="201f62541a73bed02ec346e413e7f52f70d300cf8c3ead3d37fca8dfc42fc97c" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-android" version="1.12.3">
<artifact name="mockk-android-1.12.3.aar">
<sha256 value="3ad29a64b6bf8a1ce150f6cda36fdd56dec273a2fbcb169e84ccda6126aa3497" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-common" version="1.12.3">
<artifact name="mockk-common-1.12.3.jar">
<sha256 value="2fb0d511ab5ec1fa31981d1dba94a9f8da603787a81e59d36395c695b661a2ab" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-dsl" version="1.12.3">
<artifact name="mockk-dsl-1.12.3.jar">
<sha256 value="05ceb1530ec4e6f9c7a1fe9c5b194a97e48023a95aaa4b91c96364f70c020f93" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.mockk" name="mockk-dsl-jvm" version="1.12.3">
<artifact name="mockk-dsl-jvm-1.12.3.jar">
<sha256 value="038d1c794cb26e3f56d217fa31ccf9b9f08bdec18c50b078705ed8f2fe1006b9" origin="Generated by Gradle because a key couldn't be downloaded"/>
</artifact>
</component>
<component group="io.netty" name="netty-buffer" version="4.1.34.Final">
<artifact name="netty-buffer-4.1.34.Final.jar">
<sha256 value="39dfe88df8505fd01fbf9c1dbb6b6fa9b0297e453c3dc4ce039ea578aea2eaa3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-codec" version="4.1.34.Final">
<artifact name="netty-codec-4.1.34.Final.jar">
<sha256 value="52e9eeb3638a8ed0911c72a508c05fa4f9d3391125eae46f287d3a8a0776211d" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-codec-http" version="4.1.34.Final">
<artifact name="netty-codec-http-4.1.34.Final.jar">
<sha256 value="5df5556ef6b0e7ce7c72a359e4ca774fcdf8d8fe12f0b6332715eaa44cfe41f8" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-codec-http2" version="4.1.34.Final">
<artifact name="netty-codec-http2-4.1.34.Final.jar">
<sha256 value="319f66f3ab0d3aac3477febf19c259990ee8c639fc7da8822dfa58e7dab1bdcf" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-codec-socks" version="4.1.34.Final">
<artifact name="netty-codec-socks-4.1.34.Final.jar">
<sha256 value="9c4ff58b648193942654db20f172d017441625754b902394f620f04074830346" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-common" version="4.1.34.Final">
<artifact name="netty-common-4.1.34.Final.jar">
<sha256 value="122931117eacf370b054d0e8a2411efa81de4956a6c3f938b0f0eb915969a425" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-handler" version="4.1.34.Final">
<artifact name="netty-handler-4.1.34.Final.jar">
<sha256 value="035616801fe9894ca2490832cf9976536dac740f41e90de1cdd4ba46f04263d1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-handler-proxy" version="4.1.34.Final">
<artifact name="netty-handler-proxy-4.1.34.Final.jar">
<sha256 value="f506c6acb97b3e0b0795cf9f0971d80bbab7c17086312fa225b98ccc94be6dff" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-resolver" version="4.1.34.Final">
<artifact name="netty-resolver-4.1.34.Final.jar">
<sha256 value="774221ed4c130b532865770b10630bc12d0d400127da617ee0ac8de2a7ac2097" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-transport" version="4.1.34.Final">
<artifact name="netty-transport-4.1.34.Final.jar">
<sha256 value="2b3f7d3a595101def7d411793a675bf2a325964475fd7bdbbe448e908de09445" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.opencensus" name="opencensus-api" version="0.21.0">
<artifact name="opencensus-api-0.21.0.jar">
<sha256 value="8e2cb0f6391d8eb0a1bcd01e7748883f0033b1941754f4ed3f19d2c3e4276fc8" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.opencensus" name="opencensus-contrib-grpc-metrics" version="0.21.0">
<artifact name="opencensus-contrib-grpc-metrics-0.21.0.jar">
<sha256 value="29fc79401082301542cab89d7054d2f0825f184492654c950020553ef4ff0ef8" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-buffer" version="4.1.34.Final">
<artifact name="netty-buffer-4.1.34.Final.jar">
<sha256 value="39dfe88df8505fd01fbf9c1dbb6b6fa9b0297e453c3dc4ce039ea578aea2eaa3" origin="Generated by Gradle"/>
@ -3838,6 +4073,11 @@
<sha256 value="941660d47822f9c0d80d40ea06d4981fcdc2b87cc625381b545efd7e6b449cef" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="net.java.dev.jna" name="jna" version="5.5.0">
<artifact name="jna-5.5.0.jar">
<sha256 value="b308faebfe4ed409de8410e0a632d164b2126b035f6eacff968d3908cafb4d9e" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="net.java.dev.jna" name="jna" version="5.6.0">
<artifact name="jna-5.6.0.jar">
<pgp value="fa7929f83ad44c4590f6cc6815c71c0a4e0b8edd"/>
@ -3849,6 +4089,16 @@
<sha256 value="9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="net.java.dev.jna" name="jna-platform" version="5.5.0">
<artifact name="jna-platform-5.5.0.jar">
<sha256 value="24d81621f82ac29fcdd9a74116031f5907a2343158e616f4573bbfa2434ae0d5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="net.java.dev.jna" name="jna-platform" version="5.6.0">
<artifact name="jna-platform-5.6.0.jar">
<sha256 value="9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="net.ltgt.gradle" name="gradle-errorprone-plugin" version="0.0.16">
<artifact name="gradle-errorprone-plugin-0.0.16.jar">
<sha256 value="08915abc054a0e514911890a12834e266a9478ac79d208b24ad91bd71e4b633b" origin="Generated by Gradle"/>
@ -4847,6 +5097,11 @@
<sha256 value="ff563a4b2b3cb6c215629d6d5c652ad92c3939313d05073d3f6fed0aae67834f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-daemon-embeddable" version="1.6.20">
<artifact name="kotlin-daemon-embeddable-1.6.20.jar">
<sha256 value="ff563a4b2b3cb6c215629d6d5c652ad92c3939313d05073d3f6fed0aae67834f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-gradle-plugin" version="1.6.10">
<artifact name="kotlin-gradle-plugin-1.6.10.jar">
<sha256 value="66c12048f8a4e9cf92ad65b12ac615702c11ae503f53c69f57f626128be1762a" origin="Generated by Gradle"/>
@ -4857,6 +5112,11 @@
<sha256 value="53fb7770ad9880e289b701d9fb729c824c59f44f2b0349ee6aac94380c4de129" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-gradle-plugin" version="1.6.20">
<artifact name="kotlin-gradle-plugin-1.6.20.jar">
<sha256 value="53fb7770ad9880e289b701d9fb729c824c59f44f2b0349ee6aac94380c4de129" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-gradle-plugin-api" version="1.6.10">
<artifact name="kotlin-gradle-plugin-api-1.6.10.jar">
<sha256 value="7aa62528de3da7b66d97430c6d1b3f3781455b053231bbbf967e82900f527c44" origin="Generated by Gradle"/>
@ -4942,6 +5202,11 @@
<sha256 value="59c57ab609494d2a30d6ea3737428a56918ff0b8031081ea73b8472fdec06e44" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.4.31">
<artifact name="kotlin-reflect-1.4.31.jar">
<sha256 value="91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.4.32">
<artifact name="kotlin-reflect-1.4.32.jar">
<sha256 value="dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b" origin="Generated by Gradle"/>
@ -5022,6 +5287,11 @@
<sha256 value="b53a20cc9526459a8fb0d9c23e86de3166f8d65c1c66691fad52174a75fd5d09" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-serialization" version="1.6.20">
<artifact name="kotlin-serialization-1.6.20.jar">
<sha256 value="af8a3533e70273a3d92c4266c6072ab5b905892b4e46b051641b248e34b85613" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-scripting-jvm" version="1.6.20">
<artifact name="kotlin-scripting-jvm-1.6.20.jar">
<sha256 value="b53a20cc9526459a8fb0d9c23e86de3166f8d65c1c66691fad52174a75fd5d09" origin="Generated by Gradle"/>
@ -5042,9 +5312,9 @@
<sha256 value="52283996fe4067cd7330288b96ae67ecd463614dc741172c54d9d349ab6a9cd7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.21">
<artifact name="kotlin-stdlib-1.5.21.jar">
<sha256 value="9d212b5aef23f805e0161853a5f5aefe8965b8766c889317b60f1b58bd1cf9ad" origin="Generated by Gradle"/>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.30">
<artifact name="kotlin-stdlib-1.5.30.jar">
<sha256 value="c55608e9eb6df7327e74b21e271d324dc523cef31587b8d6d2393db08d6e000c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.31">
@ -5127,6 +5397,21 @@
<sha256 value="ac12f092f12b575c1f9e0ab5025b1e610b0fe95663e26371c16c328895711bae" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.5.30">
<artifact name="kotlin-stdlib-jdk7-1.5.30.jar">
<sha256 value="7ce040646e6b9af662c96bbb988a1adcd4c994834d424e16960fa79fff93825d" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.4.32">
<artifact name="kotlin-stdlib-jdk7-1.4.32.jar">
<sha256 value="5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.5.0">
<artifact name="kotlin-stdlib-jdk7-1.5.0.jar">
<sha256 value="ac12f092f12b575c1f9e0ab5025b1e610b0fe95663e26371c16c328895711bae" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.5.31">
<artifact name="kotlin-stdlib-jdk7-1.5.31.jar">
<sha256 value="a25bf47353ce899d843cbddee516d621a73473e7fba97f8d0301e7b4aed7c15f" origin="Generated by Gradle"/>
@ -5137,6 +5422,11 @@
<sha256 value="870d35fd266b2daf64c1080fe51824d3c368f7995384a8d7c5fc2fdc40eb7b3a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.6.0">
<artifact name="kotlin-stdlib-jdk7-1.6.0.jar">
<sha256 value="870d35fd266b2daf64c1080fe51824d3c368f7995384a8d7c5fc2fdc40eb7b3a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.6.10">
<artifact name="kotlin-stdlib-jdk7-1.6.10.jar">
<sha256 value="2aedcdc6b69b33bdf5cc235bcea88e7cf6601146bb6bcdffdb312bbacd7be261" origin="Generated by Gradle"/>
@ -5187,6 +5477,11 @@
<sha256 value="fdab1bf120e2b5e7ab6d7888e9ebc024ec6b8ca729361296395dab634b213695" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.6.20">
<artifact name="kotlin-stdlib-jdk8-1.6.20.jar">
<sha256 value="fdab1bf120e2b5e7ab6d7888e9ebc024ec6b8ca729361296395dab634b213695" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-test" version="1.6.10">
<artifact name="kotlin-test-1.6.10.jar">
<sha256 value="b891453cafbf961532d2ba0fb8969e40b0f7c168c9a2fc6a8cdf7c1b0577a36a" origin="Generated by Gradle"/>
@ -5277,6 +5572,11 @@
<sha256 value="e678e804cc55891e6c0576e113f725e388bb59341e906dd0f80104defe9a49c1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-util-klib" version="1.6.20">
<artifact name="kotlin-util-klib-1.6.20.jar">
<sha256 value="e678e804cc55891e6c0576e113f725e388bb59341e906dd0f80104defe9a49c1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="atomicfu" version="0.16.3">
<artifact name="atomicfu-metadata-0.16.3-all.jar">
<sha256 value="c3c0546dd33e0ef75782734d9703eb3583a28414b1d4464fcbde56d70a7d5a6d" origin="Generated by Gradle because artifact wasn't signed"/>
@ -5326,6 +5626,11 @@
<sha256 value="ad89b520c22eab46e63610588a8c424040243294015ec214e30643c0efb7e5d4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-android" version="1.5.2">
<artifact name="kotlinx-coroutines-android-1.5.2.jar">
<sha256 value="86cf9892b0bd5306a8f4d7ad8a82356f614dc7d519eb3063b0887d7c2b405928" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core" version="1.3.4">
<artifact name="kotlinx-coroutines-core-1.3.4.jar">
<sha256 value="17bec6112d93f5fcb11c27ecc8a14b48e30a5689ccf42c95025b89ba2210c28f" origin="Generated by Gradle"/>
@ -5358,6 +5663,11 @@
<sha256 value="78d6cc7135f84d692ff3752fcfd1fa1bbe0940d7df70652e4f1eaeec0c78afbb" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-jvm" version="1.5.2">
<artifact name="kotlinx-coroutines-core-jvm-1.5.2.jar">
<sha256 value="2314c48aa1a39c05c11f3b385cdf3c56b1745f064314e4feabecebc1572b3ac1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-jvm" version="1.5.2-native-mt">
<artifact name="kotlinx-coroutines-core-jvm-1.5.2-native-mt.jar">
<sha256 value="db754be65cd22e18c8861a141cc35cedc3b659292eacb7f9d2c78a5386795dec" origin="Generated by Gradle"/>
@ -5373,6 +5683,31 @@
<sha256 value="bd5e3639e853cc1e8dca4db696ab29f95924453da93db96e20f30979e9463ef2" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-debug" version="1.5.2">
<artifact name="kotlinx-coroutines-debug-1.5.2.jar">
<sha256 value="f8f00f4f018d8445fb4c69655e433a8cb494c9b86cbaba841cc3ff54059c7d39" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-jdk8" version="1.6.0">
<artifact name="kotlinx-coroutines-jdk8-1.6.0.jar">
<sha256 value="cf93f59cafabea454b0bb03c4c3ea055f6ea17f7ff06770a765eca94dd5de867" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-slf4j" version="1.6.0">
<artifact name="kotlinx-coroutines-slf4j-1.6.0.jar">
<sha256 value="d8a019ae7be13992867be62d97e6993afc141a956010f5f704d569f5e9677167" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-test" version="1.5.2">
<artifact name="kotlinx-coroutines-test-1.5.2.jar">
<sha256 value="7f5ed01d76ecb37fc714bc0e0850b81cf753b0e968495a8db0efcd20fcb5ee60" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-test-jvm" version="1.6.0">
<artifact name="kotlinx-coroutines-test-jvm-1.6.0.jar">
<sha256 value="bef600516dbb41b237a883609a4f7468c2ed06d437ac13082ff4471723b4e88f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-jdk8" version="1.6.0">
<artifact name="kotlinx-coroutines-jdk8-1.6.0.jar">
<sha256 value="cf93f59cafabea454b0bb03c4c3ea055f6ea17f7ff06770a765eca94dd5de867" origin="Generated by Gradle"/>
@ -5391,21 +5726,62 @@
<sha256 value="aedb7bc0b0669b51fb20c6f0ca2f6a7b3e7b76ebf46f64a5b2a842eaaa386913" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-metadata-jvm" version="0.3.0">
<artifact name="kotlinx-metadata-jvm-0.3.0.jar">
<sha256 value="fdaf7ba158465f6b6e9ce5762e0300fd681a976fbfeb5ed50fa5a2b26868cec8" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core" version="1.3.2">
<artifact name="kotlinx-serialization-core-1.3.2.jar">
<sha256 value="61d27c6a971b2c6ae70c97dca3aee642525fc428ffdf52b9e276708a9e40cea8" origin="Generated by Gradle"/>
</artifact>
<artifact name="kotlinx-serialization-core-metadata-1.3.2-all.jar">
<sha256 value="b5fe298c6242baab814f701fd21478a326f4b448409c789a4962337c05f4046e" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-jvm" version="1.1.0">
<artifact name="kotlinx-serialization-core-jvm-1.1.0.jar">
<sha256 value="69d18c700cfdf207b3e9bf6f5d58e7de08482d9e34d7c2a0adcb1db8082df943" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-jvm" version="1.3.2">
<artifact name="kotlinx-serialization-core-jvm-1.3.2.jar">
<sha256 value="4b0099a2d79c6ace9b67af8a016e03fb2f08e2f4a3213ad811ef9e9a1363a15c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-linuxx64" version="1.3.0">
<artifact name="kotlinx-serialization-core.klib">
<sha256 value="ad49d11305253b69fdfab52bb88b2181701916871442081010c82950650021ad" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-linuxx64" version="1.3.2">
<artifact name="kotlinx-serialization-core.klib">
<sha256 value="8b70aea311112b67d58c42f1061e06f1fa351cd0abedfeb0410041596cf0ff50" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-json" version="1.3.2">
<artifact name="kotlinx-serialization-json-1.3.2.jar">
<sha256 value="8d58c910f51a2d23f24ac9aae4bb5a06e0273faeccc709b36458ddd2cacb0805" origin="Generated by Gradle"/>
</artifact>
<artifact name="kotlinx-serialization-json-metadata-1.3.2-all.jar">
<sha256 value="2f0dfe3bddb6c13f696c47113947b03a876f66aafcf593a66e7b840d203e5e17" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-json-jvm" version="1.1.0">
<artifact name="kotlinx-serialization-json-jvm-1.1.0.jar">
<sha256 value="cea6836d3a3990b7ac59f61a9534a0bf1c8d3932bd206080a3a13622ec7587d1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-json-jvm" version="1.3.2">
<artifact name="kotlinx-serialization-json-jvm-1.3.2.jar">
<sha256 value="706457ada21aba6cc4cdcc9637f20e700786e125ff100115c9b3e4027be03de6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-json-linuxx64" version="1.3.2">
<artifact name="kotlinx-serialization-json.klib">
<sha256 value="2a83e997494070d01e91d9d5d356f26cb1b2ba703fd063d7eee4ad60b9fe328c" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.trove4j" name="trove4j" version="20160824">
<artifact name="trove4j-20160824.jar">
<pgp value="33fd4bfd33554634053d73c0c2148900bcd3c2af"/>
@ -5884,6 +6260,11 @@
<sha256 value="35a77865bb9a451e99b95575cb154a5f08ecb007bd17e390817c0f31ab9db869" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.robolectric" name="utils-reflector" version="4.4">
<artifact name="utils-reflector-4.4.jar">
<sha256 value="35a77865bb9a451e99b95575cb154a5f08ecb007bd17e390817c0f31ab9db869" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.robolectric" name="utils-reflector" version="4.8.1">
<artifact name="utils-reflector-4.8.1.jar">
<sha256 value="d17357e5254e1e14ee258fc1604bbe011aa425fe5e7c768a04fd043476e41267" origin="Generated by Gradle"/>
@ -5894,6 +6275,11 @@
<sha256 value="c0e6cf0068ec62e86ba4e15959ed80255bd5190373f572bb5697f5143464dbf3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.slf4j" name="slf4j-android" version="1.7.36">
<artifact name="slf4j-android-1.7.36.jar">
<sha256 value="c0e6cf0068ec62e86ba4e15959ed80255bd5190373f572bb5697f5143464dbf3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.slf4j" name="slf4j-api" version="1.7.25">
<artifact name="slf4j-api-1.7.25.jar">
<pgp value="475f3b8e59e6e63aa78067482c7b12f2a511e325"/>
@ -5961,6 +6347,12 @@
<sha256 value="83168112220ac912a3dba0eebae90a4da5bf1e24b1bafd401e3d4f9f598bb2cb" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.xerial" name="sqlite-jdbc" version="3.36.0">
<artifact name="sqlite-jdbc-3.36.0.jar">
<pgp value="56b505dc8a29c69138a430b9429c8816dea04cdb"/>
<sha256 value="c0f13672668ec479dbf685dcadf6c2dd2fb44f266f99a90624dde46eb5524aaf" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="xerces" name="xercesImpl" version="2.12.0">
<artifact name="xercesImpl-2.12.0.jar">
<pgp value="51b52dc5dd452f92be342cc2858fc4c4f43856a3"/>

1
index/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

98
index/build.gradle Normal file
View File

@ -0,0 +1,98 @@
plugins {
id 'org.jetbrains.kotlin.multiplatform'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.20'
id 'com.android.library'
id "org.jlleitschuh.gradle.ktlint" version "10.2.1"
}
group = 'org.fdroid'
version = '0.1'
kotlin {
android {
compilations.all {
kotlinOptions.jvmTarget = '1.8'
}
}
// def hostOs = System.getProperty("os.name")
// def isMingwX64 = hostOs.startsWith("Windows")
// def nativeTarget
// if (hostOs == "Mac OS X") nativeTarget = macosX64('native')
// else if (hostOs == "Linux") nativeTarget = linuxX64("native") {
// binaries { sharedLib { baseName = "fdroid_index" } }
// }
// else if (isMingwX64) nativeTarget = mingwX64("native")
// else throw new GradleException("Host OS is not supported in Kotlin/Native.")
sourceSets {
all {
languageSettings {
optIn('kotlin.RequiresOptIn')
explicitApi('strict')
}
}
commonMain {
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
implementation 'io.github.microutils:kotlin-logging:2.1.21'
implementation project(":download")
implementation "io.ktor:ktor-io:2.0.0"
}
}
sharedTest {
dependencies {
implementation kotlin('test')
implementation "com.goncalossilva:resources:0.2.1"
}
}
commonTest {
dependsOn(sharedTest)
}
// JVM is disabled for now, because Android app is including it instead of Android library
jvmMain {
dependencies {
}
}
jvmTest {
dependencies {
implementation 'junit:junit:4.13.2'
}
}
androidMain {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-reflect:1.6.20"
implementation "org.slf4j:slf4j-android:1.7.36"
}
}
androidTest {
dependencies {
implementation 'junit:junit:4.13.2'
}
}
nativeMain {
dependencies {
}
}
nativeTest {
}
}
}
android {
compileSdkVersion 31
sourceSets {
main.manifest.srcFile('src/androidMain/AndroidManifest.xml')
getByName("androidTest").java.srcDir(file("src/androidAndroidTest/kotlin"))
}
defaultConfig {
minSdkVersion 21
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
apply from: "${rootProject.rootDir}/gradle/ktlint.gradle"

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.fdroid.index">
</manifest>

View File

@ -0,0 +1,17 @@
package org.fdroid.index
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.decodeFromStream
import org.fdroid.index.v1.IndexV1
import org.fdroid.index.v2.IndexV2
import java.io.InputStream
@OptIn(ExperimentalSerializationApi::class)
public fun IndexParser.parseV1(inputStream: InputStream): IndexV1 {
return json.decodeFromStream(inputStream)
}
@OptIn(ExperimentalSerializationApi::class)
public fun IndexParser.parseV2(inputStream: InputStream): IndexV2 {
return json.decodeFromStream(inputStream)
}

View File

@ -0,0 +1,53 @@
package org.fdroid.index
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.jsonObject
import org.fdroid.index.v2.IndexStreamReceiver
import org.fdroid.index.v2.IndexV2
import org.fdroid.index.v2.PackageV2
import org.fdroid.index.v2.RepoV2
import java.io.InputStream
@OptIn(ExperimentalSerializationApi::class)
public class IndexStreamProcessor(
private val indexStreamReceiver: IndexStreamReceiver,
private val json: Json = Json,
) {
public fun process(inputStream: InputStream) {
json.decodeFromStream(IndexStreamSerializer(), inputStream)
}
private inner class IndexStreamSerializer : KSerializer<IndexV2?> {
override val descriptor = IndexV2.serializer().descriptor
override fun deserialize(decoder: Decoder): IndexV2? {
val jsonInput = decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
val jsonObject = jsonInput.decodeJsonElement().jsonObject
val jsonRepo = jsonObject["repo"] ?: throw SerializationException()
val repo = json.decodeFromJsonElement<RepoV2>(jsonRepo)
val repoId = indexStreamReceiver.receive(null, repo)
val packages = jsonObject["packages"]?.jsonObject ?: throw SerializationException()
// TODO check that this isn't reading the entire stream already
packages.entries.forEach { (packageId, jsonPackage) ->
val p = json.decodeFromJsonElement<PackageV2>(jsonPackage)
indexStreamReceiver.receive(repoId, packageId, p)
}
return null
}
override fun serialize(encoder: Encoder, value: IndexV2?) {
error("Not implemented")
}
}
}

View File

@ -0,0 +1,125 @@
package org.fdroid.index
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import kotlinx.serialization.serializer
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KParameter
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
/**
* A class using Kotlin reflection to implement JSON Merge Patch (RFC 7386) against data classes.
* This approach loses type-safety, so you need to ensure that the structure of the [JsonObject]
* matches exactly the structure of the data class you want to apply the diff on.
* If something unexpected happens, [SerializationException] gets thrown.
*/
public object ReflectionDiffer {
@Throws(SerializationException::class)
public fun applyDiff(obj: Map<*, *>, diff: JsonObject): Map<*, *> {
return getMap(obj, diff)
}
@Throws(SerializationException::class)
public fun <T : Any> applyDiff(obj: T, diff: JsonObject): T {
val constructor = obj::class.primaryConstructor ?: e("no primary constructor")
val params = HashMap<KParameter, Any?>()
constructor.parameters.forEach { parameter ->
val prop = obj::class.memberProperties.find { memberProperty ->
memberProperty.name == parameter.name
} ?: e("no member property for constructor, is data class?")
if (prop.name !in diff) {
params[parameter] = prop.getter.call(obj)
return@forEach
}
if (diff[prop.name] is JsonNull) {
if (parameter.type.isMarkedNullable) params[parameter] = null
else if (!parameter.isOptional) e("not nullable: ${parameter.name}")
return@forEach
}
params[parameter] = when (prop.returnType.classifier) {
Int::class -> diff[prop.name]?.jsonPrimitive?.int ?: e("${prop.name} no int")
Long::class -> diff[prop.name]?.jsonPrimitive?.long ?: e("${prop.name} no long")
String::class -> diff[prop.name]?.jsonPrimitive?.content
?: e("${prop.name} no string")
Map::class -> applyDiff(
prop.getter.call(obj) as Map<*, *>,
diff[prop.name]?.jsonObject ?: e("${prop.name} no map")
)
else -> {
val newObj = prop.getter.call(obj)
val jsonObject = diff[prop.name] as JsonObject
if (newObj == null) {
val factory = (prop.returnType.classifier as KClass<*>).primaryConstructor!!
constructFromJson(factory, jsonObject)
} else {
applyDiff(newObj, jsonObject)
}
}
}
}
return constructor.callBy(params)
}
@Throws(SerializationException::class)
private fun <T : Any> constructFromJson(
factory: KFunction<T>,
diff: JsonObject,
): T {
val params = HashMap<KParameter, Any?>()
factory.parameters.forEach { prop ->
if (prop.name !in diff) e("${prop.name} required but not found")
if (diff[prop.name] is JsonNull) {
if (prop.type.isMarkedNullable) params[prop] = null
else if (!prop.isOptional) e("not nullable: ${prop.name}")
return@forEach
}
params[prop] = when (prop.type.classifier) {
Int::class -> diff[prop.name]?.jsonPrimitive?.int ?: e("no int")
Long::class -> diff[prop.name]?.jsonPrimitive?.long ?: e("no long")
String::class -> diff[prop.name]?.jsonPrimitive?.content ?: e("no string")
Map::class -> applyDiff(
prop.type::class.createInstance(),
diff[prop.name]?.jsonObject!!,
)
else -> TODO()
}
}
return factory.callBy(params)
}
@Throws(SerializationException::class)
private fun getMap(map: Map<*, *>, jsonObject: JsonObject?): Map<*, *> {
return map.toMutableMap().apply {
jsonObject?.entries?.forEach { (key, value) ->
if (value is JsonNull) remove(key)
else set(key, value.jsonPrimitive.content)
} ?: e("no object")
}
}
@Throws(SerializationException::class)
private fun e(msg: String): Nothing = throw SerializationException(msg)
public inline fun <reified T> Json.decodeOr(
key: String,
json: JsonObject,
default: () -> T,
): T {
return if (json.containsKey(key)) {
decodeFromJsonElement(serializersModule.serializer(), json)
} else {
default()
}
}
}

View File

@ -0,0 +1,56 @@
package org.fdroid.index
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import org.fdroid.index.v2.FileV2
import org.fdroid.index.v2.LocalizedTextV2
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
internal class ReflectionDifferTest {
@Test
fun testLocalizedNullableTextV2Diff() {
val old: LocalizedTextV2 = buildMap {
put("de", "football")
put("en", "bar")
put("de-DE", "foo bar")
}
val json = """
{
"de": "foo",
"en": null,
"en-US": "bar"
}
""".trimIndent()
val diff = Json.parseToJsonElement(json).jsonObject
val result = ReflectionDiffer.applyDiff(old, diff)
assertEquals(3, result.size)
assertEquals("foo", result["de"])
assertEquals("bar", result["en-US"])
assertEquals("foo bar", result["de-DE"])
}
@Test
fun testFileDiffV2() {
val old = FileV2(
name = "foo",
sha256 = "bar",
size = Random.nextLong()
)
val json = """
{
"name": "foo bar",
"size": null
}
""".trimIndent()
val diff = Json.parseToJsonElement(json).jsonObject
val result = ReflectionDiffer.applyDiff(old, diff)
assertEquals("foo bar", result.name)
assertEquals("bar", result.sha256)
assertEquals(null, result.size)
}
}

View File

@ -0,0 +1,25 @@
package org.fdroid.index
import io.ktor.utils.io.jvm.javaio.toByteReadChannel
import io.ktor.utils.io.jvm.javaio.toInputStream
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import org.fdroid.index.v1.IndexV1
import java.io.File
import java.io.FileInputStream
import kotlin.test.Test
internal class StreamTest {
@Test
@OptIn(ExperimentalSerializationApi::class)
fun test() = runBlocking {
val file = File("src/commonTest/resources/index-v1.json")
val byteChannel = FileInputStream(file).toByteReadChannel()
val index = Json.decodeFromStream<IndexV1>(byteChannel.toInputStream())
}
}

View File

@ -0,0 +1,37 @@
package org.fdroid.index
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.fdroid.index.v1.IndexV1
import org.fdroid.index.v2.IndexV2
public object IndexParser {
@Volatile
private var JSON: Json? = null
/**
* Initializing [Json] is expensive, so using this method is preferable as it keeps returning
* a single instance with the recommended settings.
*/
public val json: Json
@JvmStatic
get() {
return JSON ?: synchronized(this) {
Json {
ignoreUnknownKeys = true
}
}
}
@JvmStatic
public fun parseV1(str: String): IndexV1 {
return json.decodeFromString(str)
}
@JvmStatic
public fun parseV2(str: String): IndexV2 {
return json.decodeFromString(str)
}
}

View File

@ -0,0 +1,55 @@
package org.fdroid.index.v1
import kotlinx.serialization.Serializable
@Serializable
public data class AppV1(
val categories: List<String> = emptyList(), // missing in wind repo
val antiFeatures: List<String> = emptyList(),
val summary: String? = null,
val description: String? = null,
val changelog: String? = null,
val translation: String? = null,
val issueTracker: String? = null,
val sourceCode: String? = null,
val binaries: String? = null,
val name: String? = null,
val authorName: String? = null,
val authorEmail: String? = null,
val authorWebSite: String? = null,
val authorPhone: String? = null,
val donate: String? = null,
val liberapayID: String? = null,
val liberapay: String? = null,
val openCollective: String? = null,
val bitcoin: String? = null,
val litecoin: String? = null,
val flattrID: String? = null,
val suggestedVersionName: String? = null, // missing in guardian project repo
val suggestedVersionCode: String? = null, // missing in wind repo
val license: String,
val webSite: String? = null,
val added: Long? = null, // missing in wind repo,
val icon: String? = null,
val packageName: String,
val lastUpdated: Long? = null, // missing in wind repo,
val localized: Map<String, Localized>? = null,
)
@Serializable
public data class Localized(
val description: String? = null,
val name: String? = null,
val icon: String? = null,
val whatsNew: String? = null,
val video: String? = null,
val phoneScreenshots: List<String>? = null,
val sevenInchScreenshots: List<String>? = null,
val tenInchScreenshots: List<String>? = null,
val wearScreenshots: List<String>? = null,
val tvScreenshots: List<String>? = null,
val featureGraphic: String? = null,
val promoGraphic: String? = null,
val tvBanner: String? = null,
val summary: String? = null,
)

View File

@ -0,0 +1,31 @@
package org.fdroid.index.v1
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
public data class IndexV1(
val repo: RepoV1,
val requests: Requests,
val apps: List<AppV1>,
val packages: Map<String, List<PackageV1>>,
)
@Serializable
public data class RepoV1(
val timestamp: Long,
val version: Int,
@SerialName("maxage")
val maxAge: Int? = null, // missing in izzy repo
val name: String,
val icon: String,
val address: String,
val description: String,
val mirrors: List<String> = emptyList(), // missing in izzy repo
)
@Serializable
public data class Requests(
val install: List<String>,
val uninstall: List<String>,
)

View File

@ -0,0 +1,67 @@
package org.fdroid.index.v1
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive
@Serializable
public data class PackageV1(
val added: Long? = null,
val apkName: String,
val hash: String,
val hashType: String, // TODO enum?
val minSdkVersion: Int? = null,
val maxSdkVersion: Int? = null,
val targetSdkVersion: Int? = minSdkVersion,
val packageName: String,
val sig: String? = null,
val signer: String? = null,
val size: Long,
@SerialName("srcname")
val srcName: String? = null,
@SerialName("uses-permission")
val usesPermission: List<PermissionV1> = emptyList(),
@SerialName("uses-permission-sdk-23")
val usesPermission23: List<PermissionV1> = emptyList(),
val versionCode: Long? = null,
val versionName: String,
@SerialName("nativecode")
val nativeCode: List<String>? = null,
val features: List<String>? = null,
val antiFeatures: List<String>? = null,
)
@Serializable(with = PermissionV1Serializer::class)
public data class PermissionV1(
val name: String,
val maxSdk: Int?,
)
internal class PermissionV1Serializer : KSerializer<PermissionV1> {
override val descriptor = buildClassSerialDescriptor("PermissionV1") {
element<String>("name")
element<Int?>("maxSdk")
}
override fun deserialize(decoder: Decoder): PermissionV1 {
val jsonInput = decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
val jsonArray = jsonInput.decodeJsonElement().jsonArray
if (jsonArray.size != 2) throw IllegalArgumentException()
val name = jsonArray[0].jsonPrimitive.content
val maxSdk = jsonArray[1].jsonPrimitive.intOrNull
return PermissionV1(name, maxSdk)
}
override fun serialize(encoder: Encoder, value: PermissionV1) {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,8 @@
package org.fdroid.index.v2
public interface IndexStreamReceiver {
public fun receive(repoId: Long? = null, repo: RepoV2): Long
public fun receive(repoId: Long, packageId: String, p: PackageV2)
}

View File

@ -0,0 +1,66 @@
package org.fdroid.index.v2
import kotlinx.serialization.Serializable
@Serializable
public data class EntryV2(
val timestamp: Long,
val version: Long,
val maxAge: Int,
val index: FileV2,
val diffs: Map<String, FileV2>,
)
@Serializable
public data class FileV2(
val name: String,
val sha256: String? = null,
val size: Long? = null,
)
@Serializable
public data class IndexV2(
val repo: RepoV2,
val packages: Map<String, PackageV2>,
)
@Serializable
public data class RepoV2(
val name: String,
val icon: FileV2? = null,
val address: String,
val webBaseUrl: String?,
val description: LocalizedTextV2 = emptyMap(),
val mirrors: List<MirrorV2> = emptyList(),
val timestamp: Long,
val antiFeatures: Map<String, AntiFeatureV2> = emptyMap(),
val categories: Map<String, CategoryV2> = emptyMap(),
val releaseChannels: Map<String, ReleaseChannelV2> = emptyMap(),
)
public typealias LocalizedTextV2 = Map<String, String>
public typealias LocalizedFileV2 = Map<String, FileV2>
public typealias LocalizedFileListV2 = Map<String, List<FileV2>>
@Serializable
public data class MirrorV2(
val url: String,
val location: String? = null,
)
@Serializable
public data class AntiFeatureV2(
val icon: FileV2,
val description: LocalizedTextV2,
)
@Serializable
public data class CategoryV2(
val icon: FileV2,
val description: LocalizedTextV2,
)
@Serializable
public data class ReleaseChannelV2(
val description: LocalizedTextV2,
)

View File

@ -0,0 +1,136 @@
package org.fdroid.index.v2
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
public data class PackageV2(
val metadata: MetadataV2,
val versions: Map<String, PackageVersionV2>,
)
@Serializable
public data class MetadataV2(
val name: LocalizedTextV2? = null,
val summary: LocalizedTextV2? = null,
val description: LocalizedTextV2? = null,
val added: Long,
val lastUpdated: Long,
val webSite: String? = null,
val changelog: String? = null,
val license: String? = null,
val sourceCode: String? = null,
val issueTracker: String? = null,
val translation: String? = null,
val preferredSigner: String? = null,
val categories: List<String> = emptyList(),
val author: Author? = null,
val donation: Donation? = null,
val icon: LocalizedFileV2? = null,
val featureGraphic: LocalizedFileV2? = null,
val promoGraphic: LocalizedFileV2? = null,
val tvBanner: LocalizedFileV2? = null,
val video: LocalizedTextV2? = null,
val screenshots: Screenshots? = null,
)
@Serializable
public data class Author(
val name: String? = null,
val email: String? = null,
val website: String? = null,
val phone: String? = null,
) {
internal constructor() : this(null, null, null, null)
val isNull: Boolean get() = (name == null && email == null && website == null && phone == null)
}
@Serializable
public data class Donation(
val url: String? = null,
val liberapayID: String? = null,
val liberapay: String? = null,
val openCollective: String? = null,
val bitcoin: String? = null,
val litecoin: String? = null,
val flattrID: String? = null,
) {
internal constructor() : this(null, null, null, null, null, null, null)
val isNull: Boolean
get() = (url == null && liberapayID == null && liberapay == null &&
openCollective == null && bitcoin == null && litecoin == null && flattrID == null)
}
@Serializable
public data class Screenshots(
val phone: LocalizedFileListV2? = null,
val sevenInch: LocalizedFileListV2? = null,
val tenInch: LocalizedFileListV2? = null,
val wear: LocalizedFileListV2? = null,
val tv: LocalizedFileListV2? = null,
) {
val isNull: Boolean
get() = (phone == null && sevenInch == null && tenInch == null && wear == null
&& tv == null)
}
@Serializable
public data class PackageVersionV2(
val added: Long,
val file: FileV1,
val src: FileV2? = null,
val manifest: ManifestV2,
val releaseChannels: List<String> = emptyList(),
val antiFeatures: Map<String, LocalizedTextV2> = emptyMap(),
val whatsNew: LocalizedTextV2 = emptyMap(),
)
/**
* Like [FileV2] with the only difference that the [sha256] hash can not be null.
* Even in index-v1 this must exist, so we can use it as a primary key in the DB.
*/
@Serializable
public data class FileV1(
val name: String,
val sha256: String,
val size: Long? = null,
)
@Serializable
public data class ManifestV2(
val versionName: String,
val versionCode: Long,
val usesSdk: UsesSdkV2? = null,
val maxSdkVersion: Int? = null,
val signer: SignatureV2? = null, // TODO really null?
val usesPermission: List<PermissionV2> = emptyList(),
val usesPermissionSdk23: List<PermissionV2> = emptyList(),
@SerialName("nativecode")
val nativeCode: List<String> = emptyList(),
val features: List<FeatureV2> = emptyList(), // TODO can probably be a List<String> again
)
@Serializable
public data class UsesSdkV2(
val minSdkVersion: Int,
val targetSdkVersion: Int,
)
@Serializable
public data class SignatureV2(
val sha256: List<String>,
val hasMultipleSigners: Boolean = false,
)
@Serializable
public data class PermissionV2(
val name: String,
val maxSdkVersion: Int? = null,
)
@Serializable
public data class FeatureV2(
val name: String,
)

View File

@ -0,0 +1,49 @@
package org.fdroid.index
import com.goncalossilva.resources.Resource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.fdroid.index.v1.IndexV1
import org.fdroid.index.v2.EntryV2
import org.fdroid.index.v2.IndexV2
import kotlin.test.Test
class Test {
@Test
fun testIndexV1() {
val indexStr = Resource("src/commonTest/resources/index-v1.json").readText()
val index = Json.decodeFromString<IndexV1>(indexStr)
val indexArchiveStr =
Resource("src/commonTest/resources/fdroid-archive/index-v1.json").readText()
Json.decodeFromString<IndexV1>(indexArchiveStr)
val indexGuardianStr =
Resource("src/commonTest/resources/guardian/index-v1.json").readText()
Json.decodeFromString<IndexV1>(indexGuardianStr)
val indexIzzyStr = Resource("src/commonTest/resources/izzy/index-v1.json").readText()
Json.decodeFromString<IndexV1>(indexIzzyStr)
val indexWindStr = Resource("src/commonTest/resources/wind/index-v1.json").readText()
Json.decodeFromString<IndexV1>(indexWindStr)
}
@Test
fun testIndexV2() {
val entryStr = Resource("src/commonTest/resources/entry.json").readText()
val entry = Json.decodeFromString<EntryV2>(entryStr)
val indexStr = Resource("src/commonTest/resources/index-v2.json").readText()
val index = Json.decodeFromString<IndexV2>(indexStr)
}
@Test
fun testDiffV2() {
// val diff1Str = Resource("src/commonTest/resources/tmp.json").readText()
// val diff1 = Json.decodeFromString<DiffV2>(diff1Str)
// println(diff1)
}
}

View File

@ -0,0 +1,40 @@
package org.fdroid.index.v1
import com.goncalossilva.resources.Resource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.junit.Assume.assumeTrue
import kotlin.test.Test
internal class IndexV1Test {
@Test
fun testIndexV1() {
val indexRes = Resource("src/commonTest/resources/index-v1.json")
assumeTrue(indexRes.exists())
val indexStr = indexRes.readText()
val index = Json.decodeFromString<IndexV1>(indexStr)
val indexArchiveRes = Resource("src/commonTest/resources/fdroid-archive/index-v1.json")
assumeTrue(indexArchiveRes.exists())
val indexArchiveStr = indexArchiveRes.readText()
assumeTrue(indexRes.exists())
Json.decodeFromString<IndexV1>(indexArchiveStr)
val indexGuardianRes = Resource("src/commonTest/resources/guardian/index-v1.json")
assumeTrue(indexGuardianRes.exists())
val indexGuardianStr = indexGuardianRes.readText()
Json.decodeFromString<IndexV1>(indexGuardianStr)
val indexIzzyRes = Resource("src/commonTest/resources/izzy/index-v1.json")
assumeTrue(indexIzzyRes.exists())
val indexIzzyStr = indexIzzyRes.readText()
Json.decodeFromString<IndexV1>(indexIzzyStr)
val indexWindRes = Resource("src/commonTest/resources/wind/index-v1.json")
assumeTrue(indexWindRes.exists())
val indexWindStr = indexWindRes.readText()
Json.decodeFromString<IndexV1>(indexWindStr)
}
}

View File

@ -0,0 +1,33 @@
package org.fdroid.index.v2
import com.goncalossilva.resources.Resource
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.junit.Assume.assumeTrue
import kotlin.test.Test
internal class IndexV2Test {
@Test
fun testIndexV2() {
val entryRes = Resource("src/commonTest/resources/entry.json")
assumeTrue(entryRes.exists())
val entryStr = entryRes.readText()
val entry = Json.decodeFromString<EntryV2>(entryStr)
val indexRes = Resource("src/commonTest/resources/index-v2.json")
assumeTrue(indexRes.exists())
val indexStr = indexRes.readText()
val index = Json.decodeFromString<IndexV2>(indexStr)
}
@Test
fun testDiffV2() {
// val diff1Res = Resource("src/commonTest/resources/tmp.json")
// assumeTrue(diff1Res.exists())
// val diff1Str = diff1Res.readText()
// val diff1 = Json.decodeFromString<DiffV2>(diff1Str)
// println(diff1)
}
}

View File

@ -0,0 +1,28 @@
package org.fdroid.test
import kotlin.random.Random
public object DiffUtils {
/**
* Create a map diff by adding or removing keys. Note that this does not change keys.
*/
public fun <T> Map<String, T?>.randomDiff(factory: () -> T): Map<String, T?> = buildMap {
if (this@randomDiff.isNotEmpty()) {
// remove random keys
while (Random.nextBoolean()) put(this@randomDiff.keys.random(), null)
// Note: we don't replace random keys, because we can't easily diff inside T
}
// add random keys
while (Random.nextBoolean()) put(TestUtils.getRandomString(), factory())
}
public fun <T> Map<String, T>.applyDiff(diff: Map<String, T?>): Map<String, T> =
toMutableMap().apply {
diff.entries.forEach { (key, value) ->
if (value == null) remove(key)
else set(key, value)
}
}
}

View File

@ -0,0 +1,103 @@
package org.fdroid.test
import org.fdroid.index.v2.Author
import org.fdroid.index.v2.Donation
import org.fdroid.index.v2.FileV2
import org.fdroid.index.v2.LocalizedFileListV2
import org.fdroid.index.v2.MetadataV2
import org.fdroid.index.v2.Screenshots
import org.fdroid.test.TestRepoUtils.getRandomFileV2
import org.fdroid.test.TestRepoUtils.getRandomLocalizedFileV2
import org.fdroid.test.TestRepoUtils.getRandomLocalizedTextV2
import org.fdroid.test.TestUtils.getRandomList
import org.fdroid.test.TestUtils.getRandomString
import org.fdroid.test.TestUtils.orNull
import kotlin.random.Random
import kotlin.test.assertEquals
public object TestAppUtils {
public fun getRandomMetadataV2(): MetadataV2 = MetadataV2(
added = Random.nextLong(),
lastUpdated = Random.nextLong(),
name = getRandomLocalizedTextV2().orNull(),
summary = getRandomLocalizedTextV2().orNull(),
description = getRandomLocalizedTextV2().orNull(),
webSite = getRandomString().orNull(),
changelog = getRandomString().orNull(),
license = getRandomString().orNull(),
sourceCode = getRandomString().orNull(),
issueTracker = getRandomString().orNull(),
translation = getRandomString().orNull(),
preferredSigner = getRandomString().orNull(),
video = getRandomLocalizedTextV2().orNull(),
author = getRandomAuthor().orNull(),
donation = getRandomDonation().orNull(),
icon = getRandomLocalizedFileV2().orNull(),
featureGraphic = getRandomLocalizedFileV2().orNull(),
promoGraphic = getRandomLocalizedFileV2().orNull(),
tvBanner = getRandomLocalizedFileV2().orNull(),
categories = getRandomList { getRandomString() }.orNull()
?: emptyList(),
screenshots = getRandomScreenshots().orNull(),
)
public fun getRandomAuthor(): Author = Author(
name = getRandomString().orNull(),
email = getRandomString().orNull(),
website = getRandomString().orNull(),
phone = getRandomString().orNull(),
)
public fun getRandomDonation(): Donation = Donation(
url = getRandomString().orNull(),
liberapay = getRandomString().orNull(),
liberapayID = getRandomString().orNull(),
openCollective = getRandomString().orNull(),
bitcoin = getRandomString().orNull(),
litecoin = getRandomString().orNull(),
flattrID = getRandomString().orNull(),
)
public fun getRandomScreenshots(): Screenshots? = Screenshots(
phone = getRandomLocalizedFileListV2().orNull(),
sevenInch = getRandomLocalizedFileListV2().orNull(),
tenInch = getRandomLocalizedFileListV2().orNull(),
wear = getRandomLocalizedFileListV2().orNull(),
tv = getRandomLocalizedFileListV2().orNull(),
).takeIf { !it.isNull }
public fun getRandomLocalizedFileListV2(): Map<String, List<FileV2>> =
TestUtils.getRandomMap(Random.nextInt(1, 3)) {
getRandomString() to getRandomList(Random.nextInt(1, 7)) {
getRandomFileV2()
}
}
/**
* [Screenshots] include lists which can be ordered differently,
* so we need to ignore order when comparing them.
*/
public fun assertScreenshotsEqual(s1: Screenshots?, s2: Screenshots?) {
if (s1 != null && s2 != null) {
assertLocalizedFileListV2Equal(s1.phone, s2.phone)
assertLocalizedFileListV2Equal(s1.sevenInch, s2.sevenInch)
assertLocalizedFileListV2Equal(s1.tenInch, s2.tenInch)
assertLocalizedFileListV2Equal(s1.wear, s2.wear)
assertLocalizedFileListV2Equal(s1.tv, s2.tv)
} else {
assertEquals(s1, s2)
}
}
private fun assertLocalizedFileListV2Equal(l1: LocalizedFileListV2?, l2: LocalizedFileListV2?) {
if (l1 != null && l2 != null) {
l1.keys.forEach { key ->
assertEquals(l1[key]?.toSet(), l2[key]?.toSet())
}
} else {
assertEquals(l1, l2)
}
}
}

View File

@ -0,0 +1,69 @@
package org.fdroid.test
import org.fdroid.index.v2.AntiFeatureV2
import org.fdroid.index.v2.CategoryV2
import org.fdroid.index.v2.FileV2
import org.fdroid.index.v2.LocalizedTextV2
import org.fdroid.index.v2.MirrorV2
import org.fdroid.index.v2.ReleaseChannelV2
import org.fdroid.index.v2.RepoV2
import org.fdroid.test.TestUtils.getRandomList
import org.fdroid.test.TestUtils.getRandomString
import org.fdroid.test.TestUtils.orNull
import kotlin.random.Random
public object TestRepoUtils {
public fun getRandomMirror(): MirrorV2 = MirrorV2(
url = getRandomString(),
location = getRandomString().orNull()
)
public fun getRandomLocalizedTextV2(size: Int = Random.nextInt(0, 23)): LocalizedTextV2 =
buildMap {
repeat(size) {
put(getRandomString(4), getRandomString())
}
}
public fun getRandomFileV2(sha256Nullable: Boolean = true): FileV2 = FileV2(
name = getRandomString(),
sha256 = getRandomString(64).also { if (sha256Nullable) orNull() },
size = Random.nextLong(-1, Long.MAX_VALUE)
)
public fun getRandomLocalizedFileV2(): Map<String, FileV2> =
TestUtils.getRandomMap(Random.nextInt(1, 8)) {
getRandomString(4) to getRandomFileV2()
}
public fun getRandomRepo(): RepoV2 = RepoV2(
name = getRandomString(),
icon = getRandomFileV2(),
address = getRandomString(),
description = getRandomLocalizedTextV2(),
mirrors = getRandomList { getRandomMirror() },
timestamp = System.currentTimeMillis(),
antiFeatures = TestUtils.getRandomMap {
getRandomString() to AntiFeatureV2(
icon = getRandomFileV2(),
name = getRandomLocalizedTextV2(),
description = getRandomLocalizedTextV2(),
)
},
categories = TestUtils.getRandomMap {
getRandomString() to CategoryV2(
icon = getRandomFileV2(),
name = getRandomLocalizedTextV2(),
description = getRandomLocalizedTextV2(),
)
},
releaseChannels = TestUtils.getRandomMap {
getRandomString() to ReleaseChannelV2(
name = getRandomLocalizedTextV2(),
description = getRandomLocalizedTextV2(),
)
},
)
}

View File

@ -0,0 +1,37 @@
package org.fdroid.test
import kotlin.random.Random
public object TestUtils {
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
public fun getRandomString(length: Int = Random.nextInt(1, 128)): String = (1..length)
.map { Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
public fun <T> getRandomList(
size: Int = Random.nextInt(0, 23),
factory: () -> T,
): List<T> = if (size == 0) emptyList() else buildList {
repeat(size) {
add(factory())
}
}
public fun <A, B> getRandomMap(
size: Int = Random.nextInt(0, 23),
factory: () -> Pair<A, B>,
): Map<A, B> = if (size == 0) emptyMap() else buildMap {
repeat(size) {
val pair = factory()
put(pair.first, pair.second)
}
}
public fun <T> T.orNull(): T? {
return if (Random.nextBoolean()) null else this
}
}

View File

@ -0,0 +1,53 @@
package org.fdroid.test
import org.fdroid.index.v2.FeatureV2
import org.fdroid.index.v2.FileV1
import org.fdroid.index.v2.ManifestV2
import org.fdroid.index.v2.PackageVersionV2
import org.fdroid.index.v2.PermissionV2
import org.fdroid.index.v2.SignatureV2
import org.fdroid.index.v2.UsesSdkV2
import org.fdroid.test.TestRepoUtils.getRandomFileV2
import org.fdroid.test.TestRepoUtils.getRandomLocalizedTextV2
import org.fdroid.test.TestUtils.getRandomList
import org.fdroid.test.TestUtils.getRandomMap
import org.fdroid.test.TestUtils.getRandomString
import org.fdroid.test.TestUtils.orNull
import kotlin.random.Random
internal object TestVersionUtils {
fun getRandomPackageVersionV2() = PackageVersionV2(
added = Random.nextLong(),
file = getRandomFileV2(false).let {
FileV1(it.name, it.sha256!!, it.size)
},
src = getRandomFileV2().orNull(),
manifest = getRandomManifestV2(),
releaseChannels = getRandomList { getRandomString() },
antiFeatures = getRandomMap { getRandomString() to getRandomLocalizedTextV2() },
whatsNew = getRandomLocalizedTextV2(),
)
fun getRandomManifestV2() = ManifestV2(
versionName = getRandomString(),
versionCode = Random.nextLong(),
usesSdk = UsesSdkV2(
minSdkVersion = Random.nextInt(),
targetSdkVersion = Random.nextInt(),
),
maxSdkVersion = Random.nextInt().orNull(),
signer = SignatureV2(getRandomList(Random.nextInt(1, 3)) {
getRandomString(64)
}).orNull(),
usesPermission = getRandomList {
PermissionV2(getRandomString(), Random.nextInt().orNull())
},
usesPermissionSdk23 = getRandomList {
PermissionV2(getRandomString(), Random.nextInt().orNull())
},
nativeCode = getRandomList(Random.nextInt(0, 4)) { getRandomString() },
features = getRandomList { FeatureV2(getRandomString()) },
)
}

View File

@ -1,2 +1,3 @@
include ':app'
include ':download'
include ':index'