diff --git a/network/build.gradle.kts b/network/build.gradle.kts index 7959cb38cda..fce0b545667 100644 --- a/network/build.gradle.kts +++ b/network/build.gradle.kts @@ -111,3 +111,37 @@ android { it.enabled = false } } + +tasks.register("generateNewApiVersion") { + group = "custom" + description = "Generates a new API version by calling the generate_new_api_version.sh script" + + val previousApiVersion = project.findProperty("previousApiVersion") as String? ?: "" + val currentApiVersion = project.findProperty("currentApiVersion") as String? ?: "" + val newApiVersion = project.findProperty("newApiVersion") as String? ?: "" + + doFirst { + if (previousApiVersion == "" || currentApiVersion == "" || newApiVersion == "") { + println( + "Usage: ./gradlew :network:generateNewApiVersion " + + "-PpreviousApiVersion= -PcurrentApiVersion= -PnewApiVersion=" + ) + println( + "Example: ./gradlew :network:generateNewApiVersion " + + "-PpreviousApiVersion=5 -PcurrentApiVersion=6 -PnewApiVersion=7" + ) + throw IllegalArgumentException( + "All parameters (previousApiVersion, " + + "currentApiVersion, newApiVersion) must be provided." + ) + } + } + + commandLine( + "bash", + "./../scripts/generate_new_api_version.sh", + previousApiVersion, + currentApiVersion, + newApiVersion + ) +} diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt index 4ddf1328f87..ac9a4767514 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt @@ -15,18 +15,23 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ - -@file:Suppress("MagicNumber") - package com.wire.kalium.network import com.wire.kalium.network.api.unbound.configuration.ApiVersionDTO import com.wire.kalium.network.api.unbound.configuration.ServerConfigDTO import com.wire.kalium.network.api.unbound.versioning.VersionInfoDTO +// They are not truly constants as set is not a primitive type, yet are treated as one in this context +@Suppress("MagicNumber") val SupportedApiVersions = setOf(0, 1, 2, 4, 5) + +// They are not truly constants as set is not a primitive type, yet are treated as one in this context +@Suppress("MagicNumber") val DevelopmentApiVersions = setOf(6, 7) +// You can use scripts/generate_new_api_version.sh or gradle task network:generateNewApiVersion to +// bump API version and generate all needed classes + interface BackendMetaDataUtil { fun calculateApiVersion( versionInfoDTO: VersionInfoDTO, @@ -45,8 +50,13 @@ object BackendMetaDataUtilImpl : BackendMetaDataUtil { developmentApiEnabled: Boolean ): ServerConfigDTO.MetaData { - val allSupportedApiVersions = if (developmentApiEnabled) supportedApiVersions + developmentApiVersions else supportedApiVersions - val apiVersion = commonApiVersion(versionInfoDTO, allSupportedApiVersions, developmentApiEnabled)?.let { maxCommonVersion -> + val allSupportedApiVersions = + if (developmentApiEnabled) supportedApiVersions + developmentApiVersions else supportedApiVersions + val apiVersion = commonApiVersion( + versionInfoDTO, + allSupportedApiVersions, + developmentApiEnabled + )?.let { maxCommonVersion -> ApiVersionDTO.Valid(maxCommonVersion) } ?: run { handleNoCommonVersion(versionInfoDTO.supported, allSupportedApiVersions) @@ -59,16 +69,24 @@ object BackendMetaDataUtilImpl : BackendMetaDataUtil { ) } - private fun commonApiVersion(serverVersion: VersionInfoDTO, supportedApiVersions: Set, developmentAPIEnabled: Boolean): Int? { - val serverSupportedApiVersions: List = if (developmentAPIEnabled && serverVersion.developmentSupported != null) { - serverVersion.supported + serverVersion.developmentSupported!! - } else { - serverVersion.supported - } + private fun commonApiVersion( + serverVersion: VersionInfoDTO, + supportedApiVersions: Set, + developmentAPIEnabled: Boolean + ): Int? { + val serverSupportedApiVersions: List = + if (developmentAPIEnabled && serverVersion.developmentSupported != null) { + serverVersion.supported + serverVersion.developmentSupported!! + } else { + serverVersion.supported + } return serverSupportedApiVersions.intersect(supportedApiVersions).maxOrNull() } - private fun handleNoCommonVersion(serverVersion: List, appVersion: Set): ApiVersionDTO.Invalid { + private fun handleNoCommonVersion( + serverVersion: List, + appVersion: Set + ): ApiVersionDTO.Invalid { return serverVersion.maxOrNull()?.let { maxBEVersion -> appVersion.maxOrNull()?.let { maxAppVersion -> if (maxBEVersion > maxAppVersion) ApiVersionDTO.Invalid.New diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/AuthenticatedNetworkContainer.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/AuthenticatedNetworkContainer.kt index 6eb175d3280..ccd602dde35 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/AuthenticatedNetworkContainer.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/AuthenticatedNetworkContainer.kt @@ -198,6 +198,8 @@ interface AuthenticatedNetworkContainer { kaliumLogger ) + // You can use scripts/generate_new_api_version.sh or gradle task network:generateNewApiVersion to + // bump API version and generate all needed classes else -> error("Unsupported version: $version") } } diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt index 194f9775d34..f647f9dcff3 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt @@ -129,6 +129,8 @@ interface UnauthenticatedNetworkContainer { developmentApiEnabled = developmentApiEnabled ) + // You can use scripts/generate_new_api_version.sh or gradle task network:generateNewApiVersion to + // bump API version and generate all needed classes else -> error("Unsupported version: ${serverConfigDTO.metaData.commonApiVersion.version}") } } diff --git a/scripts/generate_new_api_version.sh b/scripts/generate_new_api_version.sh new file mode 100755 index 00000000000..5b2a6c2875a --- /dev/null +++ b/scripts/generate_new_api_version.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Makes all paths relative to project root so it can be run from anywhere +parent_path=$( + cd "$(dirname "${BASH_SOURCE[0]}")" || exit + pwd -P +) +cd "$parent_path/.." || exit + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 5 6 7" + exit 1 +fi + +# Validate that all parameters are integers +if ! [[ "$1" =~ ^[0-9]+$ && "$2" =~ ^[0-9]+$ && "$3" =~ ^[0-9]+$ ]]; then + echo "Error: All parameters must be integers." + exit 1 +fi + +# sometimes we have lower case (i.e. imports) sometimes upper case (i.e. class names) +previousApiVersionLower="v$1" +currentApiVersionLower="v$2" +newApiVersionLower="v$3" + +previousApiVersionUpper="V$1" +currentApiVersionUpper="V$2" +newApiVersionUpper="V$3" + +copy_api_files() { + local source_dir=$1 + local target_dir=$2 + + mkdir -p "$target_dir" + + for file in "$source_dir"/*.kt; do + if [[ -f "$file" ]]; then + content=$(cat "$file") + # package name changed from previous to current version + new_content=$(echo "$content" | sed "s/com\.wire\.kalium\.network\.api\.$currentApiVersionLower\./com.wire.kalium.network.api.$newApiVersionLower./g") + # class name changed from previous to current version + new_content=$(echo "$new_content" | sed "s/\(class .*\)$currentApiVersionUpper/\1$newApiVersionUpper/g") + # imports changed from previous to current version + new_content=$(echo "$new_content" | sed "s/com\.wire\.kalium\.network\.api\.$previousApiVersionLower\./com.wire.kalium.network.api.$currentApiVersionLower./g") + # imports class names changed from previous to current version + new_content=$(echo "$new_content" | sed "s/\(import com\.wire\.kalium\.network\.api\.$currentApiVersionLower\.\)\(.*\)$previousApiVersionUpper/\1\2$currentApiVersionUpper/g") + # class names in extension definition changed from previous to current version + new_content=$(echo "$new_content" | sed "s/\(: \)\(.*\)$previousApiVersionUpper/\1\2$currentApiVersionUpper/g") + # class names in inheritance changed from previous to current version + new_content=$(echo "$new_content" | sed "s/\(: \)\(.*\)$previousApiVersionUpper/\1\2$currentApiVersionUpper/g") + # Make class definitions empty inside {} + new_content=$(echo "$new_content" | perl -0777 -pe "s|({[\W\w]*\})|\2|g") + # Remove all private val or val + new_content=$(echo "$new_content" | sed "s/\(private \)*val //g") + # New file name with newApiVersion + new_filename=$(basename "$file" | sed "s/$currentApiVersionUpper/$newApiVersionUpper/g") + echo "$new_content" >"$target_dir/$new_filename" + echo "Created $new_filename" + fi + done +} + +SOURCE_DIR_UNAUTH="network/src/commonMain/kotlin/com/wire/kalium/network/api/$currentApiVersionLower/unauthenticated" +TARGET_DIR_UNAUTH="network/src/commonMain/kotlin/com/wire/kalium/network/api/$newApiVersionLower/unauthenticated" + +SOURCE_DIR_AUTH="network/src/commonMain/kotlin/com/wire/kalium/network/api/$currentApiVersionLower/authenticated" +TARGET_DIR_AUTH="network/src/commonMain/kotlin/com/wire/kalium/network/api/$newApiVersionLower/authenticated" + +copy_api_files "$SOURCE_DIR_UNAUTH" "$TARGET_DIR_UNAUTH" +copy_api_files "$SOURCE_DIR_AUTH" "$TARGET_DIR_AUTH" + +copy_container_files() { + local source_file="$1" + local target_file="${source_file//$currentApiVersionUpper/$newApiVersionUpper}" + target_file="${target_file//$currentApiVersionLower/$newApiVersionLower}" + if [[ -f "$source_file" ]]; then + mkdir -p "$(dirname "$target_file")" + + # Read the content of the file + content=$(cat "$source_file") + + # Perform replacements on the content + new_content="${content//$currentApiVersionUpper/$newApiVersionUpper}" + new_content="${new_content//$currentApiVersionLower/$newApiVersionLower}" + + # Save the modified content back to the target file + echo "$new_content" >"$target_file" + + echo "Created $target_file" + else + exit 1 + fi +} + +copy_container_files "network/src/commonMain/kotlin/com/wire/kalium/network/api/$currentApiVersionLower/authenticated/networkContainer/AuthenticatedNetworkContainer$currentApiVersionUpper.kt" +copy_container_files "network/src/commonMain/kotlin/com/wire/kalium/network/api/$currentApiVersionLower/unauthenticated/networkContainer/UnauthenticatedNetworkContainer$currentApiVersionUpper.kt" + +echo + +# Add the new API version to DevelopmentApiVersions if it does not already contain it +if ! grep -q "$3" network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt; then + sed -i '' "s/\(val DevelopmentApiVersions = setOf(.*\))/\1, $3)/" network/src/commonMain/kotlin/com/wire/kalium/network/BackendMetaDataUtil.kt + echo "Added $3 to DevelopmentApiVersions in BackendMetaDataUtil.kt" +else + echo "$3 is already in DevelopmentApiVersions in BackendMetaDataUtil.kt" +fi + +echo "!!!!!!!" +echo "You must add the new API version to the list of supported API versions in the AuthenticatedNetworkContainer.create() and UnauthenticatedNetworkContainer.create() methods." +echo "Check the generated files for unused parameters." +echo "!!!!!!!"