Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,20 +18,11 @@
package com.itsaky.androidide.gradle

import com.itsaky.androidide.buildinfo.BuildInfo
import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_IS_TEST_ENV
import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_MAVEN_LOCAL_REPOSITORY
import org.adfa.constants.ANDROIDIDE_HOME
import org.adfa.constants.MAVEN_LOCAL_REPOSITORY
import org.gradle.StartParameter
import org.gradle.api.Plugin
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.initialization.Settings
import org.gradle.api.invocation.Gradle
import org.gradle.api.logging.Logging
import java.io.File
import java.io.FileNotFoundException
import java.net.URI

const val MAX_LOGFILE_COUNT = 2

Expand All@@ -41,187 +32,71 @@ const val MAX_LOGFILE_COUNT = 2
* @author Akash Yadav
*/
class AndroidIDEInitScriptPlugin : Plugin<Gradle> {

companion object {

private val logger = Logging.getLogger(AndroidIDEInitScriptPlugin::class.java)
}

/**
* Keywords: [gradle, agp, androidGradlePlugin, classpath, build ]
* It seeme like this method adds custom android-gradle-plugin to the classpath.
* Without explicitly adding it to any gradle files.
* This script is a prat of androidIde. So even if child process fails to build,
* it only means that androidIDE toolchain was not satisfied.
* So far I can't find
* @see VERSION_NAME_DOWNLOAD
* gradle .jar and it seems to be required.
* This script has no direct usage by AS search, but is invoked from string and in gradle tasks.
*/
override fun apply(target: Gradle) {
removeDaemonLogs(target)

target.settingsEvaluated { settings ->
settings.addDependencyRepositories()
}

target.rootProject { rootProject ->
rootProject.buildscript.apply {
dependencies.apply {
add("classpath", rootProject.files("$ANDROIDIDE_HOME/plugin/cogo-plugin.jar"))
}
}
}

target.projectsLoaded { gradle ->
gradle.rootProject.subprojects { sub ->
if (!sub.buildFile.exists()) {
// For subproject ':nested:module',
// ':nested' represented as a 'Project', but it may or may not have a buildscript file
// if the project doesn't have a buildscript, then the plugins should not be applied
return@subprojects
}

sub.afterEvaluate {
logger.info("Trying to apply plugin '${BuildInfo.PACKAGE_NAME}' to project '${sub.path}'")
sub.pluginManager.apply(BuildInfo.PACKAGE_NAME)
}
}
}
}

private fun removeDaemonLogs(gradle: Gradle) {
// logger.lifecycle("#@^*( Applyingg Clean Plugin")
// Get the Gradle user home directory
val gradleUserHomeDir = gradle.gradleUserHomeDir

// Get the current Gradle version
val currentGradleVersion = gradle.gradleVersion
val logsDir = File(gradleUserHomeDir, "daemon/$currentGradleVersion")

if (logsDir.exists() && logsDir.isDirectory) {
logger.lifecycle("Code On the Go clean logs of gradle ($currentGradleVersion) task running....")

// Filter and iterate over log files, sorted by last modified date
logsDir.listFiles()?.filter { it.isFile && it.name.endsWith(".log") }
?.sortedByDescending { it.lastModified() }
?.drop(MAX_LOGFILE_COUNT)
?.forEach { logFile ->
logger.lifecycle("deleting log: ${logFile.name}")
logFile.delete()
}
}
else {
logger.lifecycle("No deletions made, number of log files does not exceed ($MAX_LOGFILE_COUNT) for gradle ($currentGradleVersion). ")
}
}

private fun Settings.addDependencyRepositories() {
val (isTestEnv, mavenLocalRepos) = getTestEnvProps(startParameter)
if (isTestEnv) {
addDependencyRepositories(isTestEnv, mavenLocalRepos)
} else {
addDependencyRepositories(MAVEN_LOCAL_REPOSITORY)
}
}

@Suppress("UnstableApiUsage")
private fun Settings.addDependencyRepositories(
mavenLocalRepo: String
) {
dependencyResolutionManagement.run {
repositories.configureRepositories(mavenLocalRepo)
}

pluginManagement.apply {
repositories.configureRepositories(mavenLocalRepo)
}
}

private fun RepositoryHandler.configureRepositories(
mavenLocalRepo: String
) {

val repo = File(mavenLocalRepo)
if (!repo.exists() || !repo.isDirectory) {
throw FileNotFoundException("Maven local repository '$mavenLocalRepo' not found")
}

maven { repository ->
repository.url = repo.toURI()
}

}

@Suppress("UnstableApiUsage")
private fun Settings.addDependencyRepositories(
isMavenLocalEnabled: Boolean,
mavenLocalRepo: String
) {
dependencyResolutionManagement.run {
repositories.configureRepositories(isMavenLocalEnabled, mavenLocalRepo)
}

pluginManagement.apply {
repositories.configureRepositories(isMavenLocalEnabled, mavenLocalRepo)
}
}

private fun RepositoryHandler.addDependencyRepositories(startParams: StartParameter) {
val (isTestEnv, mavenLocalRepos) = getTestEnvProps(startParams)
configureRepositories(isTestEnv, mavenLocalRepos)
}

private fun getTestEnvProps(startParameter: StartParameter): Pair<Boolean, String> {
return startParameter.run {
val isTestEnv = projectProperties.containsKey(_PROPERTY_IS_TEST_ENV)
&& projectProperties[_PROPERTY_IS_TEST_ENV].toString().toBoolean()
val mavenLocalRepos = projectProperties.getOrDefault(_PROPERTY_MAVEN_LOCAL_REPOSITORY, "")

isTestEnv to mavenLocalRepos
}
}

private fun RepositoryHandler.configureRepositories(
isMavenLocalEnabled: Boolean,
mavenLocalRepos: String
) {

if (!isMavenLocalEnabled) {

// For AndroidIDE CI builds
maven { repository ->
repository.url = URI.create(BuildInfo.SNAPSHOTS_REPOSITORY)
}
} else {
logger.info("Using local maven repository for classpath resolution...")

for (mavenLocalRepo in mavenLocalRepos.split(':')) {
if (mavenLocalRepo.isBlank()) {
mavenLocal()
} else {
logger.info("Local repository path: $mavenLocalRepo")

val repo = File(mavenLocalRepo)
if (!repo.exists() || !repo.isDirectory) {
throw FileNotFoundException("Maven local repository '$mavenLocalRepo' not found")
}

maven { repository ->
repository.url = repo.toURI()
}
}
}
}

// for AGP API dependency
google()

maven { repository ->
repository.setUrl(BuildInfo.PUBLIC_REPOSITORY)
}

mavenCentral()
gradlePluginPortal()
}
companion object {
private val logger = Logging.getLogger(AndroidIDEInitScriptPlugin::class.java)
}

override fun apply(target: Gradle) {
removeDaemonLogs(target)

target.settingsEvaluated { settings ->
settings.pluginManager.apply(COTGSettingsPlugin::class.java)
}

target.rootProject { rootProject ->
rootProject.buildscript.apply {
dependencies.apply {
add(
"classpath",
rootProject.files("$ANDROIDIDE_HOME/plugin/cogo-plugin.jar"),
)
}
}
}

target.projectsLoaded { gradle ->
gradle.rootProject.subprojects { sub ->
if (!sub.buildFile.exists()) {
// For subproject ':nested:module',
// ':nested' represented as a 'Project', but it may or may not have a buildscript file
// if the project doesn't have a buildscript, then the plugins should not be applied
return@subprojects
}

sub.afterEvaluate {
logger.info("Trying to apply plugin '${BuildInfo.PACKAGE_NAME}' to project '${sub.path}'")
sub.pluginManager.apply(BuildInfo.PACKAGE_NAME)
}
}
}
}

private fun removeDaemonLogs(gradle: Gradle) {
// Get the Gradle user home directory
val gradleUserHomeDir = gradle.gradleUserHomeDir

// Get the current Gradle version
val currentGradleVersion = gradle.gradleVersion
val logsDir = File(gradleUserHomeDir, "daemon/$currentGradleVersion")

if (logsDir.exists() && logsDir.isDirectory) {
logger.lifecycle("Code On the Go clean logs of gradle ($currentGradleVersion) task running....")

// Filter and iterate over log files, sorted by last modified date
logsDir
.listFiles()
?.filter { it.isFile && it.name.endsWith(".log") }
?.sortedByDescending { it.lastModified() }
?.drop(MAX_LOGFILE_COUNT)
?.forEach { logFile ->
logger.lifecycle("deleting log: ${logFile.name}")
logFile.delete()
}
} else {
logger.lifecycle(
"No deletions made, number of log files does not" +
" exceed ($MAX_LOGFILE_COUNT) for gradle ($currentGradleVersion).",
)
}
Comment thread
itsaky-adfa marked this conversation as resolved.
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
package com.itsaky.androidide.gradle

import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_IS_TEST_ENV
import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_MAVEN_LOCAL_REPOSITORY
import org.adfa.constants.MAVEN_LOCAL_REPOSITORY
import org.gradle.StartParameter
import org.gradle.api.Plugin
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.initialization.Settings
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import java.io.File
import java.net.URI

class COTGSettingsPlugin : Plugin<Settings> {
private val logger = Logging.getLogger(COTGSettingsPlugin::class.java)

override fun apply(target: Settings) {
if (target.gradle.parent != null) {
// only apply the settings plugin to the root Gradle build
return
}

logger.info("Plugin instance: ${System.identityHashCode(this)}")
// Add our local maven repo, always.
val allLocalRepos = mutableListOf(MAVEN_LOCAL_REPOSITORY)

// Then check if we need to add additional repos, based on whether
// we're in a test environment
val (isTestEnv, mavenLocalRepos) = getTestEnvProps(target.startParameter)
if (isTestEnv) {
allLocalRepos += mavenLocalRepos
}

target.addLocalRepos(allLocalRepos)
}

private fun RepositoryHandler.addLocalRepos(repos: List<String>) {
repos.forEach { repo ->
addLocalMavenRepoIfMissing(logger, repo)
}
}

@Suppress("UnstableApiUsage")
private fun Settings.addLocalRepos(mavenLocalRepos: List<String>) {
dependencyResolutionManagement.repositories.addLocalRepos(mavenLocalRepos)
pluginManagement.repositories.addLocalRepos(mavenLocalRepos)
}

private fun getTestEnvProps(startParameter: StartParameter): Pair<Boolean, List<String>> =
startParameter.run {
val isTestEnv =
projectProperties.containsKey(_PROPERTY_IS_TEST_ENV) &&
projectProperties[_PROPERTY_IS_TEST_ENV].toString().toBoolean()
val mavenLocalRepos =
projectProperties.getOrDefault(_PROPERTY_MAVEN_LOCAL_REPOSITORY, "")

isTestEnv to mavenLocalRepos.split(File.pathSeparatorChar).toList().filter { it.isNotBlank() }
}
Comment thread
itsaky-adfa marked this conversation as resolved.
}

private fun RepositoryHandler.addLocalMavenRepoIfMissing(
logger: Logger,
path: String,
) {
val dir = File(path)
require(dir.isDirectory) { "Repo not found: $path" }
Comment thread
itsaky-adfa marked this conversation as resolved.

val uri = dir.toURI()

addMavenRepoIfMissing(logger, uri)
}

private fun RepositoryHandler.addMavenRepoIfMissing(
logger: Logger,
uri: URI,
) {
if (none { it is MavenArtifactRepository && it.url == uri }) {
logger.info("Adding maven repository: $uri")
maven { it.url = uri }
}
}
Comment thread
itsaky-adfa marked this conversation as resolved.