diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 00000000..02b915b8
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WORKSPACE b/WORKSPACE
index 202256f0..ffdd6388 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -27,7 +27,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "grab_bazel_common",
- commit = "120019c5290cceda3c795d9ddb2a3253b9b32b3e",
+ commit = "4a18937b1a30f11996742f34587d50a5aa1f04f4",
remote = "https://github.com/grab/grab-bazel-common.git",
)
@@ -71,42 +71,657 @@ load("@rules_jvm_external//:defs.bzl", "maven_install")
load("@rules_jvm_external//:specs.bzl", "maven")
maven_install(
+ name = "flavor1free_debug_android_test_maven",
+ artifacts = [
+ "androidx.annotation:annotation-experimental:1.3.0",
+ "androidx.annotation:annotation-jvm:1.6.0",
+ "androidx.annotation:annotation:1.6.0",
+ "androidx.arch.core:core-common:2.2.0",
+ "androidx.arch.core:core-runtime:2.1.0",
+ "androidx.collection:collection:1.1.0",
+ "androidx.concurrent:concurrent-futures:1.1.0",
+ "androidx.core:core-ktx:1.2.0",
+ "androidx.core:core:1.10.1",
+ "androidx.lifecycle:lifecycle-common:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata-core:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata:2.6.1",
+ "androidx.lifecycle:lifecycle-process:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime:2.6.1",
+ "androidx.lifecycle:lifecycle-service:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel:2.6.1",
+ "androidx.savedstate:savedstate-ktx:1.2.1",
+ "androidx.savedstate:savedstate:1.2.1",
+ "androidx.startup:startup-runtime:1.1.1",
+ "androidx.test.espresso:espresso-core:3.5.1",
+ "androidx.test.espresso:espresso-idling-resource:3.5.1",
+ "androidx.test.ext:junit:1.1.5",
+ "androidx.test.services:storage:1.4.2",
+ "androidx.test:annotation:1.0.1",
+ "androidx.test:core:1.5.0",
+ "androidx.test:monitor:1.6.1",
+ "androidx.test:runner:1.5.2",
+ "androidx.tracing:tracing:1.0.0",
+ "androidx.versionedparcelable:versionedparcelable:1.1.1",
+ "com.google.code.findbugs:jsr305:2.0.2",
+ "com.google.guava:listenablefuture:1.0",
+ "com.squareup:javawriter:2.1.1",
+ "javax.inject:javax.inject:1",
+ "junit:junit:4.13.2",
+ "org.hamcrest:hamcrest-core:1.3",
+ "org.hamcrest:hamcrest-integration:1.3",
+ "org.hamcrest:hamcrest-library:1.3",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4",
+ ],
+ excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
+ fail_on_missing_checksum = False,
+ jetify = True,
+ jetify_include_list = [
+ "androidx.annotation:annotation",
+ "androidx.annotation:annotation-experimental",
+ "androidx.annotation:annotation-jvm",
+ "androidx.arch.core:core-common",
+ "androidx.arch.core:core-runtime",
+ "androidx.collection:collection",
+ "androidx.concurrent:concurrent-futures",
+ "androidx.core:core",
+ "androidx.core:core-ktx",
+ "androidx.lifecycle:lifecycle-common",
+ "androidx.lifecycle:lifecycle-livedata",
+ "androidx.lifecycle:lifecycle-livedata-core",
+ "androidx.lifecycle:lifecycle-process",
+ "androidx.lifecycle:lifecycle-runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx",
+ "androidx.lifecycle:lifecycle-service",
+ "androidx.lifecycle:lifecycle-viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+ "androidx.savedstate:savedstate",
+ "androidx.savedstate:savedstate-ktx",
+ "androidx.startup:startup-runtime",
+ "androidx.test.espresso:espresso-core",
+ "androidx.test.espresso:espresso-idling-resource",
+ "androidx.test.ext:junit",
+ "androidx.test.services:storage",
+ "androidx.test:annotation",
+ "androidx.test:core",
+ "androidx.test:monitor",
+ "androidx.test:runner",
+ "androidx.tracing:tracing",
+ "androidx.versionedparcelable:versionedparcelable",
+ "com.android.support:cardview-v7",
+ "com.google.code.findbugs:jsr305",
+ "com.google.guava:listenablefuture",
+ "com.squareup:javawriter",
+ "javax.inject:javax.inject",
+ "junit:junit",
+ "org.hamcrest:hamcrest-core",
+ "org.hamcrest:hamcrest-integration",
+ "org.hamcrest:hamcrest-library",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
+ ],
+ override_targets = {
+ "androidx.annotation:annotation": "@maven//:androidx_annotation_annotation",
+ "androidx.annotation:annotation-experimental": "@maven//:androidx_annotation_annotation_experimental",
+ "androidx.arch.core:core-common": "@maven//:androidx_arch_core_core_common",
+ "androidx.arch.core:core-runtime": "@maven//:androidx_arch_core_core_runtime",
+ "androidx.collection:collection": "@maven//:androidx_collection_collection",
+ "androidx.core:core": "@maven//:androidx_core_core",
+ "androidx.core:core-ktx": "@maven//:androidx_core_core_ktx",
+ "androidx.lifecycle:lifecycle-common": "@maven//:androidx_lifecycle_lifecycle_common",
+ "androidx.lifecycle:lifecycle-livedata": "@maven//:androidx_lifecycle_lifecycle_livedata",
+ "androidx.lifecycle:lifecycle-livedata-core": "@maven//:androidx_lifecycle_lifecycle_livedata_core",
+ "androidx.lifecycle:lifecycle-process": "@maven//:androidx_lifecycle_lifecycle_process",
+ "androidx.lifecycle:lifecycle-runtime": "@maven//:androidx_lifecycle_lifecycle_runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx": "@maven//:androidx_lifecycle_lifecycle_runtime_ktx",
+ "androidx.lifecycle:lifecycle-service": "@maven//:androidx_lifecycle_lifecycle_service",
+ "androidx.lifecycle:lifecycle-viewmodel": "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx": "@maven//:androidx_lifecycle_lifecycle_viewmodel_ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate": "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+ "androidx.savedstate:savedstate": "@maven//:androidx_savedstate_savedstate",
+ "androidx.savedstate:savedstate-ktx": "@maven//:androidx_savedstate_savedstate_ktx",
+ "androidx.startup:startup-runtime": "@maven//:androidx_startup_startup_runtime",
+ "androidx.versionedparcelable:versionedparcelable": "@maven//:androidx_versionedparcelable_versionedparcelable",
+ "com.google.code.findbugs:jsr305": "@maven//:com_google_code_findbugs_jsr305",
+ "com.google.guava:listenablefuture": "@maven//:com_google_guava_listenablefuture",
+ "javax.inject:javax.inject": "@maven//:javax_inject_javax_inject",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core",
+ },
+ repositories = [
+ "https://dl.google.com/dl/android/maven2/",
+ "https://repo.maven.apache.org/maven2/",
+ ],
+ resolve_timeout = 1000,
+ version_conflict_policy = "pinned",
+)
+
+maven_install(
+ name = "flavor1paid_debug_android_test_maven",
+ artifacts = [
+ "androidx.annotation:annotation-experimental:1.3.0",
+ "androidx.annotation:annotation-jvm:1.6.0",
+ "androidx.annotation:annotation:1.6.0",
+ "androidx.arch.core:core-common:2.2.0",
+ "androidx.arch.core:core-runtime:2.1.0",
+ "androidx.collection:collection:1.1.0",
+ "androidx.concurrent:concurrent-futures:1.1.0",
+ "androidx.core:core-ktx:1.2.0",
+ "androidx.core:core:1.10.1",
+ "androidx.lifecycle:lifecycle-common:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata-core:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata:2.6.1",
+ "androidx.lifecycle:lifecycle-process:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime:2.6.1",
+ "androidx.lifecycle:lifecycle-service:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel:2.6.1",
+ "androidx.savedstate:savedstate-ktx:1.2.1",
+ "androidx.savedstate:savedstate:1.2.1",
+ "androidx.startup:startup-runtime:1.1.1",
+ "androidx.test.espresso:espresso-core:3.5.1",
+ "androidx.test.espresso:espresso-idling-resource:3.5.1",
+ "androidx.test.ext:junit:1.1.5",
+ "androidx.test.services:storage:1.4.2",
+ "androidx.test:annotation:1.0.1",
+ "androidx.test:core:1.5.0",
+ "androidx.test:monitor:1.6.1",
+ "androidx.test:runner:1.5.2",
+ "androidx.tracing:tracing:1.0.0",
+ "androidx.versionedparcelable:versionedparcelable:1.1.1",
+ "com.google.code.findbugs:jsr305:2.0.2",
+ "com.google.guava:listenablefuture:1.0",
+ "com.squareup:javawriter:2.1.1",
+ "javax.inject:javax.inject:1",
+ "junit:junit:4.13.2",
+ "org.hamcrest:hamcrest-core:1.3",
+ "org.hamcrest:hamcrest-integration:1.3",
+ "org.hamcrest:hamcrest-library:1.3",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4",
+ ],
+ excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
+ fail_on_missing_checksum = False,
+ jetify = True,
+ jetify_include_list = [
+ "androidx.annotation:annotation",
+ "androidx.annotation:annotation-experimental",
+ "androidx.annotation:annotation-jvm",
+ "androidx.arch.core:core-common",
+ "androidx.arch.core:core-runtime",
+ "androidx.collection:collection",
+ "androidx.concurrent:concurrent-futures",
+ "androidx.core:core",
+ "androidx.core:core-ktx",
+ "androidx.lifecycle:lifecycle-common",
+ "androidx.lifecycle:lifecycle-livedata",
+ "androidx.lifecycle:lifecycle-livedata-core",
+ "androidx.lifecycle:lifecycle-process",
+ "androidx.lifecycle:lifecycle-runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx",
+ "androidx.lifecycle:lifecycle-service",
+ "androidx.lifecycle:lifecycle-viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+ "androidx.savedstate:savedstate",
+ "androidx.savedstate:savedstate-ktx",
+ "androidx.startup:startup-runtime",
+ "androidx.test.espresso:espresso-core",
+ "androidx.test.espresso:espresso-idling-resource",
+ "androidx.test.ext:junit",
+ "androidx.test.services:storage",
+ "androidx.test:annotation",
+ "androidx.test:core",
+ "androidx.test:monitor",
+ "androidx.test:runner",
+ "androidx.tracing:tracing",
+ "androidx.versionedparcelable:versionedparcelable",
+ "com.android.support:cardview-v7",
+ "com.google.code.findbugs:jsr305",
+ "com.google.guava:listenablefuture",
+ "com.squareup:javawriter",
+ "javax.inject:javax.inject",
+ "junit:junit",
+ "org.hamcrest:hamcrest-core",
+ "org.hamcrest:hamcrest-integration",
+ "org.hamcrest:hamcrest-library",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
+ ],
+ override_targets = {
+ "androidx.annotation:annotation": "@maven//:androidx_annotation_annotation",
+ "androidx.annotation:annotation-experimental": "@maven//:androidx_annotation_annotation_experimental",
+ "androidx.arch.core:core-common": "@maven//:androidx_arch_core_core_common",
+ "androidx.arch.core:core-runtime": "@maven//:androidx_arch_core_core_runtime",
+ "androidx.collection:collection": "@maven//:androidx_collection_collection",
+ "androidx.core:core": "@maven//:androidx_core_core",
+ "androidx.core:core-ktx": "@maven//:androidx_core_core_ktx",
+ "androidx.lifecycle:lifecycle-common": "@maven//:androidx_lifecycle_lifecycle_common",
+ "androidx.lifecycle:lifecycle-livedata": "@maven//:androidx_lifecycle_lifecycle_livedata",
+ "androidx.lifecycle:lifecycle-livedata-core": "@maven//:androidx_lifecycle_lifecycle_livedata_core",
+ "androidx.lifecycle:lifecycle-process": "@maven//:androidx_lifecycle_lifecycle_process",
+ "androidx.lifecycle:lifecycle-runtime": "@maven//:androidx_lifecycle_lifecycle_runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx": "@maven//:androidx_lifecycle_lifecycle_runtime_ktx",
+ "androidx.lifecycle:lifecycle-service": "@maven//:androidx_lifecycle_lifecycle_service",
+ "androidx.lifecycle:lifecycle-viewmodel": "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx": "@maven//:androidx_lifecycle_lifecycle_viewmodel_ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate": "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+ "androidx.savedstate:savedstate": "@maven//:androidx_savedstate_savedstate",
+ "androidx.savedstate:savedstate-ktx": "@maven//:androidx_savedstate_savedstate_ktx",
+ "androidx.startup:startup-runtime": "@maven//:androidx_startup_startup_runtime",
+ "androidx.versionedparcelable:versionedparcelable": "@maven//:androidx_versionedparcelable_versionedparcelable",
+ "com.google.code.findbugs:jsr305": "@maven//:com_google_code_findbugs_jsr305",
+ "com.google.guava:listenablefuture": "@maven//:com_google_guava_listenablefuture",
+ "javax.inject:javax.inject": "@maven//:javax_inject_javax_inject",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core",
+ },
+ repositories = [
+ "https://dl.google.com/dl/android/maven2/",
+ "https://repo.maven.apache.org/maven2/",
+ ],
+ resolve_timeout = 1000,
+ version_conflict_policy = "pinned",
+)
+
+maven_install(
+ name = "flavor2free_debug_android_test_maven",
+ artifacts = [
+ "androidx.annotation:annotation-experimental:1.3.0",
+ "androidx.annotation:annotation-jvm:1.6.0",
+ "androidx.annotation:annotation:1.6.0",
+ "androidx.arch.core:core-common:2.2.0",
+ "androidx.arch.core:core-runtime:2.1.0",
+ "androidx.collection:collection:1.1.0",
+ "androidx.concurrent:concurrent-futures:1.1.0",
+ "androidx.core:core-ktx:1.2.0",
+ "androidx.core:core:1.10.1",
+ "androidx.lifecycle:lifecycle-common:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata-core:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata:2.6.1",
+ "androidx.lifecycle:lifecycle-process:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime:2.6.1",
+ "androidx.lifecycle:lifecycle-service:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel:2.6.1",
+ "androidx.savedstate:savedstate-ktx:1.2.1",
+ "androidx.savedstate:savedstate:1.2.1",
+ "androidx.startup:startup-runtime:1.1.1",
+ "androidx.test.espresso:espresso-core:3.5.1",
+ "androidx.test.espresso:espresso-idling-resource:3.5.1",
+ "androidx.test.ext:junit:1.1.5",
+ "androidx.test.services:storage:1.4.2",
+ "androidx.test:annotation:1.0.1",
+ "androidx.test:core:1.5.0",
+ "androidx.test:monitor:1.6.1",
+ "androidx.test:runner:1.5.2",
+ "androidx.tracing:tracing:1.0.0",
+ "androidx.versionedparcelable:versionedparcelable:1.1.1",
+ "com.google.code.findbugs:jsr305:2.0.2",
+ "com.google.guava:listenablefuture:1.0",
+ "com.squareup:javawriter:2.1.1",
+ "javax.inject:javax.inject:1",
+ "junit:junit:4.13.2",
+ "org.hamcrest:hamcrest-core:1.3",
+ "org.hamcrest:hamcrest-integration:1.3",
+ "org.hamcrest:hamcrest-library:1.3",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4",
+ ],
+ excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
+ fail_on_missing_checksum = False,
+ jetify = True,
+ jetify_include_list = [
+ "androidx.annotation:annotation",
+ "androidx.annotation:annotation-experimental",
+ "androidx.annotation:annotation-jvm",
+ "androidx.arch.core:core-common",
+ "androidx.arch.core:core-runtime",
+ "androidx.collection:collection",
+ "androidx.concurrent:concurrent-futures",
+ "androidx.core:core",
+ "androidx.core:core-ktx",
+ "androidx.lifecycle:lifecycle-common",
+ "androidx.lifecycle:lifecycle-livedata",
+ "androidx.lifecycle:lifecycle-livedata-core",
+ "androidx.lifecycle:lifecycle-process",
+ "androidx.lifecycle:lifecycle-runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx",
+ "androidx.lifecycle:lifecycle-service",
+ "androidx.lifecycle:lifecycle-viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+ "androidx.savedstate:savedstate",
+ "androidx.savedstate:savedstate-ktx",
+ "androidx.startup:startup-runtime",
+ "androidx.test.espresso:espresso-core",
+ "androidx.test.espresso:espresso-idling-resource",
+ "androidx.test.ext:junit",
+ "androidx.test.services:storage",
+ "androidx.test:annotation",
+ "androidx.test:core",
+ "androidx.test:monitor",
+ "androidx.test:runner",
+ "androidx.tracing:tracing",
+ "androidx.versionedparcelable:versionedparcelable",
+ "com.android.support:cardview-v7",
+ "com.google.code.findbugs:jsr305",
+ "com.google.guava:listenablefuture",
+ "com.squareup:javawriter",
+ "javax.inject:javax.inject",
+ "junit:junit",
+ "org.hamcrest:hamcrest-core",
+ "org.hamcrest:hamcrest-integration",
+ "org.hamcrest:hamcrest-library",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
+ ],
+ override_targets = {
+ "androidx.annotation:annotation": "@maven//:androidx_annotation_annotation",
+ "androidx.annotation:annotation-experimental": "@maven//:androidx_annotation_annotation_experimental",
+ "androidx.arch.core:core-common": "@maven//:androidx_arch_core_core_common",
+ "androidx.arch.core:core-runtime": "@maven//:androidx_arch_core_core_runtime",
+ "androidx.collection:collection": "@maven//:androidx_collection_collection",
+ "androidx.core:core": "@maven//:androidx_core_core",
+ "androidx.core:core-ktx": "@maven//:androidx_core_core_ktx",
+ "androidx.lifecycle:lifecycle-common": "@maven//:androidx_lifecycle_lifecycle_common",
+ "androidx.lifecycle:lifecycle-livedata": "@maven//:androidx_lifecycle_lifecycle_livedata",
+ "androidx.lifecycle:lifecycle-livedata-core": "@maven//:androidx_lifecycle_lifecycle_livedata_core",
+ "androidx.lifecycle:lifecycle-process": "@maven//:androidx_lifecycle_lifecycle_process",
+ "androidx.lifecycle:lifecycle-runtime": "@maven//:androidx_lifecycle_lifecycle_runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx": "@maven//:androidx_lifecycle_lifecycle_runtime_ktx",
+ "androidx.lifecycle:lifecycle-service": "@maven//:androidx_lifecycle_lifecycle_service",
+ "androidx.lifecycle:lifecycle-viewmodel": "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx": "@maven//:androidx_lifecycle_lifecycle_viewmodel_ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate": "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+ "androidx.savedstate:savedstate": "@maven//:androidx_savedstate_savedstate",
+ "androidx.savedstate:savedstate-ktx": "@maven//:androidx_savedstate_savedstate_ktx",
+ "androidx.startup:startup-runtime": "@maven//:androidx_startup_startup_runtime",
+ "androidx.versionedparcelable:versionedparcelable": "@maven//:androidx_versionedparcelable_versionedparcelable",
+ "com.google.code.findbugs:jsr305": "@maven//:com_google_code_findbugs_jsr305",
+ "com.google.guava:listenablefuture": "@maven//:com_google_guava_listenablefuture",
+ "javax.inject:javax.inject": "@maven//:javax_inject_javax_inject",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core",
+ },
+ repositories = [
+ "https://dl.google.com/dl/android/maven2/",
+ "https://repo.maven.apache.org/maven2/",
+ ],
+ resolve_timeout = 1000,
+ version_conflict_policy = "pinned",
+)
+
+maven_install(
+ name = "flavor2paid_debug_android_test_maven",
+ artifacts = [
+ "androidx.annotation:annotation-experimental:1.3.0",
+ "androidx.annotation:annotation-jvm:1.6.0",
+ "androidx.annotation:annotation:1.6.0",
+ "androidx.arch.core:core-common:2.2.0",
+ "androidx.arch.core:core-runtime:2.1.0",
+ "androidx.collection:collection:1.1.0",
+ "androidx.concurrent:concurrent-futures:1.1.0",
+ "androidx.core:core-ktx:1.2.0",
+ "androidx.core:core:1.10.1",
+ "androidx.lifecycle:lifecycle-common:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata-core:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata:2.6.1",
+ "androidx.lifecycle:lifecycle-process:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime:2.6.1",
+ "androidx.lifecycle:lifecycle-service:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel:2.6.1",
+ "androidx.savedstate:savedstate-ktx:1.2.1",
+ "androidx.savedstate:savedstate:1.2.1",
+ "androidx.startup:startup-runtime:1.1.1",
+ "androidx.test.espresso:espresso-core:3.5.1",
+ "androidx.test.espresso:espresso-idling-resource:3.5.1",
+ "androidx.test.ext:junit:1.1.5",
+ "androidx.test.services:storage:1.4.2",
+ "androidx.test:annotation:1.0.1",
+ "androidx.test:core:1.5.0",
+ "androidx.test:monitor:1.6.1",
+ "androidx.test:runner:1.5.2",
+ "androidx.tracing:tracing:1.0.0",
+ "androidx.versionedparcelable:versionedparcelable:1.1.1",
+ "com.google.code.findbugs:jsr305:2.0.2",
+ "com.google.guava:listenablefuture:1.0",
+ "com.squareup:javawriter:2.1.1",
+ "javax.inject:javax.inject:1",
+ "junit:junit:4.13.2",
+ "org.hamcrest:hamcrest-core:1.3",
+ "org.hamcrest:hamcrest-integration:1.3",
+ "org.hamcrest:hamcrest-library:1.3",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4",
+ ],
+ excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
+ fail_on_missing_checksum = False,
+ jetify = True,
+ jetify_include_list = [
+ "androidx.annotation:annotation",
+ "androidx.annotation:annotation-experimental",
+ "androidx.annotation:annotation-jvm",
+ "androidx.arch.core:core-common",
+ "androidx.arch.core:core-runtime",
+ "androidx.collection:collection",
+ "androidx.concurrent:concurrent-futures",
+ "androidx.core:core",
+ "androidx.core:core-ktx",
+ "androidx.lifecycle:lifecycle-common",
+ "androidx.lifecycle:lifecycle-livedata",
+ "androidx.lifecycle:lifecycle-livedata-core",
+ "androidx.lifecycle:lifecycle-process",
+ "androidx.lifecycle:lifecycle-runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx",
+ "androidx.lifecycle:lifecycle-service",
+ "androidx.lifecycle:lifecycle-viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+ "androidx.savedstate:savedstate",
+ "androidx.savedstate:savedstate-ktx",
+ "androidx.startup:startup-runtime",
+ "androidx.test.espresso:espresso-core",
+ "androidx.test.espresso:espresso-idling-resource",
+ "androidx.test.ext:junit",
+ "androidx.test.services:storage",
+ "androidx.test:annotation",
+ "androidx.test:core",
+ "androidx.test:monitor",
+ "androidx.test:runner",
+ "androidx.tracing:tracing",
+ "androidx.versionedparcelable:versionedparcelable",
+ "com.android.support:cardview-v7",
+ "com.google.code.findbugs:jsr305",
+ "com.google.guava:listenablefuture",
+ "com.squareup:javawriter",
+ "javax.inject:javax.inject",
+ "junit:junit",
+ "org.hamcrest:hamcrest-core",
+ "org.hamcrest:hamcrest-integration",
+ "org.hamcrest:hamcrest-library",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
+ ],
+ override_targets = {
+ "androidx.annotation:annotation": "@maven//:androidx_annotation_annotation",
+ "androidx.annotation:annotation-experimental": "@maven//:androidx_annotation_annotation_experimental",
+ "androidx.arch.core:core-common": "@maven//:androidx_arch_core_core_common",
+ "androidx.arch.core:core-runtime": "@maven//:androidx_arch_core_core_runtime",
+ "androidx.collection:collection": "@maven//:androidx_collection_collection",
+ "androidx.core:core": "@maven//:androidx_core_core",
+ "androidx.core:core-ktx": "@maven//:androidx_core_core_ktx",
+ "androidx.lifecycle:lifecycle-common": "@maven//:androidx_lifecycle_lifecycle_common",
+ "androidx.lifecycle:lifecycle-livedata": "@maven//:androidx_lifecycle_lifecycle_livedata",
+ "androidx.lifecycle:lifecycle-livedata-core": "@maven//:androidx_lifecycle_lifecycle_livedata_core",
+ "androidx.lifecycle:lifecycle-process": "@maven//:androidx_lifecycle_lifecycle_process",
+ "androidx.lifecycle:lifecycle-runtime": "@maven//:androidx_lifecycle_lifecycle_runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx": "@maven//:androidx_lifecycle_lifecycle_runtime_ktx",
+ "androidx.lifecycle:lifecycle-service": "@maven//:androidx_lifecycle_lifecycle_service",
+ "androidx.lifecycle:lifecycle-viewmodel": "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx": "@maven//:androidx_lifecycle_lifecycle_viewmodel_ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate": "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+ "androidx.savedstate:savedstate": "@maven//:androidx_savedstate_savedstate",
+ "androidx.savedstate:savedstate-ktx": "@maven//:androidx_savedstate_savedstate_ktx",
+ "androidx.startup:startup-runtime": "@maven//:androidx_startup_startup_runtime",
+ "androidx.versionedparcelable:versionedparcelable": "@maven//:androidx_versionedparcelable_versionedparcelable",
+ "com.google.code.findbugs:jsr305": "@maven//:com_google_code_findbugs_jsr305",
+ "com.google.guava:listenablefuture": "@maven//:com_google_guava_listenablefuture",
+ "javax.inject:javax.inject": "@maven//:javax_inject_javax_inject",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core": "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core",
+ },
+ repositories = [
+ "https://dl.google.com/dl/android/maven2/",
+ "https://repo.maven.apache.org/maven2/",
+ ],
+ resolve_timeout = 1000,
+ version_conflict_policy = "pinned",
+)
+
+maven_install(
+ name = "maven",
artifacts = DAGGER_ARTIFACTS + GRAB_BAZEL_COMMON_ARTIFACTS + [
"androidx.activity:activity-compose:1.7.2",
- "androidx.activity:activity:1.6.0",
- "androidx.annotation:annotation:1.1.0",
+ "androidx.activity:activity-ktx:1.7.2",
+ "androidx.activity:activity:1.7.2",
+ "androidx.annotation:annotation-experimental:1.3.0",
+ "androidx.annotation:annotation:1.6.0",
+ "androidx.appcompat:appcompat-resources:1.6.1",
"androidx.appcompat:appcompat:1.6.1",
- "androidx.compose.compiler:compiler:1.4.3",
+ "androidx.arch.core:core-common:2.2.0",
+ "androidx.arch.core:core-runtime:2.1.0",
+ "androidx.collection:collection:1.1.0",
+ "androidx.compose.animation:animation-core:1.2.1",
+ "androidx.compose.animation:animation:1.2.1",
"androidx.compose.foundation:foundation-layout:1.4.3",
"androidx.compose.foundation:foundation:1.4.3",
+ "androidx.compose.material:material-icons-core:1.4.3",
+ "androidx.compose.material:material-ripple:1.4.3",
"androidx.compose.material:material:1.4.3",
+ "androidx.compose.runtime:runtime-saveable:1.4.3",
+ "androidx.compose.runtime:runtime:1.4.3",
+ "androidx.compose.ui:ui-geometry:1.4.3",
+ "androidx.compose.ui:ui-graphics:1.4.3",
+ "androidx.compose.ui:ui-text:1.4.3",
+ "androidx.compose.ui:ui-tooling-data:1.4.3",
+ "androidx.compose.ui:ui-tooling-preview:1.4.3",
"androidx.compose.ui:ui-tooling:1.4.3",
+ "androidx.compose.ui:ui-unit:1.4.3",
"androidx.compose.ui:ui:1.4.3",
"androidx.constraintlayout:constraintlayout-core:1.0.4",
maven.artifact(
artifact = "constraintlayout",
exclusions = [
"androidx.appcompat:appcompat",
+ "androidx.constraintlayout:constraintlayout-core",
"androidx.core:core",
],
group = "androidx.constraintlayout",
version = "2.1.4",
),
+ "androidx.core:core-ktx:1.2.0",
"androidx.core:core:1.10.1",
+ "androidx.cursoradapter:cursoradapter:1.0.0",
+ "androidx.customview:customview:1.0.0",
"androidx.databinding:databinding-adapters:7.2.2",
"androidx.databinding:databinding-common:7.2.2",
+ "androidx.databinding:databinding-compiler-common:7.2.2",
"androidx.databinding:databinding-compiler:7.2.2",
+ "androidx.databinding:databinding-ktx:7.2.2",
"androidx.databinding:databinding-runtime:7.2.2",
"androidx.databinding:viewbinding:7.2.2",
+ "androidx.drawerlayout:drawerlayout:1.0.0",
"androidx.emoji2:emoji2:1.3.0",
+ "androidx.fragment:fragment:1.3.6",
+ "androidx.interpolator:interpolator:1.0.0",
"androidx.lifecycle:lifecycle-common:2.6.1",
- "androidx.lifecycle:lifecycle-runtime:2.5.1",
- "androidx.lifecycle:lifecycle-viewmodel:2.5.1",
- "androidx.test.espresso:espresso-core:3.5.1",
- "androidx.test.ext:junit:1.1.5",
- "androidx.test:monitor:1.6.1",
- "junit:junit:4.13.2",
- "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31",
+ "androidx.lifecycle:lifecycle-livedata-core:2.6.1",
+ "androidx.lifecycle:lifecycle-livedata:2.6.1",
+ "androidx.lifecycle:lifecycle-process:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-runtime:2.6.1",
+ "androidx.lifecycle:lifecycle-service:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1",
+ "androidx.lifecycle:lifecycle-viewmodel:2.6.1",
+ "androidx.loader:loader:1.0.0",
+ "androidx.savedstate:savedstate-ktx:1.2.1",
+ "androidx.savedstate:savedstate:1.2.1",
+ "androidx.startup:startup-runtime:1.1.1",
+ "androidx.vectordrawable:vectordrawable-animated:1.1.0",
+ "androidx.vectordrawable:vectordrawable:1.1.0",
+ "androidx.versionedparcelable:versionedparcelable:1.1.1",
+ "androidx.viewpager:viewpager:1.0.0",
+ "com.android.databinding:baseLibrary:7.2.2",
+ "com.android.tools.build.jetifier:jetifier-core:1.0.0-beta09",
+ "com.android.tools:annotations:30.2.2",
+ "com.google.auto:auto-common:0.10",
+ "com.google.code.findbugs:jsr305:3.0.2",
+ "com.google.code.gson:gson:2.8.6",
+ "com.google.dagger:dagger-compiler:2.29",
+ "com.google.dagger:dagger-producers:2.29",
+ "com.google.dagger:dagger-spi:2.29",
+ "com.google.dagger:dagger:2.29",
+ "com.google.errorprone:error_prone_annotations:2.3.4",
+ "com.google.errorprone:javac-shaded:9-dev-r4023-3",
+ "com.google.googlejavaformat:google-java-format:1.5",
+ "com.google.guava:failureaccess:1.0.1",
+ "com.google.guava:guava:30.1-jre",
+ "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+ "com.google.j2objc:j2objc-annotations:1.3",
+ "com.googlecode.juniversalchardet:juniversalchardet:1.0.3",
+ "com.squareup:javapoet:1.13.0",
+ "com.sun.istack:istack-commons-runtime:3.0.8",
+ "com.sun.xml.fastinfoset:FastInfoset:1.2.16",
+ "commons-codec:commons-codec:1.11",
+ "commons-io:commons-io:2.4",
+ "jakarta.activation:jakarta.activation-api:1.2.1",
+ "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2",
+ "javax.annotation:jsr250-api:1.0",
+ "javax.inject:javax.inject:1",
+ "net.ltgt.gradle.incap:incap:0.2",
+ "org.checkerframework:checker-compat-qual:2.5.3",
+ "org.checkerframework:checker-qual:3.5.0",
+ "org.glassfish.jaxb:jaxb-runtime:2.3.2",
+ "org.glassfish.jaxb:txw2:2.3.2",
+ "org.jetbrains.kotlinx:atomicfu:0.17.3",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4",
+ "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0",
+ "org.jvnet.staxex:stax-ex:1.8.1",
],
excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
fail_on_missing_checksum = False,
@@ -114,36 +729,105 @@ maven_install(
jetify_include_list = [
"androidx.activity:activity",
"androidx.activity:activity-compose",
+ "androidx.activity:activity-ktx",
"androidx.annotation:annotation",
- "androidx.compose.compiler:compiler",
+ "androidx.annotation:annotation-experimental",
+ "androidx.appcompat:appcompat-resources",
+ "androidx.arch.core:core-common",
+ "androidx.arch.core:core-runtime",
+ "androidx.collection:collection",
+ "androidx.compose.animation:animation",
+ "androidx.compose.animation:animation-core",
"androidx.compose.foundation:foundation",
"androidx.compose.foundation:foundation-layout",
"androidx.compose.material:material",
+ "androidx.compose.material:material-icons-core",
+ "androidx.compose.material:material-ripple",
+ "androidx.compose.runtime:runtime",
+ "androidx.compose.runtime:runtime-saveable",
"androidx.compose.ui:ui",
+ "androidx.compose.ui:ui-geometry",
+ "androidx.compose.ui:ui-graphics",
+ "androidx.compose.ui:ui-text",
"androidx.compose.ui:ui-tooling",
+ "androidx.compose.ui:ui-tooling-data",
+ "androidx.compose.ui:ui-tooling-preview",
+ "androidx.compose.ui:ui-unit",
"androidx.constraintlayout:constraintlayout",
"androidx.constraintlayout:constraintlayout-core",
"androidx.core:core",
+ "androidx.core:core-ktx",
+ "androidx.cursoradapter:cursoradapter",
+ "androidx.customview:customview",
"androidx.databinding:databinding-adapters",
"androidx.databinding:databinding-common",
"androidx.databinding:databinding-compiler",
+ "androidx.databinding:databinding-compiler-common",
+ "androidx.databinding:databinding-ktx",
"androidx.databinding:databinding-runtime",
"androidx.databinding:viewbinding",
+ "androidx.drawerlayout:drawerlayout",
"androidx.emoji2:emoji2",
+ "androidx.fragment:fragment",
+ "androidx.interpolator:interpolator",
"androidx.lifecycle:lifecycle-common",
+ "androidx.lifecycle:lifecycle-livedata",
+ "androidx.lifecycle:lifecycle-livedata-core",
+ "androidx.lifecycle:lifecycle-process",
"androidx.lifecycle:lifecycle-runtime",
+ "androidx.lifecycle:lifecycle-runtime-ktx",
+ "androidx.lifecycle:lifecycle-service",
"androidx.lifecycle:lifecycle-viewmodel",
- "androidx.test.espresso:espresso-core",
- "androidx.test.ext:junit",
- "androidx.test:monitor",
+ "androidx.lifecycle:lifecycle-viewmodel-ktx",
+ "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+ "androidx.loader:loader",
+ "androidx.savedstate:savedstate",
+ "androidx.savedstate:savedstate-ktx",
+ "androidx.startup:startup-runtime",
+ "androidx.vectordrawable:vectordrawable",
+ "androidx.vectordrawable:vectordrawable-animated",
+ "androidx.versionedparcelable:versionedparcelable",
+ "androidx.viewpager:viewpager",
+ "com.android.databinding:baseLibrary",
"com.android.support:cardview-v7",
- "junit:junit",
- "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+ "com.android.tools.build.jetifier:jetifier-core",
+ "com.android.tools:annotations",
+ "com.google.auto:auto-common",
+ "com.google.code.findbugs:jsr305",
+ "com.google.code.gson:gson",
+ "com.google.dagger:dagger",
+ "com.google.dagger:dagger-compiler",
+ "com.google.dagger:dagger-producers",
+ "com.google.dagger:dagger-spi",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.errorprone:javac-shaded",
+ "com.google.googlejavaformat:google-java-format",
+ "com.google.guava:failureaccess",
+ "com.google.guava:guava",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "com.googlecode.juniversalchardet:juniversalchardet",
+ "com.squareup:javapoet",
+ "com.sun.istack:istack-commons-runtime",
+ "com.sun.xml.fastinfoset:FastInfoset",
+ "commons-codec:commons-codec",
+ "commons-io:commons-io",
+ "jakarta.activation:jakarta.activation-api",
+ "jakarta.xml.bind:jakarta.xml.bind-api",
+ "javax.annotation:jsr250-api",
+ "javax.inject:javax.inject",
+ "net.ltgt.gradle.incap:incap",
+ "org.checkerframework:checker-compat-qual",
+ "org.checkerframework:checker-qual",
+ "org.glassfish.jaxb:jaxb-runtime",
+ "org.glassfish.jaxb:txw2",
+ "org.jetbrains.kotlinx:atomicfu",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-android",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+ "org.jetbrains.kotlinx:kotlinx-coroutines-core",
+ "org.jetbrains.kotlinx:kotlinx-metadata-jvm",
+ "org.jvnet.staxex:stax-ex",
],
- maven_install_json = "//:maven_install.json",
- override_targets = {
- "androidx.appcompat:appcompat": "@//third_party:androidx_appcompat_appcompat",
- },
repositories = [
"https://dl.google.com/dl/android/maven2/",
"https://repo.maven.apache.org/maven2/",
@@ -152,9 +836,26 @@ maven_install(
version_conflict_policy = "pinned",
)
-load("@maven//:defs.bzl", "pinned_maven_install")
-
-pinned_maven_install()
+maven_install(
+ name = "test_maven",
+ artifacts = [
+ "junit:junit:4.13.2",
+ "org.hamcrest:hamcrest-core:1.3",
+ ],
+ excluded_artifacts = ["androidx.test.espresso:espresso-contrib"],
+ fail_on_missing_checksum = False,
+ jetify = True,
+ jetify_include_list = [
+ "com.android.support:cardview-v7",
+ "junit:junit",
+ "org.hamcrest:hamcrest-core",
+ ],
+ repositories = [
+ "https://repo.maven.apache.org/maven2/",
+ ],
+ resolve_timeout = 1000,
+ version_conflict_policy = "pinned",
+)
android_sdk_repository(
name = "androidsdk",
diff --git a/build.gradle b/build.gradle
index 9e7ebf6c..d89cdb2b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -135,11 +135,11 @@ grazel {
jetifyIncludeList.add("com.android.support:cardview-v7")
jetifyExcludeList.add("androidx.appcompat:appcompat")
artifactPinning {
- enabled.set(true)
+ enabled.set(false)
}
- overrideTargetLabels.putAll(
- ["androidx.appcompat:appcompat": "@//third_party:androidx_appcompat_appcompat"]
- )
+// overrideTargetLabels.putAll(
+// ["androidx.appcompat:appcompat": "@//third_party:androidx_appcompat_appcompat"]
+// )
versionConflictPolicy = "pinned"
}
kotlin {
diff --git a/constants.gradle b/constants.gradle
index eb0e7734..35590514 100644
--- a/constants.gradle
+++ b/constants.gradle
@@ -15,7 +15,7 @@
*/
ext {
groupId = "com.grab.grazel"
- versionName = project.hasProperty("versionName") ? versionName : "0.4.1-alpha.13"
+ versionName = project.hasProperty("versionName") ? versionName : "0.4.1-alpha.13-rd"
website = "https://grab.github.io/Grazel/"
}
diff --git a/flavor-libs/sample-library-flavor1/BUILD.bazel b/flavor-libs/sample-library-flavor1/BUILD.bazel
index d226594b..8741e324 100644
--- a/flavor-libs/sample-library-flavor1/BUILD.bazel
+++ b/flavor-libs/sample-library-flavor1/BUILD.bazel
@@ -23,6 +23,6 @@ grab_kt_jvm_test(
"//visibility:public",
],
deps = [
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
diff --git a/flavor-libs/sample-library-flavor2/BUILD.bazel b/flavor-libs/sample-library-flavor2/BUILD.bazel
index 052ff9e3..de25a256 100644
--- a/flavor-libs/sample-library-flavor2/BUILD.bazel
+++ b/flavor-libs/sample-library-flavor2/BUILD.bazel
@@ -23,6 +23,6 @@ grab_kt_jvm_test(
"//visibility:public",
],
deps = [
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 85e16ca7..fbd00886 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -23,9 +23,14 @@ javapoet = "1.13.0"
junit = "4.13.2"
kotlin = "1.8.10"
kotlin-dsl = "2.3.3"
+kotlin-serialization = "1.5.1"
+kotlinx-coroutines-android = "1.3.9"
+kotlinx-coroutines-core-jvm = "1.7.2"
+leakcanary-android = "2.12"
lifecycle-viewmodel = "2.6.1"
mockito-kotlin = "1.6.0"
nexus = "1.1.0"
+paging-runtime = "3.1.1"
picnic = "0.4.0"
truth = "1.1.3"
@@ -38,6 +43,7 @@ androidx-constraintlayout-core = { module = "androidx.constraintlayout:constrain
androidx-core = { module = "androidx.core:core", version.ref = "androidx-core" }
androidx-emoji2 = { module = "androidx.emoji2:emoji2", version.ref = "emoji2" }
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "lifecycle-viewmodel" }
+androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging-runtime" }
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-junit" }
androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime", version.ref = "androidx-lifecycle-runtime" }
@@ -70,10 +76,15 @@ javapoet = { module = "com.squareup:javapoet", version.ref = "javapoet" }
junit = { module = "junit:junit", version.ref = "junit" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
+kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin-serialization" }
+kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines-android" }
+kotlinx-coroutines-core-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "kotlinx-coroutines-core-jvm" }
+leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanary-android" }
mockito-kotlin = { module = "com.nhaarman:mockito-kotlin", version.ref = "mockito-kotlin" }
nexus-gradle-publish-plugin = { module = "io.github.gradle-nexus:publish-plugin", version.ref = "nexus" }
picnic = { module = "com.jakewharton.picnic:picnic", version.ref = "picnic" }
[plugins]
kotlin-dsl = { id = "org.gradle.kotlin.kotlin-dsl", version.ref = "kotlin-dsl" }
-gradle-publish = { id = "com.gradle.plugin-publish", version.ref = "gradle-plugin-publish" }
\ No newline at end of file
+gradle-publish = { id = "com.gradle.plugin-publish", version.ref = "gradle-plugin-publish" }
+kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
\ No newline at end of file
diff --git a/grazel-gradle-plugin/build.gradle b/grazel-gradle-plugin/build.gradle
index d78a20f4..3b9a8f7c 100644
--- a/grazel-gradle-plugin/build.gradle
+++ b/grazel-gradle-plugin/build.gradle
@@ -31,6 +31,7 @@ plugins {
id "java-gradle-plugin"
alias(libs.plugins.kotlin.dsl)
alias(libs.plugins.gradle.publish)
+ alias(libs.plugins.kotlin.serialization)
id "maven-publish"
id "idea"
}
@@ -88,6 +89,9 @@ dependencies {
implementation libs.google.dagger
kapt libs.google.dagger.compiler
+ implementation libs.kotlin.serialization
+ implementation libs.kotlinx.coroutines.core.jvm
+
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
testImplementation libs.google.truth
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/rules/MavenRules.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/rules/MavenRules.kt
index 83e17af7..c892e00e 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/rules/MavenRules.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/rules/MavenRules.kt
@@ -20,7 +20,6 @@ import com.grab.grazel.bazel.starlark.AssigneeBuilder
import com.grab.grazel.bazel.starlark.StarlarkType
import com.grab.grazel.bazel.starlark.StatementsBuilder
import com.grab.grazel.bazel.starlark.StringStatement
-import com.grab.grazel.bazel.starlark.add
import com.grab.grazel.bazel.starlark.array
import com.grab.grazel.bazel.starlark.asString
import com.grab.grazel.bazel.starlark.assigneeBuilder
@@ -29,7 +28,6 @@ import com.grab.grazel.bazel.starlark.obj
import com.grab.grazel.bazel.starlark.quote
sealed class MavenRepository : AssigneeBuilder {
-
data class DefaultMavenRepository(
val url: String,
val username: String? = null,
@@ -54,7 +52,7 @@ sealed class MavenRepository : AssigneeBuilder {
* @param appendExternal Indicates whether to append or prepend the External variables
*/
private fun combineExternalVariablesAndArray(
- externalVariables: List,
+ externalVariables: Set,
arrayValues: List,
appendExternal: Boolean = false,
) = assigneeBuilder {
@@ -73,17 +71,18 @@ fun StatementsBuilder.mavenInstall(
name: String? = null,
rulesJvmExternalName: String,
artifacts: Set = emptySet(),
- mavenRepositories: List = emptyList(),
- externalArtifacts: List = emptyList(),
- externalRepositories: List = emptyList(),
+ mavenRepositories: Set = emptySet(),
+ externalArtifacts: Set = emptySet(),
+ externalRepositories: Set = emptySet(),
jetify: Boolean = false,
mavenInstallJson: String? = null,
jetifyIncludeList: List = emptyList(),
failOnMissingChecksum: Boolean = true,
resolveTimeout: Int = 600,
- excludeArtifacts: List = emptyList(),
+ excludeArtifacts: Set = emptySet(),
overrideTargets: Map = emptyMap(),
versionConflictPolicy: String? = null,
+ artifactPinning: Boolean,
) {
load("@$rulesJvmExternalName//:defs.bzl", "maven_install")
load("@$rulesJvmExternalName//:specs.bzl", "maven")
@@ -98,7 +97,7 @@ fun StatementsBuilder.mavenInstall(
"repositories" `=` combineExternalVariablesAndArray(
externalRepositories,
- mavenRepositories.map { it.build().asString() },
+ mavenRepositories.map { it.build().asString() }.sorted(),
true,
)
@@ -134,6 +133,13 @@ fun StatementsBuilder.mavenInstall(
"version_conflict_policy" `=` it.quote
}
}
+
+ if (artifactPinning) {
+ load("@$name//:defs.bzl") {
+ "${name}_pinned_maven_install" `=` "pinned_maven_install".quote
+ }
+ add("${name}_pinned_maven_install()")
+ }
}
/**
@@ -196,46 +202,4 @@ sealed class MavenInstallArtifact : StarlarkType {
}
}
}
-}
-
-fun StatementsBuilder.jvmRules(
- rulesJvmExternalRule: BazelRepositoryRule,
- resolveTimeout: Int = 600,
- artifacts: Set = emptySet(),
- artifactPinning: Boolean,
- mavenInstallJson: String? = null,
- mavenRepositories: List = emptyList(),
- externalArtifacts: List = emptyList(),
- externalRepositories: List = emptyList(),
- excludeArtifacts: List = emptyList(),
- overrideTargets: Map = emptyMap(),
- jetify: Boolean = false,
- jetifyIncludeList: List = emptyList(),
- failOnMissingChecksum: Boolean = true,
- versionConflictPolicy: String? = null,
-) {
- add(rulesJvmExternalRule)
-
- newLine()
-
- mavenInstall(
- rulesJvmExternalName = rulesJvmExternalRule.name,
- artifacts = artifacts,
- mavenRepositories = mavenRepositories,
- externalArtifacts = externalArtifacts,
- externalRepositories = externalRepositories,
- overrideTargets = overrideTargets,
- mavenInstallJson = mavenInstallJson,
- jetify = jetify,
- jetifyIncludeList = jetifyIncludeList,
- failOnMissingChecksum = failOnMissingChecksum,
- resolveTimeout = resolveTimeout,
- excludeArtifacts = excludeArtifacts,
- versionConflictPolicy = versionConflictPolicy,
- )
-
- if (artifactPinning) {
- load("@maven//:defs.bzl", "pinned_maven_install")
- add("pinned_maven_install()")
- }
}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/BazelDependency.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/BazelDependency.kt
index aebc5c3f..fb941704 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/BazelDependency.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/BazelDependency.kt
@@ -17,7 +17,6 @@
package com.grab.grazel.bazel.starlark
import org.gradle.api.Project
-import org.gradle.api.artifacts.Dependency
sealed class BazelDependency {
data class ProjectDependency(
@@ -49,16 +48,20 @@ sealed class BazelDependency {
override fun toString() = dep
}
- data class MavenDependency(val dependency: Dependency) : BazelDependency() {
+ data class MavenDependency(
+ val repo: String = "maven",
+ val group: String,
+ val name: String
+ ) : BazelDependency() {
private fun String.toBazelPath(): String {
return replace(".", "_").replace("-", "_")
}
override fun toString(): String {
- val group = dependency.group?.toBazelPath() ?: ""
- val name = dependency.name.toBazelPath()
- return "@maven//:${group}_$name"
+ val group = group.toBazelPath()
+ val name = name.toBazelPath()
+ return "@$repo//:${group}_$name"
}
}
}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/Functions.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/Functions.kt
index 1302c640..13946916 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/Functions.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/bazel/starlark/Functions.kt
@@ -22,7 +22,7 @@ import java.io.PrintWriter
data class FunctionStatement(
val name: String,
- private val params: List,
+ private val params: List,
private val multilineParams: Boolean = false
) : Assignee {
override fun write(level: Int, writer: PrintWriter) {
@@ -75,6 +75,25 @@ fun StatementsBuilder.load(bzlFile: String, vararg symbols: String) {
loadStrategy.load(this, bzlFile, *symbols)
}
+/**
+ * Load statement with option to alias imported symbol via `assignmentBuilder`
+ *
+ * Eg:
+ * ```
+ * load("@maven//:defs.bzl", default_pinned_maven_install = "pinned_maven_install")
+ * ```
+ */
+fun StatementsBuilder.load(path: String, assignmentBuilder: AssignmentBuilder.() -> Unit = {}) {
+ val symbolImports = Assignments(assignmentBuilder = assignmentBuilder)
+ add(
+ FunctionStatement(
+ name = "load",
+ params = listOf(path.quote.toStatement()) + symbolImports
+ )
+ )
+}
+
+
@Suppress("unused")
fun StatementsBuilder.glob(include: ArrayStatement): FunctionStatement {
val multilineParams = include.elements.size > 2
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/di/GrazelComponent.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/di/GrazelComponent.kt
index e4bcc295..17f97218 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/di/GrazelComponent.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/di/GrazelComponent.kt
@@ -30,7 +30,6 @@ import com.grab.grazel.gradle.dependencies.DependenciesDataSource
import com.grab.grazel.gradle.dependencies.DependenciesGraphsBuilder
import com.grab.grazel.gradle.dependencies.DependenciesModule
import com.grab.grazel.gradle.dependencies.DependencyGraphs
-import com.grab.grazel.gradle.dependencies.MavenInstallArtifactsCalculator
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import com.grab.grazel.gradle.variant.VariantBuilder
import com.grab.grazel.gradle.variant.VariantMatcher
@@ -43,6 +42,7 @@ import com.grab.grazel.migrate.android.AndroidLibraryDataExtractor
import com.grab.grazel.migrate.android.ManifestValuesBuilder
import com.grab.grazel.migrate.dependencies.ArtifactsPinner
import com.grab.grazel.migrate.dependencies.DefaultArtifactsPinner
+import com.grab.grazel.migrate.dependencies.MavenInstallArtifactsCalculator
import com.grab.grazel.migrate.internal.ProjectBazelFileBuilder
import com.grab.grazel.migrate.internal.RootBazelFileBuilder
import com.grab.grazel.migrate.internal.WorkspaceBuilder
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/Dependencies.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/Dependencies.kt
index a8f1991c..5615d7b7 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/Dependencies.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/Dependencies.kt
@@ -17,14 +17,27 @@
package com.grab.grazel.gradle.dependencies
import com.grab.grazel.GrazelExtension
-import com.grab.grazel.bazel.rules.MavenInstallArtifact
-import com.grab.grazel.bazel.rules.MavenInstallArtifact.Exclusion.SimpleExclusion
+import com.grab.grazel.bazel.rules.ANDROIDX_GROUP
+import com.grab.grazel.bazel.rules.ANNOTATION_ARTIFACT
+import com.grab.grazel.bazel.rules.DAGGER_GROUP
+import com.grab.grazel.bazel.rules.DATABINDING_GROUP
+import com.grab.grazel.bazel.starlark.BazelDependency
+import com.grab.grazel.bazel.starlark.BazelDependency.StringDependency
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.ConfigurationDataSource
import com.grab.grazel.gradle.ConfigurationScope
+import com.grab.grazel.gradle.ConfigurationScope.TEST
import com.grab.grazel.gradle.RepositoryDataSource
import com.grab.grazel.gradle.configurationScopes
+import com.grab.grazel.gradle.hasDatabinding
import com.grab.grazel.gradle.variant.AndroidVariantsExtractor
+import com.grab.grazel.gradle.variant.DEFAULT_VARIANT
+import com.grab.grazel.gradle.variant.TEST_VARIANT
+import com.grab.grazel.gradle.variant.Variant
+import com.grab.grazel.gradle.variant.VariantBuilder
+import com.grab.grazel.gradle.variant.isConfigScope
+import com.grab.grazel.gradle.variant.migratableConfigurations
+import com.grab.grazel.migrate.dependencies.MavenInstallStore
import com.grab.grazel.util.GradleProvider
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
@@ -46,17 +59,6 @@ internal val IGNORED_ARTIFACT_GROUPS = listOf(
"org.jetbrains.kotlin"
)
-@Deprecated(
- "No longer used, use com.grab.grazel.gradle.dependencies.ExcludeRule instead.",
- replaceWith = ReplaceWith("ExcludeRule", "com.grab.grazel.gradle.dependencies.ExcludeRule")
-)
-data class ExcludeRuleOld(
- val group: String,
- val artifact: String
-) {
- override fun toString(): String = "$group:$artifact"
-}
-
/**
* Simple data holder for a Maven artifact containing its group, name and version.
*/
@@ -64,7 +66,6 @@ internal data class MavenArtifact(
val group: String?,
val name: String?,
val version: String? = null,
- val excludeRuleOlds: Set = emptySet()
) {
val id get() = "$group:$name"
override fun toString() = "$group:$name:$version"
@@ -93,20 +94,6 @@ internal interface DependenciesDataSource {
vararg scopes: ConfigurationScope
): Sequence>
- /**
- * Returns the resolved artifacts dependencies for the given projects in the fully qualified Maven format.
- *
- * @param projects The list of projects for which the artifacts need to be resolved
- * @param overrideArtifactVersions List of fully qualified maven coordinates with versions that used for calculation
- * instead of the one calculated automatically.
- *
- * @return List of artifacts in fully qualified Maven format
- */
- fun resolvedArtifactsFor(
- projects: List,
- overrideArtifactVersions: List = emptyList()
- ): List
-
/**
* @return true if the project has any private dependencies in any configuration
*/
@@ -132,6 +119,14 @@ internal interface DependenciesDataSource {
rootProject: Project,
fileExtension: String? = null
): Map
+
+ /**
+ * Non project dependencies for the given [buildGraphType]
+ */
+ fun externalDependencies(
+ project: Project,
+ buildGraphType: BuildGraphType
+ ): List
}
@Singleton
@@ -142,38 +137,13 @@ internal class DefaultDependenciesDataSource @Inject constructor(
private val artifactsConfig: ArtifactsConfig,
private val repositoryDataSource: RepositoryDataSource,
private val dependencyResolutionService: GradleProvider,
- private val androidVariantsExtractor: AndroidVariantsExtractor
+ private val androidVariantsExtractor: AndroidVariantsExtractor,
+ private val variantBuilder: VariantBuilder,
+ private val mavenInstallStore: MavenInstallStore
) : DependenciesDataSource {
private val configurationScopes by lazy { grazelExtension.configurationScopes() }
- private val excludeArtifactsDenyList by lazy { grazelExtension.rules.mavenInstall.excludeArtifactsDenyList.get() }
-
- private val resolvedVersions: Map* maven coord */ String,/* version */ String> by lazy {
- rootProject
- .subprojects
- .asSequence()
- .flatMap { it.firstLevelModuleDependencies() }
- .flatMap { (listOf(it) + it.children).asSequence() }
- .map { it.moduleGroup + ":" + it.moduleName to it.moduleVersion }
- .toMap()
- }
-
- // TODO Can be moved else where for clarity
- private val resolvedRepositories: Map* maven coord */ String,/* repo name */ String> by lazy {
- rootProject
- .subprojects
- .asSequence()
- .flatMap { it.externalResolvedDependencies().asSequence() }
- .filter { it.repositoryName != null && it.moduleVersion != null }
- .map { componentResult ->
- val moduleVersion = componentResult.moduleVersion
- val id = moduleVersion!!.group + ":" + moduleVersion.name
- id to componentResult.repositoryName!!
- }.distinct()
- .toMap()
- }
-
private fun Project.buildGraphTypes() =
configurationScopes.flatMap { configurationScope ->
androidVariantsExtractor.getVariants(this).map { variant ->
@@ -181,28 +151,6 @@ internal class DefaultDependenciesDataSource @Inject constructor(
}
}
- /**
- * Given a group, name and version will update version with following properties
- * * Overridden version by user
- * * Resolved version by Gradle
- * * Declared version in buildscript.
- */
- private fun correctArtifactVersion(
- mavenArtifact: MavenArtifact,
- overrideArtifactVersions: Map = emptyMap()
- ): MavenArtifact {
- // To correctly calculate the actual used version, we map the version from resolvedVersions since
- // resolvedVersions would contain the actual resolved dependency version (respecting resolution strategy)
- // instead of the ones declared in a project's build file
- // Additionally we also check if user needs to override the version via overrideArtifactVersions and use
- // that if found
- val id = "${mavenArtifact.group}:${mavenArtifact.name}"
- val newVersion = overrideArtifactVersions[id]
- ?: resolvedVersions[id]
- ?: mavenArtifact.version
- return mavenArtifact.copy(version = newVersion)
- }
-
/**
* @return `true` when the `MavenArtifact` is present is ignored by user.
*/
@@ -213,79 +161,6 @@ internal class DefaultDependenciesDataSource @Inject constructor(
*/
private val MavenArtifact.isExcluded get() = artifactsConfig.excludedList.contains(id)
- override fun resolvedArtifactsFor(
- projects: List,
- overrideArtifactVersions: List
- ): List {
- // Prepare override versions map
- val overrideArtifactVersionMap = overrideArtifactVersions.associate { mavenCoordinate ->
- try {
- val chunks = mavenCoordinate.split(":")
- chunks.first() + ":" + chunks[1] to chunks[2]
- } catch (e: IndexOutOfBoundsException) {
- error("$mavenCoordinate is not a proper maven coordinate, please ensure version is correctly specified")
- }
- }
-
- // Filter out configurations we are interested in.
- val configurations = projects
- .asSequence()
- .flatMap { project ->
- configurationDataSource.configurations(
- project,
- *configurationScopes
- )
- }
- .toList()
-
- // Calculate all the external artifacts
- val externalArtifacts = configurations.asSequence()
- .flatMap { it.dependencies.asSequence() }
- .filter { it.group != null }
- .filterIsInstance()
- .map { dependency -> dependency.toMavenArtifact() }
-
-
- // Collect all forced versions
- // (Perf fix) - collecting all projects' forced modules is costly, hence take the first sub project
- // TODO Provide option to consider all forced versions backed by a flag.
- val forcedVersions = sequenceOf(rootProject.subprojects.first())
- .flatMap { project ->
- configurationDataSource.configurations(
- project,
- *configurationScopes
- )
- }
- .let(::collectForcedVersions)
-
- return (externalArtifacts + forcedVersions)
- .groupBy { it.id }
- .map { (_, mavenArtifacts) ->
- // Merge all exclude rules so that we have a cumulative set
- mavenArtifacts
- .first()
- .copy(
- excludeRuleOlds = mavenArtifacts
- .flatMap(MavenArtifact::excludeRuleOlds)
- .toSet()
- )
- }.asSequence()
- .filter { mavenArtifact ->
- // Only allow dependencies from supported repositories
- mavenArtifact.isFromSupportedRepository(repositoryDataSource)
- }.filter { mavenArtifact ->
- // Don't include artifacts that are excluded or included
- !mavenArtifact.isIgnored && !mavenArtifact.isExcluded
- }.map { mavenArtifact ->
- // Fix the artifact version as per resolvedVersions or overrideVersions
- correctArtifactVersion(
- mavenArtifact = mavenArtifact,
- overrideArtifactVersions = overrideArtifactVersionMap
- )
- }.map(MavenArtifact::toMavenInstallArtifact)
- .toList()
- }
-
override fun hasDepsFromUnsupportedRepositories(project: Project): Boolean {
return project
.externalResolvedDependencies()
@@ -296,32 +171,34 @@ internal class DefaultDependenciesDataSource @Inject constructor(
override fun hasIgnoredArtifacts(project: Project): Boolean {
return project.firstLevelModuleDependencies()
.flatMap { (listOf(it) + it.children).asSequence() }
- .filter { !IGNORED_ARTIFACT_GROUPS.contains(it.moduleGroup) }
+ .filter { it.moduleGroup !in IGNORED_ARTIFACT_GROUPS }
.any { MavenArtifact(it.moduleGroup, it.moduleName).isIgnored }
}
override fun mavenDependencies(
project: Project,
vararg buildGraphTypes: BuildGraphType
- ): Sequence =
- declaredDependencies(project, *buildGraphTypes.map { it.configurationScope }.toTypedArray())
- .filter { (configuration, _) ->
- if (buildGraphTypes.isEmpty()) {
- true
- } else {
- configurationDataSource.isThisConfigurationBelongsToThisVariants(
- project,
- *buildGraphTypes.map { it.variant }.toTypedArray(),
- configuration = configuration
- )
- }
+ ): Sequence {
+ return declaredDependencies(
+ project,
+ *buildGraphTypes.map { it.configurationScope }.toTypedArray()
+ ).filter { (configuration, _) ->
+ if (buildGraphTypes.isEmpty()) {
+ true
+ } else {
+ configurationDataSource.isThisConfigurationBelongsToThisVariants(
+ project,
+ *buildGraphTypes.map { it.variant }.toTypedArray(),
+ configuration = configuration
+ )
}
- .map { it.second }
- .filter { it.group != null && !IGNORED_ARTIFACT_GROUPS.contains(it.group) }
+ }.map { it.second }
+ .filter { it.group != null && it.group !in IGNORED_ARTIFACT_GROUPS }
.filter {
val artifact = MavenArtifact(it.group, it.name)
!artifact.isExcluded && !artifact.isIgnored
}.filter { it !is ProjectDependency }
+ }
override fun projectDependencies(
project: Project, vararg scopes: ConfigurationScope
@@ -359,6 +236,57 @@ internal class DefaultDependenciesDataSource @Inject constructor(
return results
}
+ override fun externalDependencies(
+ project: Project,
+ buildGraphType: BuildGraphType
+ ): List {
+ val variants = variantBuilder.build(project).groupBy(Variant<*>::name)
+ val inputVariant = buildGraphType.variant
+ // From input variant map to Grazel variant
+ val grazelVariant: Variant<*> = when {
+ inputVariant != null -> variants[inputVariant.name]!!.first {
+ it.variantType.isConfigScope(project, buildGraphType.configurationScope)
+ }
+ // Input variant is null, probably legacy code path assumes non android project has no
+ // variants. To compensate, map it to `default` or `test` based on
+ // BuildGraphType.configurationScope
+ // This will no longer needed after migrating legacy code path to use variants
+ else -> when (buildGraphType.configurationScope) {
+ TEST -> variants[TEST_VARIANT]!!.first()
+ else -> variants[DEFAULT_VARIANT]!!.first()
+ }
+ }
+
+ return grazelVariant.migratableConfigurations
+ .asSequence()
+ .flatMap { it.allDependencies.filterIsInstance() }
+ .filter { it.group !in IGNORED_ARTIFACT_GROUPS }
+ .filter {
+ val artifact = MavenArtifact(it.group, it.name)
+ !artifact.isExcluded && !artifact.isIgnored
+ }.filter {
+ if (project.hasDatabinding) {
+ it.group != DATABINDING_GROUP && (it.group != ANDROIDX_GROUP && it.name != ANNOTATION_ARTIFACT)
+ } else true
+ }.map { dependency ->
+ val variantHierarchy = buildSet {
+ add(grazelVariant.name)
+ addAll(grazelVariant.extendsFrom.reversed())
+ }
+ when (dependency.group) {
+ DAGGER_GROUP -> StringDependency("//:dagger")
+ else -> mavenInstallStore.get(
+ variants = variantHierarchy,
+ group = dependency.group!!,
+ name = dependency.name
+ ) ?: run {
+ error("$dependency cant be found for migrating ${project.name}")
+ }
+ }
+ }.distinct()
+ .toList()
+ }
+
/**
* Resolves all the external dependencies for the given project. By resolving all the dependencies, we get accurate
* dependency information that respects resolution strategy, substitution and any other modification by Gradle apart
@@ -373,15 +301,6 @@ internal class DefaultDependenciesDataSource @Inject constructor(
)
)
- /**
- * @return true if the [MavenArtifact] was fetched from a supported repository
- */
- private fun MavenArtifact.isFromSupportedRepository(
- repositoryDataSource: RepositoryDataSource
- ) = resolvedRepositories.containsKey(id) && !repositoryDataSource
- .unsupportedRepositoryNames
- .contains(resolvedRepositories.getValue(id))
-
/**
* Collects first level module dependencies from their resolved configuration. Additionally, excludes any artifacts
* that are not meant to be used in Bazel as defined by [IGNORED_ARTIFACT_GROUPS]
@@ -401,7 +320,7 @@ internal class DefaultDependenciesDataSource @Inject constructor(
sequenceOf()
}
}.filterIsInstance()
- .filter { !IGNORED_ARTIFACT_GROUPS.contains(it.moduleGroup) }
+ .filter { it.moduleGroup !in IGNORED_ARTIFACT_GROUPS }
}
internal fun firstLevelModuleDependencies(project: Project) =
@@ -427,57 +346,9 @@ internal class DefaultDependenciesDataSource @Inject constructor(
}
}
- /**
- * Collects any custom resolution strategy (particularly forced modules) defined in the given `configurations`
- *
- * @return Gradle's forced modules artifacts parsed to `MavenArtifact`.
- */
- private fun collectForcedVersions(
- configurations: Sequence
- ): Sequence = mutableMapOf().apply {
- configurations
- .flatMap { it.resolutionStrategy.forcedModules.asSequence() }
- .forEach { mvSelector ->
- val key = MavenArtifact(mvSelector.group, mvSelector.name, mvSelector.version)
- put(key, key.id)
- }
- }.keys.asSequence()
-
- /**
- * Map [ExternalDependency] to [MavenArtifact] with relevant details like exclude rules.
- */
- private fun ExternalDependency.toMavenArtifact(): MavenArtifact {
- return MavenArtifact(
- group = group,
- name = name,
- version = version,
- excludeRuleOlds = excludeRules
- .asSequence()
- .map {
- @Suppress("USELESS_ELVIS") // Gradle lying, module can be null
- ExcludeRuleOld(it.group, it.module ?: "")
- }
- .filterNot { it.artifact.isNullOrBlank() }
- .filterNot { excludeArtifactsDenyList.contains(it.toString()) }
- .toSet()
- )
- }
-
private fun DefaultResolvedDependency.toMavenArtifact() = MavenArtifact(
group = moduleGroup,
name = moduleName,
version = moduleVersion,
)
-}
-
-internal fun MavenArtifact.toMavenInstallArtifact(): MavenInstallArtifact {
- return when {
- excludeRuleOlds.isEmpty() -> MavenInstallArtifact.SimpleArtifact(toString())
- else -> MavenInstallArtifact.DetailedArtifact(
- group = group!!,
- artifact = name!!,
- version = version!!,
- exclusions = excludeRuleOlds.map { SimpleExclusion("${it.group}:${it.artifact}") }
- )
- }
}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculator.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculator.kt
deleted file mode 100644
index 46766694..00000000
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculator.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.grab.grazel.gradle.dependencies
-
-import com.grab.grazel.GrazelExtension
-import com.grab.grazel.di.qualifiers.RootProject
-import com.grab.grazel.gradle.ConfigurationDataSource
-import com.grab.grazel.gradle.RepositoryDataSource
-import org.gradle.api.Project
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.artifacts.ExternalDependency
-import org.gradle.api.artifacts.result.ResolutionResult
-import org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository
-import org.gradle.api.internal.artifacts.result.DefaultResolvedComponentResult
-import org.gradle.api.internal.artifacts.result.DefaultResolvedDependencyResult
-import javax.inject.Inject
-
-data class Repository(
- val name: String,
- val repository: DefaultMavenArtifactRepository
-)
-
-data class ExcludeRule(
- val group: String,
- val artifact: String
-) {
- override fun toString(): String = "$group:$artifact"
-}
-
-class MavenExternalArtifact(
- val group: String,
- val name: String,
- val version: String,
- val repository: Repository,
- val componentResult: DefaultResolvedComponentResult,
- val excludeRules: List
-) {
- val id get() = "$group:$name:$version resolved from ${repository.name}"
- override fun toString() = id
-}
-
-
-@Deprecated("Use task based dependency resolution instead")
-internal class MavenInstallArtifactsCalculator
-@Inject
-constructor(
- @param:RootProject private val rootProject: Project,
- private val configurationDataSource: ConfigurationDataSource,
- private val repositoryDataSource: RepositoryDataSource,
- private val grazelExtension: GrazelExtension,
-) {
-
- private val excludeArtifactsDenyList by lazy {
- grazelExtension.rules.mavenInstall.excludeArtifactsDenyList.get()
- }
-
- fun calculate(): Map> {
- return emptyMap()
- }
-
- /**
- * Takes a list of variants and the list of configurations in them to produce a `MavenExternalArtifact`
- * The data required for `MavenExternalArtifact` comes from different places and this method merges
- * from all of them to produce `Map` of variants and `MavenExternalArtifact`s.
- *
- * * Repository is calculated from merging all repositories in the project.
- * @see [RepositoryDataSource.allRepositoriesByName]
- * * Exclude rules are calculated from `ExternalDependency` provided from `configuration.dependencies`
- * * [ResolutionResult] is used to calculate dependency versions to ensure final version after
- * dependency resolution is used
- *
- */
- private fun resolveVariantDependencies(
- variantConfigs: Map>
- ): Map> {
- val repositories = repositoryDataSource.allRepositoriesByName
- return variantConfigs.mapValues { (_, configurations) ->
- val excludeRules = calculateExcludeRules(configurations)
- configurations
- .asSequence()
- .filter { it.isCanBeResolved }
- .map { it.incoming }
- .flatMap { resolvableDependencies ->
- try {
- resolvableDependencies
- .resolutionResult
- .root
- .dependencies
- .asSequence()
- .filterIsInstance()
- .map { it.selected }
- .filter { !it.toString().startsWith("project :") }
- .filterIsInstance()
- .map { componentResult ->
- val version = componentResult.moduleVersion!!
- MavenExternalArtifact(
- group = version.group,
- version = version.version,
- name = version.name,
- repository = Repository(
- name = componentResult.repositoryName!!,
- repository = repositories[componentResult.repositoryName!!]!!
- ),
- componentResult = componentResult,
- excludeRules = excludeRules.getOrDefault(
- version.toString(),
- emptyList()
- )
- )
- }
- } catch (e: Exception) {
- e.printStackTrace()
- emptySequence()
- }
- }.toSortedSet(compareBy(MavenExternalArtifact::id))
- .toList()
- }
- }
-
- /**
- * Calculate and merge exclude rules from all dependency declarations.
- *
- * @param configurations Configurations to merge exclude rules from
- * @return Map of maven id and its merged exclude rules.
- */
- private fun calculateExcludeRules(
- configurations: List
- ): Map> {
- return configurations
- .asSequence()
- .flatMap { it.dependencies }
- .filter { it.group != null }
- .filterIsInstance()
- .groupBy { dep -> "${dep.group}:${dep.name}:${dep.version}" }
- .mapValues { (_, artifacts) ->
- artifacts.flatMap { it.extractExcludeRules() }.distinct()
- }.filterValues { it.isNotEmpty() }
- }
-
- private fun ExternalDependency.extractExcludeRules(): Set {
- return excludeRules
- .asSequence()
- .map {
- @Suppress("USELESS_ELVIS") // Gradle lying, module can be null
- ExcludeRule(it.group, it.module ?: "")
- }
- .filterNot { it.artifact.isNullOrBlank() }
- .filterNot { excludeArtifactsDenyList.contains(it.toString()) }
- .toSet()
- }
-}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/ResolvedComponentsVisitor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/ResolvedComponentsVisitor.kt
new file mode 100644
index 00000000..c119ea74
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/ResolvedComponentsVisitor.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.gradle.dependencies
+
+import com.grab.grazel.gradle.dependencies.ResolvedComponentsVisitor.Companion.IGNORED_ARTIFACTS
+import com.grab.grazel.util.ansiCyan
+import com.grab.grazel.util.ansiGreen
+import com.grab.grazel.util.ansiYellow
+import org.gradle.api.artifacts.result.ResolutionResult
+import org.gradle.api.artifacts.result.ResolvedComponentResult
+import org.gradle.api.artifacts.result.ResolvedDependencyResult
+import org.gradle.api.internal.artifacts.result.DefaultResolvedComponentResult
+import java.util.TreeSet
+
+private typealias Node = ResolvedComponentResult
+
+/**
+ * Visitor to flatten all components (including transitives) from a root [ResolvedComponentResult].
+ * Ignore few artifacts specified by [IGNORED_ARTIFACTS]
+ */
+internal class ResolvedComponentsVisitor {
+
+ private fun printIndented(level: Int, message: String, logger: (message: String) -> Unit) {
+ val prefix = if (level == 0) "─" else " └"
+ val indent = (0..level * 2).joinToString(separator = "") { "─" }
+ val msg = message.let {
+ when (level) {
+ 0 -> it.ansiCyan
+ 1 -> it.ansiGreen
+ else -> it.ansiYellow
+ }
+ }
+ logger("$prefix$indent $msg")
+ }
+
+ private val Node.isProject get() = toString().startsWith("project :")
+ private val Node.repository
+ get() = (this as DefaultResolvedComponentResult).repositoryName ?: ""
+
+ /**
+ * Visit all external dependency nodes in the graph and map them to [T] using the [transform]
+ * function. Both current component and its transitive dependencies are provided in the callback
+ *
+ * @param root The root component usually [ResolutionResult.getRoot]
+ * @param transform The callback used to convert to [T]
+ */
+ fun > visit(
+ root: Node,
+ logger: (message: String) -> Unit = { },
+ transform: (component: Node, repository: String, dependencies: Set) -> T?
+ ): Set {
+ val transitiveClosureMap = mutableMapOf>()
+ val visited = mutableSetOf()
+ val result = TreeSet(compareBy { it })
+
+ fun dfs(node: Node, level: Int = 0) {
+ if (node in visited) return
+ visited.add(node)
+ printIndented(level, node.toString(), logger)
+
+ val transitiveClosure = TreeSet(compareBy(Node::toString))
+ node.dependencies
+ .asSequence()
+ .filterIsInstance()
+ .map { it.selected }
+ .filter { !it.isProject }
+ .filter { dep -> IGNORED_ARTIFACTS.none { dep.toString().startsWith(it) } }
+ .forEach { directDependency ->
+ dfs(directDependency, level + 1)
+
+ transitiveClosure.add(directDependency)
+ transitiveClosure.addAll(transitiveClosureMap[directDependency] ?: emptySet())
+ }
+ transitiveClosureMap[node] = transitiveClosure
+ // TODO(arun) Memoize the transform
+ if (!node.isProject) {
+ transform(
+ node,
+ node.repository,
+ transitiveClosure.map { it.toString() + ":" + it.repository }.toSet()
+ )?.let(result::add)
+ }
+ }
+ dfs(root)
+ return result
+ }
+
+ companion object {
+ private val IGNORED_ARTIFACTS = listOf(
+ "org.jetbrains.kotlin:kotlin-parcelize-runtime"
+ )
+ }
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/ExcludeRule.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ExcludeRule.kt
similarity index 74%
rename from grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/ExcludeRule.kt
rename to grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ExcludeRule.kt
index 745c1e1e..e754f52b 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/ExcludeRule.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ExcludeRule.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,12 @@
* limitations under the License.
*/
-package com.grab.grazel.migrate.dependencies.model
+package com.grab.grazel.gradle.dependencies.model
-internal data class ExcludeRule(
+import java.io.Serializable
+
+@kotlinx.serialization.Serializable
+data class ExcludeRule(
val group: String,
val artifact: String
-)
\ No newline at end of file
+) : Serializable
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ResolveDependenciesResult.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ResolveDependenciesResult.kt
new file mode 100644
index 00000000..fdbb00f2
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ResolveDependenciesResult.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.gradle.dependencies.model
+
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.decodeFromStream
+import org.gradle.api.file.RegularFile
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionComparator
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.Version
+import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser
+import java.io.File
+
+@Serializable
+data class ResolveDependenciesResult(
+ val variantName: String,
+ val dependencies: Map> = HashMap()
+) {
+ companion object {
+ fun fromJson(json: RegularFile) = fromJson(json.asFile)
+ fun fromJson(json: File) = json
+ .inputStream()
+ .buffered().use { stream -> Json.decodeFromStream(stream) }
+ }
+}
+
+@Serializable
+data class ResolvedDependency(
+ val id: String,
+ val version: String,
+ val shortId: String,
+ val direct: Boolean,
+ val dependencies: Set,
+ val excludeRules: Set,
+ val repository: String
+) : Comparable {
+ override fun compareTo(other: ResolvedDependency) = id.compareTo(other.id)
+
+ companion object {
+ fun from(dependencyNotation: String): ResolvedDependency {
+ val (group, name, version, repository) = dependencyNotation.split(":")
+ val shortId = "$group:$name"
+ return ResolvedDependency(
+ id = "$group:$name:$version",
+ version = version,
+ shortId = shortId,
+ direct = false,
+ dependencies = emptySet(),
+ excludeRules = emptySet(),
+ repository = repository
+ )
+ }
+ }
+}
+
+/**
+ * Unwrap [ResolvedDependency] such that it contains all its dependencies in the form of
+ * [ResolvedDependency]
+ */
+val ResolvedDependency.allDependencies: Set
+ get() = buildSet {
+ add(this@allDependencies.copy(dependencies = emptySet()))
+ addAll(dependencies.map { dependency -> ResolvedDependency.from(dependency) })
+ }
+
+
+class VersionInfo(val version: String) : Versioned, Comparable {
+ private val parsedVersion = VersionParser().transform(version)
+ override fun getVersion(): Version = parsedVersion
+ private val comparator = DefaultVersionComparator()
+ override fun compareTo(other: VersionInfo) = comparator.compare(this, other)
+}
+
+val ResolvedDependency.versionInfo get() = VersionInfo(version = version)
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/variant/VariantBuilder.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/variant/VariantBuilder.kt
index 10e0d347..b2261319 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/variant/VariantBuilder.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/variant/VariantBuilder.kt
@@ -14,7 +14,7 @@ import javax.inject.Singleton
/**
* [VariantBuilder] is used to construct unified [Set] of [Variant] types for Android/Jvm [Project]
*
- * [VariantBuilder.build] caches constructed Variants and can be called multiple times for a project.
+ * [VariantBuilder.onVariants] caches constructed Variants and can be called multiple times for a project.
*
* For lazy construction and safe to call during configuration phase use [VariantBuilder.onVariants]
*
@@ -144,20 +144,41 @@ constructor(
action(AndroidVariant(project, variant))
}
- // Special case, if this module does not have flavors declared then variants
- // will be just buildTypes. Since we already would have passed buildType variants
- // above we don't need to pass it again here.
+
if (flavors.isNotEmpty()) {
- buildTypes.flatMap { buildType ->
- VariantType.values().filter { it != JvmBuild }.map { variantType ->
- AndroidBuildType(
- project = project,
- backingVariant = buildType,
- variantType = variantType,
- flavors = flavorNames
- )
- }
- }.distinctBy { it.name + it.variantType }.forEach { variant -> action(variant) }
+ // Special case, if this module does not have flavors declared then variants
+ // will be just buildTypes. Since we already would have passed buildType variants
+ // above we don't need to pass it again here.
+ buildTypes
+ .asSequence()
+ .flatMap { buildType ->
+ VariantType.values()
+ .filter { it != JvmBuild }
+ .map { variantType ->
+ AndroidBuildType(
+ project = project,
+ backingVariant = buildType,
+ variantType = variantType,
+ flavors = flavorNames
+ )
+ }
+ }.distinctBy { it.name + it.variantType }
+ .forEach(action)
+
+ VariantType
+ .values()
+ .asSequence()
+ .filter { it != JvmBuild }
+ .flatMap { variantType ->
+ flavors.map { flavor ->
+ AndroidFlavor(
+ project,
+ flavor,
+ variantType,
+ buildTypeNames
+ )
+ }
+ }.forEach(action)
}
} else if (project.isJvm) {
action(JvmVariant(project = project, variantType = JvmBuild))
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/MigrationModule.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/MigrationModule.kt
index 794fe267..2ed721c4 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/MigrationModule.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/MigrationModule.kt
@@ -16,5 +16,12 @@
package com.grab.grazel.migrate
+import com.grab.grazel.migrate.dependencies.DefaultMavenInstallStore
+import com.grab.grazel.migrate.dependencies.MavenInstallStore
+import dagger.Binds
+
@dagger.Module
-internal interface MigrationModule
\ No newline at end of file
+internal interface MigrationModule {
+ @Binds
+ fun DefaultMavenInstallStore.binds(): MavenInstallStore
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidExtractor.kt
index 9f5d1ceb..54b1157f 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidExtractor.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidExtractor.kt
@@ -34,7 +34,7 @@ import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import com.grab.grazel.gradle.variant.MatchedVariant
import com.grab.grazel.gradle.variant.getMigratableBuildVariants
import com.grab.grazel.gradle.variant.nameSuffix
-import com.grab.grazel.migrate.android.PathResolveMode.*
+import com.grab.grazel.migrate.android.PathResolveMode.DIRECTORY
import com.grab.grazel.migrate.android.SourceSetType.ASSETS
import com.grab.grazel.migrate.android.SourceSetType.JAVA_KOTLIN
import com.grab.grazel.migrate.android.SourceSetType.RESOURCES
@@ -88,7 +88,7 @@ constructor(
dependent,
matchedVariant
)
- } + dependenciesDataSource.collectMavenDeps(
+ } + dependenciesDataSource.externalDependencies(
project,
BuildGraphType(BUILD, matchedVariant.variant)
) + project.kotlinParcelizeDeps()
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidInstrumentationBinaryDataExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidInstrumentationBinaryDataExtractor.kt
index e8965e14..eabe729c 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidInstrumentationBinaryDataExtractor.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidInstrumentationBinaryDataExtractor.kt
@@ -69,7 +69,7 @@ internal class DefaultAndroidInstrumentationBinaryDataExtractor
).map { dependency ->
gradleDependencyToBazelDependency.map(project, dependency, matchedVariant)
} +
- dependenciesDataSource.collectMavenDeps(
+ dependenciesDataSource.externalDependencies(
project,
BuildGraphType(ConfigurationScope.ANDROID_TEST, matchedVariant.variant)
) +
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidLibraryDataExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidLibraryDataExtractor.kt
deleted file mode 100644
index 8c75de2b..00000000
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidLibraryDataExtractor.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.grab.grazel.migrate.android
-
-import com.grab.grazel.bazel.rules.ANDROIDX_GROUP
-import com.grab.grazel.bazel.rules.ANNOTATION_ARTIFACT
-import com.grab.grazel.bazel.rules.DAGGER_GROUP
-import com.grab.grazel.bazel.rules.DATABINDING_GROUP
-import com.grab.grazel.bazel.starlark.BazelDependency
-import com.grab.grazel.gradle.dependencies.BuildGraphType
-import com.grab.grazel.gradle.dependencies.DependenciesDataSource
-import com.grab.grazel.gradle.hasDatabinding
-import org.gradle.api.Project
-
-internal fun DependenciesDataSource.collectMavenDeps(
- project: Project, vararg buildGraphTypes: BuildGraphType
-): List = mavenDependencies(project, *buildGraphTypes)
- .filter {
- if (project.hasDatabinding) {
- it.group != DATABINDING_GROUP && (it.group != ANDROIDX_GROUP && it.name != ANNOTATION_ARTIFACT)
- } else true
- }.map {
- if (it.group == DAGGER_GROUP) {
- BazelDependency.StringDependency("//:dagger")
- } else {
- BazelDependency.MavenDependency(it)
- }
- }.distinct()
- .toList()
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidUnitTestDataExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidUnitTestDataExtractor.kt
index b4fb1d26..c660c36d 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidUnitTestDataExtractor.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/AndroidUnitTestDataExtractor.kt
@@ -79,7 +79,7 @@ internal class DefaultAndroidUnitTestDataExtractor @Inject constructor(
).map { dependent ->
gradleDependencyToBazelDependency.map(project, dependent, matchedVariant)
} +
- dependenciesDataSource.collectMavenDeps(
+ dependenciesDataSource.externalDependencies(
project,
BuildGraphType(ConfigurationScope.TEST, matchedVariant.variant)
) +
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/Crashlytics.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/Crashlytics.kt
index 123b54f0..1a6cb9b5 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/Crashlytics.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/android/Crashlytics.kt
@@ -17,6 +17,8 @@
package com.grab.grazel.migrate.android
import com.grab.grazel.GrazelExtension
+import com.grab.grazel.gradle.variant.AndroidVariantDataSource
+import com.grab.grazel.gradle.variant.getMigratableBuildVariants
import com.grab.grazel.gradle.variant.MatchedVariant
import com.grab.grazel.gradle.variant.nameSuffix
import org.gradle.api.Project
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculator.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculator.kt
new file mode 100644
index 00000000..15b0ccaf
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculator.kt
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.migrate.dependencies
+
+import com.grab.grazel.GrazelExtension
+import com.grab.grazel.bazel.rules.MavenInstallArtifact
+import com.grab.grazel.bazel.rules.MavenInstallArtifact.*
+import com.grab.grazel.bazel.rules.MavenInstallArtifact.Exclusion.*
+import com.grab.grazel.bazel.rules.MavenRepository.*
+import com.grab.grazel.di.qualifiers.RootProject
+import com.grab.grazel.gradle.RepositoryDataSource
+import com.grab.grazel.gradle.dependencies.IGNORED_ARTIFACT_GROUPS
+import com.grab.grazel.gradle.dependencies.model.ExcludeRule
+import com.grab.grazel.gradle.variant.DEFAULT_VARIANT
+import com.grab.grazel.gradle.variant.Variant
+import com.grab.grazel.gradle.variant.VariantBuilder
+import com.grab.grazel.gradle.variant.migratableConfigurations
+import com.grab.grazel.migrate.android.JetifierDataExtractor
+import com.grab.grazel.migrate.dependencies.model.MavenExternalArtifact
+import com.grab.grazel.migrate.dependencies.model.Repository
+import com.grab.grazel.migrate.dependencies.model.mergeWith
+import com.grab.grazel.migrate.dependencies.model.toMavenArtifact
+import com.grab.grazel.util.ansiCyan
+import com.grab.grazel.util.ansiYellow
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.ExternalDependency
+import org.gradle.api.artifacts.repositories.PasswordCredentials
+import org.gradle.api.artifacts.result.ResolutionResult
+import org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository
+import org.gradle.api.internal.artifacts.result.DefaultResolvedComponentResult
+import org.gradle.api.internal.artifacts.result.DefaultResolvedDependencyResult
+import java.util.*
+import javax.inject.Inject
+
+internal class MavenInstallArtifactsCalculator
+@Inject
+constructor(
+ @param:RootProject private val rootProject: Project,
+ private val repositoryDataSource: RepositoryDataSource,
+ private val grazelExtension: GrazelExtension,
+ private val variantBuilder: VariantBuilder,
+ private val mavenInstallStore: MavenInstallStore
+) {
+ private val excludeArtifactsDenyList by lazy {
+ grazelExtension.rules.mavenInstall.excludeArtifactsDenyList.get()
+ }
+ private val mavenInstallExtension get() = grazelExtension.rules.mavenInstall
+
+ /**
+ * Calculates `MavenInstallData` with exclude rules, dependency resolution, and repositories for
+ * the given `projectsToMigrate`.
+ */
+ fun get(
+ projectsToMigrate: List,
+ externalArtifacts: Set,
+ externalRepositories: Set
+ ): Set {
+ val artifactsMap = calculateArtifactsMap(projectsToMigrate)
+ return artifactsMap.mapNotNull { (variantName, artifacts) ->
+ val name = variantName.toMavenRepoName()
+ val mavenInstallArtifacts = artifacts.map { artifact ->
+ when {
+ artifact.excludeRules.isEmpty() -> SimpleArtifact(artifact.id)
+ else -> DetailedArtifact(
+ group = artifact.group,
+ artifact = artifact.name,
+ version = artifact.version,
+ exclusions = artifact.excludeRules.map {
+ SimpleExclusion("${it.group}:${it.artifact}")
+ }
+ )
+ }
+ }.sortedBy { it.id }.toSet().also { if (it.isEmpty()) return@mapNotNull null }
+
+ val mavenRepositories = artifacts
+ .asSequence()
+ .map { it.repository.repository }
+ .distinct()
+ .map { repo -> repo.toMavenRepository() }
+ .toSet()
+
+ val overridesFromExtension = mavenInstallExtension.overrideTargetLabels.get().toList()
+ val overridesFromArtifacts = artifacts
+ .mapNotNull(MavenExternalArtifact::overrideTarget)
+ .map { it.artifactShortId to it.label.toString() }
+ .toList()
+ val overrideTargets = (overridesFromArtifacts + overridesFromExtension)
+ .sortedWith(
+ compareBy(Pair::second).thenBy(Pair::first)
+ ).toMap()
+ MavenInstallData(
+ name = name,
+ artifacts = mavenInstallArtifacts,
+ externalArtifacts = if (variantName == DEFAULT_VARIANT) externalArtifacts else emptySet(),
+ repositories = mavenRepositories,
+ externalRepositories = if (variantName == DEFAULT_VARIANT) externalRepositories else emptySet(),
+ jetifierData = JetifierDataExtractor().extract(
+ rootProject = rootProject,
+ includeList = mavenInstallExtension.jetifyIncludeList.get(),
+ excludeList = mavenInstallExtension.jetifyExcludeList.get(),
+ allArtifacts = mavenInstallArtifacts.map(MavenInstallArtifact::id)
+ ),
+ failOnMissingChecksum = false,
+ excludeArtifacts = mavenInstallExtension.excludeArtifacts.get().toSet(),
+ overrideTargets = overrideTargets,
+ resolveTimeout = mavenInstallExtension.resolveTimeout,
+ artifactPinning = mavenInstallExtension.artifactPinning.enabled.get(),
+ versionConflictPolicy = mavenInstallExtension.versionConflictPolicy
+ )
+ }.sortedBy { it.name }.toSet()
+ }
+
+
+ /**
+ * Calculate a map of `variantName` and their [MavenExternalArtifact] instances from each project's
+ * configurations.
+ */
+ private fun calculateArtifactsMap(
+ projectsToMigrate: List
+ ): Map> {
+ val allVariants = projectsToMigrate.flatMap { variantBuilder.build(it) }
+
+ // Group variants and their configurations
+ val variantConfigs = allVariants
+ .groupBy(Variant<*>::name, Variant<*>::migratableConfigurations)
+ .mapValues { it.value.flatten().asSequence() }
+
+ // With the variant specific configurations, map to their direct dependencies.
+ val variantDependencies = resolveVariantDirectDependencies(variantConfigs)
+
+ // Reduce variant dependencies to only contain dependencies unique to them.
+ val reducedDependencies = reduceDependencies(
+ variantDependencies = variantDependencies,
+ variantsExtendsMap = allVariants
+ .groupBy(Variant<*>::name, Variant<*>::extendsFrom)
+ .mapValues { it.value.flatten().toSet() }
+ ).onEach { (variantName, dependencies) ->
+ // Cache the computed buckets into MavenInstallStore
+ val variantRepoName = variantName.toMavenRepoName()
+ dependencies.forEach { artifact ->
+ mavenInstallStore[variantRepoName, artifact.group] = artifact.name
+ }
+ }
+
+ // Filtered dependencies would not have accurate transitive closure in each bucket since
+ // dependencies might have been filtered in above step. To fix, we compute a new transitive
+ // graph using MavenInstallArtifact.componentResult
+ return computeFlatTransitiveGraph(reducedDependencies)
+ }
+
+ /**
+ * Takes a list of variant name and the list of [Configuration] in them to produce
+ * a `MavenExternalArtifact` of direct dependencies.
+ *
+ * The data required for `MavenExternalArtifact` comes from different places and this method merges
+ * from all of them to produce `Map` of variants and `MavenExternalArtifact`s. The is derived as
+ * stated below.
+ *
+ * * Repository is calculated from merging all repositories in the project.
+ * * Exclude rules are calculated from `ExternalDependency` provided from `configuration.dependencies`
+ * * [org.gradle.api.artifacts.ResolvableDependencies.getDependencies] is used to calculate the direct
+ * dependencies of a configuration.
+ * * [ResolutionResult] is used to calculate dependency versions after resolving the correct version
+ * and on which repository it was resolved from.
+ * Only [ResolutionResult] contains transitive dependencies' information hence it is retained in
+ * [MavenExternalArtifact.componentResult] for further processing
+ */
+ private fun resolveVariantDirectDependencies(
+ variantConfigs: Map>
+ ): Map> {
+ val repositories = repositoryDataSource.allRepositoriesByName
+ return variantConfigs.mapValues { (_, configurations) ->
+ val visitedComponents = mutableMapOf()
+ val excludeRules = calculateExcludeRules(configurations)
+ configurations
+ .filter { it.isCanBeResolved }
+ .flatMap { config ->
+ val resolvableDependencies = config.incoming
+ val directDependencies = resolvableDependencies
+ .dependencies
+ .asSequence()
+ .filterIsInstance()
+ .groupBy { "${it.group}:${it.name}" }
+ resolvableDependencies
+ .resolutionResult
+ .allComponents
+ .asSequence()
+ .filter { !it.toString().startsWith("project :") }
+ .filter { it.toString() !in visitedComponents }
+ .filter { it.moduleVersion!!.group !in IGNORED_ARTIFACT_GROUPS }
+ .filterIsInstance()
+ .filter { component ->
+ component.moduleVersion
+ ?.let { id -> "${id.group}:${id.name}" }
+ ?.let { it in directDependencies } ?: false
+ }.map { component ->
+ val version = component.moduleVersion!!
+ MavenExternalArtifact(
+ group = version.group,
+ version = version.version,
+ name = version.name,
+ repository = Repository(
+ name = component.repositoryName!!,
+ repository = repositories[component.repositoryName!!]!!
+ ),
+ excludeRules = excludeRules.getOrDefault(
+ version.toString(),
+ emptyList()
+ )
+ ).apply { componentResult = component }.also {
+ visitedComponents[it.id] = ""
+ }
+ }
+ }.pickMaxVersion()
+ }
+ }
+
+ /**
+ * From the [Sequence] of [MavenExternalArtifact] potentially containing duplicates, picks the
+ * max version of a dependency.
+ */
+ private fun Sequence.pickMaxVersion() = groupBy {
+ it.shortId
+ }.mapValues { (_, artifacts) ->
+ artifacts.maxOf { it }.let { maxVersionArtifact ->
+ when {
+ artifacts.size > 1 -> {
+ val others = artifacts.filter { it != maxVersionArtifact }
+ maxVersionArtifact.mergeWith(others = others)
+ }
+
+ else -> maxVersionArtifact
+ }
+ }
+ }.asSequence().map { it.value }
+
+ /**
+ * Calculate and merge exclude rules from all dependency declarations.
+ *
+ * @param configurations Configurations to merge exclude rules from
+ * @return Map of maven id and its merged exclude rules.
+ */
+ private fun calculateExcludeRules(
+ configurations: Sequence
+ ): Map> {
+ return configurations
+ .flatMap { config -> config.hierarchy.flatMap { it.dependencies } }
+ .filter { it.group != null }
+ .filterIsInstance()
+ .groupBy { dep -> "${dep.group}:${dep.name}:${dep.version}" }
+ .mapValues { (_, artifacts) ->
+ artifacts.flatMap { it.extractExcludeRules() }
+ .distinct()
+ .sortedBy { it.toString() }
+ }.filterValues { it.isNotEmpty() }
+ }
+
+
+ /**
+ * Variant to dependencies map can contain duplicates i.e dependencies in one variant can be
+ * also present in another. This method tries to ensure the base variants (default, test) contains
+ * all the common dependencies from their descendants by utilising [Variant.extendsFrom] property.
+ *
+ * For example:
+ *
+ * // and "default" extendsFrom "flavor"
+ * "default" = ["artifact1", "artifact2", "artifact3"]
+ * "flavor" = ["artifact1", "artifact3"]
+ * result = ["artifact3"]
+ */
+ private fun reduceDependencies(
+ variantDependencies: Map>,
+ variantsExtendsMap: Map* Variant name */String, Set* Extends name */String>>
+ ): Map* Variant name */String, Sequence> {
+ val results = variantsExtendsMap.mapValues { (currentVariant, extendsFrom) ->
+ if (currentVariant == DEFAULT_VARIANT || extendsFrom.isEmpty()) {
+ variantDependencies.getOrDefault(currentVariant, emptySequence())
+ } else {
+ val baseVariantDeps = extendsFrom
+ .asSequence()
+ .map { extends ->
+ variantDependencies.getOrDefault(
+ extends,
+ emptySequence()
+ )
+ }.flatten()
+ .distinctBy { it.id }
+ reduce(
+ currentDeps = variantDependencies.getOrDefault(currentVariant, emptySequence()),
+ baseVariantDeps = baseVariantDeps
+ )
+ }
+ }
+ return results
+ }
+
+ private fun reduce(
+ currentDeps: Sequence,
+ baseVariantDeps: Sequence
+ ): Sequence {
+ val baseVariantDepsMap = baseVariantDeps.groupBy { it.id }
+ // Filter all dependencies that are not in baseDeps
+ return currentDeps
+ .filter { !baseVariantDepsMap.contains(it.id) }
+ .sortedBy { it.id }
+ }
+
+
+ private fun computeFlatTransitiveGraph(
+ reducedDeps: Map>
+ ): Map> {
+ val repositories = repositoryDataSource.allRepositoriesByName
+ val results = mutableMapOf>()
+
+ // Compute the default classpath first
+ val defaultClasspath = flatten(reducedDeps[DEFAULT_VARIANT]!!, repositories)
+ .also { dependencies -> results[DEFAULT_VARIANT] = dependencies }
+
+ val defaultClasspathMap = defaultClasspath.associateBy(MavenExternalArtifact::shortId)
+
+ // With default classpath as base, compute the transitive graph of other classpaths
+ reducedDeps.filter { it.key != DEFAULT_VARIANT }
+ .mapValues { (_, dependencies) ->
+ flatten(
+ dependencies = dependencies,
+ repositories = repositories,
+ computeOverrides = true,
+ defaultClasspath = defaultClasspathMap
+ )
+ }.forEach { (variant, artifacts) -> results[variant] = artifacts }
+ return results
+ }
+
+ private fun flatten(
+ dependencies: Sequence,
+ repositories: Map,
+ computeOverrides: Boolean = false,
+ defaultClasspath: Map = emptyMap()
+ ): Sequence {
+ // Flatten transitive graph of each ComponentResult by visiting all dependencies
+ val visited = mutableMapOf()
+ return dependencies.flatMap { mavenArtifact ->
+ val result = mutableSetOf()
+
+ fun visit(componentResult: DefaultResolvedComponentResult, level: Int = 0) {
+ printIndented(level, componentResult.toString())
+ visited.getOrPut(
+ componentResult.moduleVersion.toString()
+ ) { componentResult }
+ if (componentResult.moduleVersion!!.group in IGNORED_ARTIFACT_GROUPS)
+ return
+
+ componentResult.dependencies
+ .asSequence()
+ .filterIsInstance()
+ .map { it.selected }
+ .filterIsInstance()
+ .map { selected ->
+ selected to selected.toMavenArtifact(
+ repositories = repositories,
+ defaultClasspath = if (computeOverrides) defaultClasspath else emptyMap()
+ )
+ }.filter { (_, artifact) -> artifact.group !in IGNORED_ARTIFACT_GROUPS }
+ .forEach { (selected, artifact: MavenExternalArtifact) ->
+ result += artifact
+ if (!visited.contains(selected.moduleVersion!!.toString())) {
+ visit(selected, level + 1)
+ }
+ }
+ }
+ result += mavenArtifact
+ visit(mavenArtifact.componentResult)
+ result
+ }.pickMaxVersion()
+ }
+
+ private fun DefaultMavenArtifactRepository.toMavenRepository(): DefaultMavenRepository {
+ val passwordCredentials = try {
+ getCredentials(PasswordCredentials::class.java)
+ } catch (e: Exception) {
+ // We only support basic auth now
+ null
+ }
+ return DefaultMavenRepository(
+ url.toString(),
+ passwordCredentials?.username,
+ passwordCredentials?.password
+ )
+ }
+
+ private fun ExternalDependency.extractExcludeRules(): Set {
+ return excludeRules
+ .asSequence()
+ .map {
+ @Suppress("USELESS_ELVIS") // Gradle lying, module can be null
+ (ExcludeRule(
+ it.group,
+ it.module ?: ""
+ ))
+ }
+ .filterNot { it.artifact.isNullOrBlank() }
+ .filterNot { it.toString() in excludeArtifactsDenyList }
+ .toSet()
+ }
+
+ private fun printIndented(level: Int, message: String) {
+ val prefix = if (level == 0) "─" else " └"
+ val indent = (0..level * 2).joinToString(separator = "") { "─" }
+ val msg = message.let { if (level == 0) it.ansiCyan else it.ansiYellow }
+ rootProject.logger.info("$prefix$indent $msg")
+ }
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallStore.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallStore.kt
new file mode 100644
index 00000000..f2c257ba
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallStore.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.migrate.dependencies
+
+import com.grab.grazel.bazel.starlark.BazelDependency.MavenDependency
+import java.util.concurrent.ConcurrentHashMap
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Data structure to hold information about generated maven repositories in `WORKSPACE`
+ */
+internal interface MavenInstallStore {
+ /**
+ * For a given variant hierarchy and `group` and `name`, the function will try to look
+ * for the dependency in each of the variant hierarchy and return the first one found.
+ *
+ * For example, if `androidx.activity:activity` is given and it was categorized
+ * under `@maven` repository then will return `@maven//:androidx_activity_activity`
+ * in form of [MavenDependency]
+ */
+ operator fun get(variants: Set, group: String, name: String): MavenDependency?
+
+ operator fun set(variantRepoName: String, group: String, name: String)
+
+ val size: Int
+}
+
+@Singleton
+class DefaultMavenInstallStore
+@Inject
+constructor() : MavenInstallStore {
+
+ private data class ArtifactKey(
+ val variant: String,
+ val group: String,
+ val name: String,
+ )
+
+ private val map = ConcurrentHashMap()
+
+ override val size: Int get() = map.size
+
+ override fun get(variants: Set, group: String, name: String): MavenDependency {
+ fun get(repo: String): MavenDependency? =
+ if (map.containsKey(ArtifactKey(repo, group, name))) {
+ MavenDependency(repo, group, name)
+ } else null
+
+ return variants.asSequence().mapNotNull { variant ->
+ val repoName = variant.toMavenRepoName()
+ get(repoName)
+ }.firstOrNull() ?: get("maven") ?: run {
+ // When no dependency is found in the index, assume @maven. This could be incorrect
+ // but makes for easier testing
+ MavenDependency(group = group, name = name)
+ }
+ }
+
+ override fun set(variantRepoName: String, group: String, name: String) {
+ map[ArtifactKey(variantRepoName, group, name)] = variantRepoName
+ }
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/MavenExternalArtifact.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/MavenExternalArtifact.kt
index 86fa2687..baa8f1ca 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/MavenExternalArtifact.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/dependencies/model/MavenExternalArtifact.kt
@@ -17,10 +17,12 @@
package com.grab.grazel.migrate.dependencies.model
import com.grab.grazel.bazel.starlark.BazelDependency.MavenDependency
+import com.grab.grazel.gradle.dependencies.model.ExcludeRule
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.Versioned
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionComparator
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.Version
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser
+import org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository
import org.gradle.api.internal.artifacts.result.DefaultResolvedComponentResult
internal data class MavenExternalArtifact(
@@ -62,4 +64,34 @@ internal fun MavenExternalArtifact.mergeWith(others: List
).apply {
componentResult = current.componentResult
}
+}
+
+internal fun DefaultResolvedComponentResult.toMavenArtifact(
+ repositories: Map,
+ excludeRules: List = emptyList(),
+ defaultClasspath: Map = emptyMap()
+): MavenExternalArtifact {
+ val version = moduleVersion!!
+ val shortId = version.group + ":" + version.name
+ val overrideTarget = if (defaultClasspath.isEmpty()) null else {
+ when (shortId) {
+ in defaultClasspath -> OverrideTarget(
+ artifactShortId = shortId,
+ label = MavenDependency(group = version.group, name = version.name)
+ )
+
+ else -> null
+ }
+ }
+ return MavenExternalArtifact(
+ group = version.group,
+ version = version.version,
+ name = version.name,
+ repository = Repository(
+ name = repositoryName!!,
+ repository = repositories[repositoryName!!]!!
+ ),
+ excludeRules = excludeRules,
+ overrideTarget = overrideTarget
+ ).also { it.componentResult = this }
}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/internal/WorkspaceBuilder.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/internal/WorkspaceBuilder.kt
index 69d78592..cdbce11d 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/internal/WorkspaceBuilder.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/internal/WorkspaceBuilder.kt
@@ -19,40 +19,32 @@ package com.grab.grazel.migrate.internal
import com.android.build.gradle.BaseExtension
import com.grab.grazel.GrazelExtension
import com.grab.grazel.bazel.rules.DAGGER_ARTIFACTS
-import com.grab.grazel.bazel.rules.DAGGER_GROUP
import com.grab.grazel.bazel.rules.DAGGER_REPOSITORIES
-import com.grab.grazel.bazel.rules.DATABINDING_ARTIFACTS
-import com.grab.grazel.bazel.rules.DATABINDING_GROUP
import com.grab.grazel.bazel.rules.GRAB_BAZEL_COMMON_ARTIFACTS
-import com.grab.grazel.bazel.rules.MavenRepository.DefaultMavenRepository
import com.grab.grazel.bazel.rules.androidNdkRepository
import com.grab.grazel.bazel.rules.androidSdkRepository
import com.grab.grazel.bazel.rules.bazelCommonRepository
import com.grab.grazel.bazel.rules.daggerWorkspaceRules
-import com.grab.grazel.bazel.rules.jvmRules
import com.grab.grazel.bazel.rules.kotlinCompiler
import com.grab.grazel.bazel.rules.kotlinRepository
import com.grab.grazel.bazel.rules.loadBazelCommonArtifacts
import com.grab.grazel.bazel.rules.loadDaggerArtifactsAndRepositories
+import com.grab.grazel.bazel.rules.mavenInstall
import com.grab.grazel.bazel.rules.registerKotlinToolchain
import com.grab.grazel.bazel.rules.toolAndroidRepository
import com.grab.grazel.bazel.rules.workspace
import com.grab.grazel.bazel.starlark.LoadStrategy
import com.grab.grazel.bazel.starlark.StatementsBuilder
+import com.grab.grazel.bazel.starlark.add
import com.grab.grazel.bazel.starlark.statements
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.GradleProjectInfo
-import com.grab.grazel.gradle.RepositoryDataSource
-import com.grab.grazel.gradle.dependencies.DependenciesDataSource
-import com.grab.grazel.gradle.dependencies.MavenArtifact
-import com.grab.grazel.gradle.dependencies.toMavenInstallArtifact
import com.grab.grazel.gradle.isAndroidApplication
import com.grab.grazel.migrate.BazelFileBuilder
-import com.grab.grazel.migrate.android.JetifierDataExtractor
import com.grab.grazel.migrate.android.parseCompileSdkVersion
import com.grab.grazel.migrate.dependencies.ArtifactsPinner
+import com.grab.grazel.migrate.dependencies.MavenInstallArtifactsCalculator
import org.gradle.api.Project
-import org.gradle.api.artifacts.repositories.PasswordCredentials
import org.gradle.kotlin.dsl.the
import javax.inject.Inject
import javax.inject.Singleton
@@ -62,18 +54,16 @@ internal class WorkspaceBuilder(
private val projectsToMigrate: List,
private val grazelExtension: GrazelExtension,
private val gradleProjectInfo: GradleProjectInfo,
- private val dependenciesDataSource: DependenciesDataSource,
- private val repositoryDataSource: RepositoryDataSource,
- private val artifactsPinner: ArtifactsPinner
+ private val artifactsPinner: ArtifactsPinner,
+ private val mavenInstallArtifactsCalculator: MavenInstallArtifactsCalculator
) : BazelFileBuilder {
@Singleton
class Factory @Inject constructor(
@param:RootProject private val rootProject: Project,
private val grazelExtension: GrazelExtension,
private val gradleProjectInfo: GradleProjectInfo,
- private val dependenciesDataSource: DependenciesDataSource,
- private val repositoryDataSource: RepositoryDataSource,
private val artifactsPinner: ArtifactsPinner,
+ private val mavenInstallArtifactsCalculator: MavenInstallArtifactsCalculator
) {
fun create(
projectsToMigrate: List
@@ -82,16 +72,11 @@ internal class WorkspaceBuilder(
projectsToMigrate,
grazelExtension,
gradleProjectInfo,
- dependenciesDataSource,
- repositoryDataSource,
- artifactsPinner
+ artifactsPinner,
+ mavenInstallArtifactsCalculator
)
}
- private val dependenciesExtension get() = grazelExtension.dependencies
- private val mavenInstall get() = grazelExtension.rules.mavenInstall
- private val hasDatabinding = gradleProjectInfo.hasDatabinding
-
override fun build() = statements(loadStrategy = LoadStrategy.Inline()) {
workspace(name = rootProject.name)
@@ -108,7 +93,6 @@ internal class WorkspaceBuilder(
private fun StatementsBuilder.buildJvmRules() {
val hasDagger = gradleProjectInfo.hasDagger
-
val externalArtifacts = mutableListOf()
val externalRepositories = mutableListOf()
@@ -123,63 +107,31 @@ internal class WorkspaceBuilder(
loadBazelCommonArtifacts(grazelExtension.rules.bazelCommon.repository.name)
externalArtifacts += GRAB_BAZEL_COMMON_ARTIFACTS
- val mavenArtifacts = dependenciesDataSource
- .resolvedArtifactsFor(
- projects = projectsToMigrate,
- overrideArtifactVersions = dependenciesExtension.overrideArtifactVersions.get()
- ).asSequence()
- .filter {
- val dagger = if (hasDagger) !it.id.contains(DAGGER_GROUP) else true
- val db = if (hasDatabinding) !it.id.contains(DATABINDING_GROUP) else true
- dagger && db
- }
-
- val databindingArtifacts = if (!hasDatabinding) emptySequence() else {
- DATABINDING_ARTIFACTS.map(MavenArtifact::toMavenInstallArtifact).asSequence()
+ val mavenInstall = grazelExtension.rules.mavenInstall.apply {
+ add(repository)
+ }
+ mavenInstallArtifactsCalculator.get(
+ projectsToMigrate,
+ externalArtifacts.toSortedSet(),
+ externalRepositories.toSortedSet()
+ ).forEach { mavenInstallData ->
+ mavenInstall(
+ name = mavenInstallData.name,
+ rulesJvmExternalName = mavenInstall.repository.name,
+ artifacts = mavenInstallData.artifacts,
+ externalArtifacts = mavenInstallData.externalArtifacts,
+ mavenRepositories = mavenInstallData.repositories,
+ externalRepositories = mavenInstallData.externalRepositories,
+ jetify = mavenInstallData.jetifierData.isEnabled,
+ jetifyIncludeList = mavenInstallData.jetifierData.includeList,
+ failOnMissingChecksum = false,
+ resolveTimeout = mavenInstallData.resolveTimeout,
+ excludeArtifacts = mavenInstallData.excludeArtifacts,
+ overrideTargets = mavenInstallData.overrideTargets,
+ versionConflictPolicy = mavenInstallData.versionConflictPolicy,
+ artifactPinning = artifactsPinner.isEnabled
+ )
}
-
- val repositories = repositoryDataSource.supportedRepositories
- .map { repo ->
- val passwordCredentials = if (grazelExtension.rules.mavenInstall.includeCredentials) {
- try {
- repo.getCredentials(PasswordCredentials::class.java)
- } catch (e: Exception) {
- // We only support basic auth now
- null
- }
- } else null
- DefaultMavenRepository(
- repo.url.toString(),
- passwordCredentials?.username,
- passwordCredentials?.password
- )
- }
-
- val allArtifacts = (mavenArtifacts + databindingArtifacts).sortedBy { it.id }.toSet()
-
- val jetifierData = JetifierDataExtractor().extract(
- rootProject = rootProject,
- includeList = mavenInstall.jetifyIncludeList.get(),
- excludeList = mavenInstall.jetifyExcludeList.get(),
- allArtifacts = allArtifacts.map { it.id }
- )
-
- jvmRules(
- rulesJvmExternalRule = mavenInstall.repository,
- artifacts = allArtifacts,
- mavenRepositories = (repositories).distinct().toList(),
- externalArtifacts = externalArtifacts.toList(),
- externalRepositories = externalRepositories.toList(),
- jetify = jetifierData.isEnabled,
- jetifyIncludeList = jetifierData.includeList,
- failOnMissingChecksum = false,
- artifactPinning = artifactsPinner.isEnabled,
- mavenInstallJson = artifactsPinner.mavenInstallJson(),
- resolveTimeout = mavenInstall.resolveTimeout,
- excludeArtifacts = mavenInstall.excludeArtifacts.get(),
- overrideTargets = mavenInstall.overrideTargetLabels.get(),
- versionConflictPolicy = mavenInstall.versionConflictPolicy,
- )
}
@@ -201,7 +153,7 @@ internal class WorkspaceBuilder(
}
}
- internal fun addAndroidSdkRepositories(statementsBuilder: StatementsBuilder): Unit =
+ internal fun addAndroidSdkRepositories(statementsBuilder: StatementsBuilder) {
statementsBuilder.run {
// Find the android application module and extract compileSdk and buildToolsVersion
rootProject
@@ -222,6 +174,7 @@ internal class WorkspaceBuilder(
ndkApiLevel = grazelExtension.android.ndkApiLevel
)
}
+ }
private fun validateNdkApiLevel() {
val ndkApiLevel = grazelExtension.android.ndkApiLevel ?: return
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinProjectDataExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinProjectDataExtractor.kt
index 832ac0f1..103445e2 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinProjectDataExtractor.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinProjectDataExtractor.kt
@@ -27,7 +27,6 @@ import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.dependencies.GradleDependencyToBazelDependency
import com.grab.grazel.gradle.hasKotlinAndroidExtensions
import com.grab.grazel.migrate.android.SourceSetType
-import com.grab.grazel.migrate.android.collectMavenDeps
import com.grab.grazel.migrate.android.filterSourceSetPaths
import com.grab.grazel.migrate.dependencies.calculateDirectDependencyTags
import dagger.Lazy
@@ -71,7 +70,10 @@ constructor(
).map { dependent ->
gradleDependencyToBazelDependency.map(project, dependent, null)
} +
- dependenciesDataSource.collectMavenDeps(project) +
+ dependenciesDataSource.externalDependencies(
+ project,
+ BuildGraphType(ConfigurationScope.BUILD)
+ ) +
project.androidJarDeps() +
project.kotlinParcelizeDeps()
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinUnitTestDataExtractor.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinUnitTestDataExtractor.kt
index 6cf9b329..90ae2525 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinUnitTestDataExtractor.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/migrate/kotlin/KotlinUnitTestDataExtractor.kt
@@ -26,7 +26,6 @@ import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.dependencies.GradleDependencyToBazelDependency
import com.grab.grazel.migrate.android.FORMAT_UNIT_TEST_NAME
import com.grab.grazel.migrate.android.SourceSetType
-import com.grab.grazel.migrate.android.collectMavenDeps
import com.grab.grazel.migrate.android.filterNonDefaultSourceSetDirs
import com.grab.grazel.migrate.android.filterSourceSetPaths
import com.grab.grazel.migrate.common.calculateTestAssociate
@@ -77,7 +76,7 @@ internal class DefaultKotlinUnitTestDataExtractor @Inject constructor(
}
)
addAll(
- dependenciesDataSource.collectMavenDeps(
+ dependenciesDataSource.externalDependencies(
project,
BuildGraphType(ConfigurationScope.TEST)
)
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ComputeWorkspaceDependenciesTask.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ComputeWorkspaceDependenciesTask.kt
new file mode 100644
index 00000000..d7a51220
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ComputeWorkspaceDependenciesTask.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.tasks.internal
+
+import com.grab.grazel.gradle.dependencies.model.ResolveDependenciesResult
+import com.grab.grazel.gradle.dependencies.model.ResolvedDependency
+import com.grab.grazel.gradle.dependencies.model.allDependencies
+import com.grab.grazel.gradle.dependencies.model.versionInfo
+import com.grab.grazel.gradle.variant.DEFAULT_VARIANT
+import com.grab.grazel.gradle.variant.VariantBuilder
+import dagger.Lazy
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.file.RegularFile
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.kotlin.dsl.register
+import java.io.File
+import java.util.stream.Collectors
+import java.util.stream.Collectors.flatMapping
+import java.util.stream.Collectors.groupingByConcurrent
+import kotlin.streams.toList
+
+@CacheableTask
+abstract class ComputeWorkspaceDependenciesTask : DefaultTask() {
+ @get:InputFiles
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val compileDependenciesJsons: ListProperty
+
+ @get:OutputFile
+ abstract val mergedDependencies: RegularFileProperty
+
+ init {
+ group = GRAZEL_TASK_GROUP
+ description = "Computes external maven dependencies for bazel"
+ }
+
+ @TaskAction
+ fun action() {
+ val flattenClasspath = compileDependenciesJsons.get()
+ .parallelStream()
+ .map(ResolveDependenciesResult::fromJson)
+ .collect(
+ // Group variantName to dependencies
+ groupingByConcurrent(
+ ResolveDependenciesResult::variantName,
+ // Extract compile classpath and flatten it by including the transitive closure
+ flatMapping(
+ { resolvedDependency ->
+ resolvedDependency
+ .dependencies
+ .getValue("compile")
+ .stream()
+ .flatMap { it.allDependencies.stream() }
+ .parallel()
+ },
+ // To find the max version, need to group by their shortID
+ groupingByConcurrent(
+ ResolvedDependency::shortId,
+ // Once grouped, reduce it and only pick the highest version
+ Collectors.reducing(null) { old, new ->
+ when {
+ old == null -> new
+ new == null -> old
+ else -> if (old.versionInfo > new.versionInfo) old else new
+ }
+ }
+ )
+ )
+ )
+ )
+
+ val defaultClasspath = flattenClasspath.getValue(DEFAULT_VARIANT)
+
+ val finalClasspath = flattenClasspath
+ .entries
+ .parallelStream()
+ .filter { it.key != DEFAULT_VARIANT }
+ .collect(
+ Collectors.toConcurrentMap(
+ { it.key },
+ { (variantName, dependencies) ->
+ dependencies
+ .values
+ .stream()
+ .map { dependency ->
+ if (dependency!!.shortId in defaultClasspath) {
+ // TODO(arun) Add override target and check for all parent classpaths
+ println(dependency.shortId)
+ }
+ dependency
+ }.toList()
+ }
+ )
+ ).apply {
+ put(DEFAULT_VARIANT, defaultClasspath.values.toList())
+ }.filterValues { it.isNotEmpty() }
+
+ mergedDependencies.asFile.get().writeText(Json.encodeToString(finalClasspath.toMap()))
+ }
+
+ companion object {
+ private const val TASK_NAME = "computeWorkspaceDependencies"
+ internal fun register(rootProject: Project, variantBuilderProvider: Lazy) {
+ val computeTask = rootProject.tasks
+ .register(TASK_NAME) {
+ mergedDependencies.set(
+ File(
+ rootProject.buildDir,
+ "grazel/mergedDependencies.json"
+ )
+ )
+ }
+ ResolveVariantDependenciesTask.register(
+ rootProject,
+ variantBuilderProvider
+ ) { taskProvider ->
+ computeTask.configure {
+ compileDependenciesJsons.add(taskProvider.flatMap { it.resolvedDependencies })
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ResolveVariantDependenciesTask.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ResolveVariantDependenciesTask.kt
new file mode 100644
index 00000000..7c78b0cc
--- /dev/null
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/ResolveVariantDependenciesTask.kt
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2023 Grabtaxi Holdings PTE LTD (GRAB)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.grab.grazel.tasks.internal
+
+import com.grab.grazel.gradle.dependencies.ResolvedComponentsVisitor
+import com.grab.grazel.gradle.dependencies.model.ExcludeRule
+import com.grab.grazel.gradle.dependencies.model.ResolveDependenciesResult
+import com.grab.grazel.gradle.dependencies.model.ResolvedDependency
+import com.grab.grazel.gradle.variant.Variant
+import com.grab.grazel.gradle.variant.VariantBuilder
+import com.grab.grazel.gradle.variant.isBase
+import com.grab.grazel.util.dependsOn
+import dagger.Lazy
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.artifacts.ExternalDependency
+import org.gradle.api.artifacts.result.ResolvedComponentResult
+import org.gradle.api.file.RegularFile
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.MapProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.TaskProvider
+import org.gradle.kotlin.dsl.named
+import org.gradle.kotlin.dsl.register
+import java.io.File
+import kotlin.streams.asSequence
+
+@CacheableTask
+abstract class ResolveVariantDependenciesTask : DefaultTask() {
+
+ @get:Input
+ abstract val variantName: Property
+
+ @get:Input
+ abstract val base: Property
+
+ @get:Input
+ abstract val compileConfiguration: ListProperty
+
+ @get:Input
+ abstract val compileDirectDependencies: MapProperty
+
+ @get:Input
+ abstract val compileExcludeRules: MapProperty>
+
+ @get:Input
+ abstract val annotationProcessorConfiguration: ListProperty
+
+ @get:Input
+ abstract val kotlinCompilerPluginConfiguration: ListProperty
+
+ @get:OutputFile
+ abstract val resolvedDependencies: RegularFileProperty
+
+ @get:InputFiles
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val baseDependenciesJsons: ListProperty
+
+ init {
+ group = GRAZEL_TASK_GROUP
+ description = "Resolves configurations and serialized them to be read on later"
+ }
+
+ private fun ListProperty.toResolvedDependencies(
+ directDependenciesMap: Map = emptyMap(),
+ baseDependenciesMap: Map = emptyMap(),
+ excludeRulesMap: Map> = emptyMap(),
+ removeTransitives: Boolean = false
+ ): Set {
+ return get().asSequence().flatMap { root ->
+ ResolvedComponentsVisitor()
+ .visit(root, logger::info) { component, repository, dependencies ->
+ val version = component.moduleVersion!!
+ val shortId = version.group + ":" + version.name
+ val isDirect = shortId in directDependenciesMap
+ if (shortId !in baseDependenciesMap)
+ ResolvedDependency(
+ id = component.toString(),
+ shortId = shortId,
+ direct = isDirect,
+ version = version.version,
+ dependencies = dependencies,
+ repository = repository,
+ excludeRules = excludeRulesMap.getOrDefault(shortId, emptySet())
+ )
+ else null
+ }.asSequence()
+ }.filter { if (removeTransitives) it.direct else true }.toSet()
+ }
+
+ @TaskAction
+ fun action() {
+ val baseDependenciesMap = buildMap {
+ if (!base.get()) {
+ // For non baseVariant tasks, every dependency that appears in the base task's json output
+ // is consider direct dependencies, hence parse it add to [directDependenciesMap]
+ baseDependenciesJsons.get()
+ .stream()
+ .parallel()
+ .map(ResolveDependenciesResult.Companion::fromJson)
+ .sequential()
+ .asSequence()
+ .flatMap { it.dependencies.getValue("compile") } // Make this configurable
+ .groupBy(ResolvedDependency::shortId, ResolvedDependency::direct)
+ .mapValues { entry -> entry.value.any { it } }
+ .forEach { (shortId, direct) ->
+ if (direct) put(shortId, shortId)
+ }
+ }
+ }
+
+ val resolvedDependenciesResult = ResolveDependenciesResult(
+ variantName = variantName.get(),
+ dependencies = buildMap {
+ put(
+ "compile",
+ compileConfiguration.toResolvedDependencies(
+ directDependenciesMap = compileDirectDependencies.get(),
+ baseDependenciesMap = baseDependenciesMap,
+ excludeRulesMap = compileExcludeRules.get(),
+ removeTransitives = !base.get()
+ )
+ )
+ /*put(
+ "annotationProcessing",
+ annotationProcessorConfiguration.toResolvedDependencies()
+ )
+ put("kotlinExtension", kotlinCompilerPluginConfiguration.toResolvedDependencies())*/
+ }
+ )
+ resolvedDependencies.get()
+ .asFile
+ .writeText(Json.encodeToString(resolvedDependenciesResult))
+ }
+
+ companion object {
+ internal fun register(
+ rootProject: Project,
+ variantBuilderProvider: Lazy,
+ subprojectTaskConfigure: (TaskProvider) -> Unit
+ ) {
+ // Register a lifecycle to aggregate all subproject tasks
+ val rootResolveDependenciesTask = rootProject.tasks.register("resolveDependencies") {}
+ rootProject.afterEvaluate {
+ val variantBuilder = variantBuilderProvider.get()
+ subprojects.forEach { project ->
+ // First pass to create all tasks
+ variantBuilder.onVariants(project) { variant ->
+ processVariant(project, variant, rootResolveDependenciesTask)
+ }
+ // Second pass to establish inter dependencies based on extendsFrom property
+ variantBuilder.onVariants(project) { variant ->
+ configureVariantTaskDependencies(project, variant, subprojectTaskConfigure)
+ }
+ }
+ }
+ }
+
+ private fun ExternalDependency.extractExcludeRules(): Set {
+ return excludeRules
+ .map {
+ @Suppress("USELESS_ELVIS") // Gradle lying, module can be null
+ (ExcludeRule(
+ it.group,
+ it.module ?: ""
+ ))
+ }
+ .filterNot { it.artifact.isNullOrBlank() }
+ // TODO(arun) Respect excludeArtifactsDenyList
+ //.filterNot { it.toString() in excludeArtifactsDenyList }
+ .toSet()
+ }
+
+ private fun processVariant(
+ project: Project,
+ variant: Variant<*>,
+ rootResolveDependenciesTask: TaskProvider
+ ) {
+ val resolveVariantDependenciesTask = project.tasks
+ .register(variant.name + "ResolveDependencies") {
+ variantName.set(variant.name)
+ base.set(variant.isBase)
+ compileConfiguration.addAll(project.provider {
+ variant.compileConfiguration
+ .map { it.incoming.resolutionResult.root }
+ .toList()
+ })
+ compileDirectDependencies.set(project.provider {
+ variant.compileConfiguration
+ .asSequence()
+ .flatMap { it.incoming.dependencies }
+ .filterIsInstance()
+ .associate { "${it.group}:${it.name}" to "${it.group}:${it.name}" }
+ })
+ compileExcludeRules.set(project.provider {
+ variant.compileConfiguration
+ .asSequence()
+ .flatMap { it.incoming.dependencies }
+ .filterIsInstance()
+ .groupBy { dep -> "${dep.group}:${dep.name}" }
+ .mapValues { (_, artifacts) ->
+ artifacts.flatMap { it.extractExcludeRules() }.toSet()
+ }.filterValues { it.isNotEmpty() }
+
+ })
+ /* runtimeConfiguration.addAll(project.provider {
+ variant.runtimeConfiguration
+ .map { it.incoming.resolutionResult.root }
+ .toImmutableList()
+ })
+ annotationProcessorConfiguration.addAll(project.provider {
+ variant.annotationProcessorConfiguration.map { it.incoming.resolutionResult.root }
+ })
+ kotlinCompilerPluginConfiguration.addAll(project.provider {
+ variant.kotlinCompilerPluginConfiguration
+ .map { it.incoming.resolutionResult.root }
+ .toList()
+ })*/
+ resolvedDependencies.set(
+ File(
+ project.buildDir,
+ "grazel/${variant.name}/dependencies.json"
+ )
+ )
+ }
+ rootResolveDependenciesTask.dependsOn(resolveVariantDependenciesTask)
+ }
+
+
+ private fun configureVariantTaskDependencies(
+ project: Project,
+ variant: Variant<*>,
+ subprojectTaskConfigure: (TaskProvider) -> Unit
+ ) {
+ val tasks = project.tasks
+ val taskName = variant.name + "ResolveDependencies"
+ val resolveTask = tasks.named(taskName)
+ resolveTask.configure {
+ val variantTask = this
+ variant.extendsFrom.forEach { extends ->
+ try {
+ val taskName = extends + "ResolveDependencies"
+ val extendsTask = tasks.named(taskName)
+ variantTask.baseDependenciesJsons.add(extendsTask.flatMap { it.resolvedDependencies })
+ } catch (e: Exception) {
+ // TODO(arun) Handle gracefully
+ }
+ }
+ }
+ subprojectTaskConfigure(resolveTask)
+ }
+ }
+}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/TasksManager.kt b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/TasksManager.kt
index ed375189..57123fc6 100644
--- a/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/TasksManager.kt
+++ b/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/tasks/internal/TasksManager.kt
@@ -63,6 +63,7 @@ constructor(
* See [Task Graph](https://grab.github.io/Grazel/gradle_tasks/#task-graph)
*/
fun configTasks() {
+ ComputeWorkspaceDependenciesTask.register(rootProject, grazelComponent.variantBuilder())
// Root bazel file generation task that should run at the start of migration
val rootGenerateBazelScriptsTasks = GenerateRootBazelScriptsTask.register(
rootProject,
diff --git a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/DefaultDependenciesDataSourceTest.kt b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/DefaultDependenciesDataSourceTest.kt
index d92b110f..163b9609 100644
--- a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/DefaultDependenciesDataSourceTest.kt
+++ b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/DefaultDependenciesDataSourceTest.kt
@@ -25,7 +25,10 @@ import com.grab.grazel.fake.FLAVOR2
import com.grab.grazel.fake.FakeAndroidVariantDataSource
import com.grab.grazel.gradle.dependencies.*
import com.grab.grazel.gradle.variant.AndroidVariantsExtractor
+import com.grab.grazel.gradle.variant.DefaultAndroidVariantDataSource
import com.grab.grazel.gradle.variant.DefaultAndroidVariantsExtractor
+import com.grab.grazel.gradle.variant.DefaultVariantBuilder
+import com.grab.grazel.migrate.dependencies.DefaultMavenInstallStore
import org.gradle.api.Project
import org.gradle.kotlin.dsl.add
import org.gradle.kotlin.dsl.configure
@@ -91,6 +94,12 @@ class DefaultDependenciesDataSourceTest : GrazelPluginTest() {
dependencyResolutionService = DefaultDependencyResolutionService.register(rootProject),
grazelExtension = GrazelExtension(rootProject),
androidVariantsExtractor = androidVariantsExtractor,
+ variantBuilder = DefaultVariantBuilder(
+ DefaultAndroidVariantDataSource(
+ androidVariantsExtractor
+ )
+ ),
+ mavenInstallStore = DefaultMavenInstallStore()
)
}
@@ -154,6 +163,12 @@ class DefaultDependenciesDataSourceTest : GrazelPluginTest() {
dependencyResolutionService = DefaultDependencyResolutionService.register(rootProject),
grazelExtension = GrazelExtension(rootProject),
androidVariantsExtractor = androidVariantsExtractor,
+ variantBuilder = DefaultVariantBuilder(
+ DefaultAndroidVariantDataSource(
+ androidVariantsExtractor
+ )
+ ),
+ mavenInstallStore = DefaultMavenInstallStore()
)
assertTrue(
"hasIgnoredArtifacts returns true when project contains any ignored artifacts",
@@ -181,6 +196,12 @@ class DefaultDependenciesDataSourceTest : GrazelPluginTest() {
dependencyResolutionService = DefaultDependencyResolutionService.register(rootProject),
grazelExtension = GrazelExtension(rootProject),
androidVariantsExtractor = DefaultAndroidVariantsExtractor(),
+ variantBuilder = DefaultVariantBuilder(
+ DefaultAndroidVariantDataSource(
+ androidVariantsExtractor
+ )
+ ),
+ mavenInstallStore = DefaultMavenInstallStore()
)
val dependencyArtifactMap = dependenciesDataSource.dependencyArtifactMap(
rootProject,
diff --git a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculatorTest.kt b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculatorTest.kt
deleted file mode 100644
index 31e1115f..00000000
--- a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/gradle/dependencies/MavenInstallArtifactsCalculatorTest.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.grab.grazel.gradle.dependencies
-
-import com.android.build.gradle.AppExtension
-import com.grab.grazel.buildProject
-import com.grab.grazel.fake.FLAVOR1
-import com.grab.grazel.fake.FLAVOR2
-import com.grab.grazel.gradle.ANDROID_APPLICATION_PLUGIN
-import com.grab.grazel.util.addGrazelExtension
-import com.grab.grazel.util.createGrazelComponent
-import com.grab.grazel.util.doEvaluate
-import org.gradle.api.Project
-import org.gradle.kotlin.dsl.configure
-import org.gradle.kotlin.dsl.dependencies
-import org.gradle.kotlin.dsl.repositories
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-
-class MavenInstallArtifactsCalculatorTest {
- private lateinit var rootProject: Project
- private lateinit var androidBinary: Project
- private lateinit var mavenInstallArtifactsCalculator: MavenInstallArtifactsCalculator
-
- @Before
- fun setUp() {
- rootProject = buildProject("root")
- rootProject.addGrazelExtension()
- val grazelComponent = rootProject.createGrazelComponent()
- mavenInstallArtifactsCalculator = grazelComponent.mavenInstallArtifactsCalculator().get()
- androidBinary = buildProject("app-binary", parent = rootProject)
- configureAndroidBinary()
- }
-
- private fun configureAndroidBinary() {
- androidBinary.run {
- plugins.apply {
- apply(ANDROID_APPLICATION_PLUGIN)
- }
- repositories {
- mavenCentral()
- google()
- }
- extensions.configure {
- defaultConfig {
- compileSdkVersion(29)
- buildToolsVersion("29.0.3")
- }
- flavorDimensions("service")
- productFlavors {
- create(FLAVOR1) {
- dimension = "service"
- }
- create(FLAVOR2) {
- dimension = "service"
- }
- }
- }
- dependencies {
- add(
- "implementation",
- "androidx.appcompat:appcompat:1.3.0"
- )
- }
- doEvaluate()
- }
- }
-
- @After
- fun tearDown() {
- }
-
- @Test
- fun `test`() {
- }
-}
\ No newline at end of file
diff --git a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/android/DefaultAndroidUnitTestDataExtractorTest.kt b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/android/DefaultAndroidUnitTestDataExtractorTest.kt
index f8236728..b08de53a 100644
--- a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/android/DefaultAndroidUnitTestDataExtractorTest.kt
+++ b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/android/DefaultAndroidUnitTestDataExtractorTest.kt
@@ -33,7 +33,9 @@ import com.grab.grazel.gradle.dependencies.GradleDependencyToBazelDependency
import com.grab.grazel.gradle.variant.AndroidVariantsExtractor
import com.grab.grazel.gradle.variant.DefaultAndroidVariantDataSource
import com.grab.grazel.gradle.variant.DefaultAndroidVariantsExtractor
+import com.grab.grazel.gradle.variant.DefaultVariantBuilder
import com.grab.grazel.gradle.variant.MatchedVariant
+import com.grab.grazel.migrate.dependencies.DefaultMavenInstallStore
import com.grab.grazel.util.doEvaluate
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
@@ -104,6 +106,12 @@ class DefaultAndroidUnitTestDataExtractorTest : GrazelPluginTest() {
dependencyResolutionService = DefaultDependencyResolutionService.register(rootProject),
grazelExtension = GrazelExtension(rootProject),
androidVariantsExtractor = androidVariantsExtractor,
+ variantBuilder = DefaultVariantBuilder(
+ DefaultAndroidVariantDataSource(
+ androidVariantsExtractor
+ )
+ ),
+ mavenInstallStore = DefaultMavenInstallStore()
)
val dependencyGraphs = FakeDependencyGraphs()
diff --git a/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculatorTest.kt b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculatorTest.kt
new file mode 100644
index 00000000..7b09ec01
--- /dev/null
+++ b/grazel-gradle-plugin/src/test/kotlin/com/grab/grazel/migrate/dependencies/MavenInstallArtifactsCalculatorTest.kt
@@ -0,0 +1,39 @@
+package com.grab.grazel.migrate.dependencies
+
+import com.grab.grazel.buildProject
+import com.grab.grazel.gradle.variant.setupAndroidVariantProject
+import com.grab.grazel.gradle.variant.setupJvmVariantProject
+import com.grab.grazel.util.addGrazelExtension
+import com.grab.grazel.util.createGrazelComponent
+import com.grab.grazel.util.doEvaluate
+import org.gradle.api.Project
+import org.junit.Before
+import org.junit.Test
+
+class MavenInstallArtifactsCalculatorTest {
+ private lateinit var rootProject: Project
+ private lateinit var androidProject: Project
+ private lateinit var jvmProject: Project
+ private lateinit var mavenInstallArtifactsCalculator: MavenInstallArtifactsCalculator
+ private val projectsToMigrate by lazy { listOf(rootProject, androidProject, jvmProject) }
+
+ @Before
+ fun setUp() {
+ rootProject = buildProject("root").also {
+ it.addGrazelExtension()
+ }
+ androidProject = buildProject("android", rootProject).also {
+ setupAndroidVariantProject(it)
+ }
+ jvmProject = buildProject("java", rootProject).also {
+ setupJvmVariantProject(it)
+ }
+ projectsToMigrate.forEach { it.doEvaluate() }
+ val grazelComponent = rootProject.createGrazelComponent()
+ mavenInstallArtifactsCalculator = grazelComponent.mavenInstallArtifactsCalculator().get()
+ }
+
+ @Test
+ fun `test`() {
+ }
+}
\ No newline at end of file
diff --git a/sample-android-library/BUILD.bazel b/sample-android-library/BUILD.bazel
index 4a5f017d..a2215ded 100644
--- a/sample-android-library/BUILD.bazel
+++ b/sample-android-library/BUILD.bazel
@@ -83,7 +83,7 @@ grab_android_local_test(
deps = [
"//:parcelize",
"//sample-android-library:sample-android-library-flavor1-free-debug",
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
@@ -105,7 +105,7 @@ grab_android_local_test(
deps = [
"//:parcelize",
"//sample-android-library:sample-android-library-flavor1-paid-debug",
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
@@ -127,7 +127,7 @@ grab_android_local_test(
deps = [
"//:parcelize",
"//sample-android-library:sample-android-library-flavor2-free-debug",
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
@@ -149,6 +149,6 @@ grab_android_local_test(
deps = [
"//:parcelize",
"//sample-android-library:sample-android-library-flavor2-paid-debug",
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)
diff --git a/sample-android/BUILD.bazel b/sample-android/BUILD.bazel
index 19f3cdd7..b8d1567b 100644
--- a/sample-android/BUILD.bazel
+++ b/sample-android/BUILD.bazel
@@ -32,7 +32,6 @@ android_binary(
crunch_png = False,
custom_package = "com.grab.grazel.android.sample",
debug_key = "//buildsystem:debug-keystore",
- enable_compose = True,
enable_data_binding = True,
incremental_dexing = True,
manifest = "src/debug/AndroidManifest.xml",
@@ -74,7 +73,6 @@ android_binary(
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -128,7 +126,6 @@ android_binary(
crunch_png = False,
custom_package = "com.grab.grazel.android.sample",
debug_key = "//buildsystem:debug-keystore",
- enable_compose = True,
enable_data_binding = True,
incremental_dexing = True,
manifest = "src/debug/AndroidManifest.xml",
@@ -170,7 +167,6 @@ android_binary(
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -224,7 +220,6 @@ android_binary(
crunch_png = False,
custom_package = "com.grab.grazel.android.sample",
debug_key = "//buildsystem:debug-keystore",
- enable_compose = True,
enable_data_binding = True,
incremental_dexing = True,
manifest = "src/debug/AndroidManifest.xml",
@@ -266,7 +261,6 @@ android_binary(
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -320,7 +314,6 @@ android_binary(
crunch_png = False,
custom_package = "com.grab.grazel.android.sample",
debug_key = "//buildsystem:debug-keystore",
- enable_compose = True,
enable_data_binding = True,
incremental_dexing = True,
manifest = "src/debug/AndroidManifest.xml",
@@ -362,7 +355,6 @@ android_binary(
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -420,10 +412,12 @@ android_instrumentation_binary(
"//sample-android-flavor:sample-android-flavor-flavor1-free-debug",
"//sample-android-library:sample-android-library-flavor1-free-debug",
"//sample-kotlin-library",
+ "@flavor1free_debug_android_test_maven//:androidx_test_espresso_espresso_core",
+ "@flavor1free_debug_android_test_maven//:androidx_test_ext_junit",
+ "@flavor1free_debug_android_test_maven//:androidx_test_monitor",
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -435,9 +429,6 @@ android_instrumentation_binary(
"@maven//:androidx_lifecycle_lifecycle_common",
"@maven//:androidx_lifecycle_lifecycle_runtime",
"@maven//:androidx_lifecycle_lifecycle_viewmodel",
- "@maven//:androidx_test_espresso_espresso_core",
- "@maven//:androidx_test_ext_junit",
- "@maven//:androidx_test_monitor",
],
)
@@ -474,10 +465,12 @@ android_instrumentation_binary(
"//sample-android-flavor:sample-android-flavor-flavor1-paid-debug",
"//sample-android-library:sample-android-library-flavor1-paid-debug",
"//sample-kotlin-library",
+ "@flavor1paid_debug_android_test_maven//:androidx_test_espresso_espresso_core",
+ "@flavor1paid_debug_android_test_maven//:androidx_test_ext_junit",
+ "@flavor1paid_debug_android_test_maven//:androidx_test_monitor",
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -489,9 +482,6 @@ android_instrumentation_binary(
"@maven//:androidx_lifecycle_lifecycle_common",
"@maven//:androidx_lifecycle_lifecycle_runtime",
"@maven//:androidx_lifecycle_lifecycle_viewmodel",
- "@maven//:androidx_test_espresso_espresso_core",
- "@maven//:androidx_test_ext_junit",
- "@maven//:androidx_test_monitor",
],
)
@@ -528,10 +518,12 @@ android_instrumentation_binary(
"//sample-android-flavor:sample-android-flavor-flavor2-free-debug",
"//sample-android-library:sample-android-library-flavor2-free-debug",
"//sample-kotlin-library",
+ "@flavor2free_debug_android_test_maven//:androidx_test_espresso_espresso_core",
+ "@flavor2free_debug_android_test_maven//:androidx_test_ext_junit",
+ "@flavor2free_debug_android_test_maven//:androidx_test_monitor",
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -543,9 +535,6 @@ android_instrumentation_binary(
"@maven//:androidx_lifecycle_lifecycle_common",
"@maven//:androidx_lifecycle_lifecycle_runtime",
"@maven//:androidx_lifecycle_lifecycle_viewmodel",
- "@maven//:androidx_test_espresso_espresso_core",
- "@maven//:androidx_test_ext_junit",
- "@maven//:androidx_test_monitor",
],
)
@@ -582,10 +571,12 @@ android_instrumentation_binary(
"//sample-android-flavor:sample-android-flavor-flavor2-paid-debug",
"//sample-android-library:sample-android-library-flavor2-paid-debug",
"//sample-kotlin-library",
+ "@flavor2paid_debug_android_test_maven//:androidx_test_espresso_espresso_core",
+ "@flavor2paid_debug_android_test_maven//:androidx_test_ext_junit",
+ "@flavor2paid_debug_android_test_maven//:androidx_test_monitor",
"@maven//:androidx_activity_activity",
"@maven//:androidx_activity_activity_compose",
"@maven//:androidx_appcompat_appcompat",
- "@maven//:androidx_compose_compiler_compiler",
"@maven//:androidx_compose_foundation_foundation",
"@maven//:androidx_compose_foundation_foundation_layout",
"@maven//:androidx_compose_material_material",
@@ -597,8 +588,5 @@ android_instrumentation_binary(
"@maven//:androidx_lifecycle_lifecycle_common",
"@maven//:androidx_lifecycle_lifecycle_runtime",
"@maven//:androidx_lifecycle_lifecycle_viewmodel",
- "@maven//:androidx_test_espresso_espresso_core",
- "@maven//:androidx_test_ext_junit",
- "@maven//:androidx_test_monitor",
],
)
diff --git a/sample-android/build.gradle b/sample-android/build.gradle
index 0a9cfbbf..1b9a34a5 100644
--- a/sample-android/build.gradle
+++ b/sample-android/build.gradle
@@ -123,6 +123,10 @@ android {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
+
+ buildFeatures {
+ compose = false
+ }
}
dependencies {
@@ -142,6 +146,10 @@ dependencies {
exclude group: "androidx.appcompat", module: "appcompat"
}
+ // Test for variant classpath
+ debugImplementation libs.androidx.paging.runtime
+ debugImplementation libs.leakcanary.android
+
implementation libs.androidx.compose.ui
implementation libs.androidx.compose.ui.tooling
implementation libs.androidx.compose.material
diff --git a/sample-kotlin-library/BUILD.bazel b/sample-kotlin-library/BUILD.bazel
index c8382d98..151db88f 100644
--- a/sample-kotlin-library/BUILD.bazel
+++ b/sample-kotlin-library/BUILD.bazel
@@ -23,6 +23,6 @@ grab_kt_jvm_test(
"//visibility:public",
],
deps = [
- "@maven//:junit_junit",
+ "@test_maven//:junit_junit",
],
)