Last active
March 29, 2024 12:32
-
-
Save DHosseiny/17a55cab01879bb69ea63ceca8726cc0 to your computer and use it in GitHub Desktop.
Script to migrate gradle dependencies and plugins to version catalog. This script looks for libs.version.toml file and uses existing added libraries and logs not added libraries(just copy from logs and paste in libraries section)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File | |
val path = "path/to/project/directory" // TODO: change here | |
println("Processing in folder: $path") | |
println() | |
fun writeDependenciesFromVersionCatalog(path: String) { | |
val rootPath = File(path) | |
if (File(rootPath.path + "/build.gradle").exists().not()) { | |
println("Not root of a gradle project") | |
return | |
} | |
val tomlFile = File(rootPath.path + "/gradle/libs.versions.toml") | |
if (tomlFile.exists().not()) { | |
println("No libs.versions.toml file in gradle directory") | |
return | |
} | |
val tomlFileText = tomlFile.readText() | |
val existingLibraries = tomlFileText.substringAfter("[libraries]") | |
.substringBefore("[plugins]") // TODO: change to bundles if u have bundles section | |
.lines() | |
.mapNotNull { | |
it.takeIf { | |
it.contains("module = \"") // TODO: replace with "group" and "name" if group and name used | |
}?.substringBefore(" =") | |
}.toMutableList() | |
val librariesToAdd = StringBuilder("") | |
val gradleFiles = File(path) | |
.walk() | |
.maxDepth(4) | |
.onEnter { it.isDirectory } | |
.filter { File(it.path + "/build.gradle").exists() } | |
.map { | |
val gradleFile = File(it.path + "/build.gradle") | |
println(gradleFile.path) | |
gradleFile | |
} | |
.toList() | |
if (gradleFiles.isEmpty()) { | |
println("No modules found") | |
return | |
} | |
val dependencyWords = arrayOf( | |
"implementation", "kapt", "ksp", "testImplementation", | |
"androidTestImplementation", "coreLibraryDesugaring", | |
"kaptAndroidTest", "androidTestUtil", "debugImplementation", | |
"qaImplementation", "api", "compileOnly", "runtimeOnly" // TODO: add dependency words base on your buildVariants and flavors | |
) | |
val replaceablePlugins = arrayOf( | |
"com.android.library" to "android.library", | |
"kotlin-android" to "kotlin.android", | |
"kotlin-kapt" to "kapt", | |
"androidx.navigation.safeargs.kotlin" to "navigation.safeargs", | |
"dagger.hilt.android.plugin" to "hilt", | |
"com.google.devtools.ksp" to "ksp", | |
"kotlin-parcelize" to "kotlin.parcelize", // TODO: this part is harcoded from our own toml file. add your own plugins if u have others | |
) | |
gradleFiles.forEach { gradleFile -> | |
println("processing file $gradleFile") | |
val gradleFileText = gradleFile.readText() | |
val editedLines = gradleFile | |
.readLines() | |
.map { line -> | |
println("line is: $line") | |
if (line.isBlank()) { // blank line, ignore | |
line | |
} else { | |
val dependencyWord = dependencyWords.find { dependencyWord -> | |
line.contains("$dependencyWord \"") || line.contains("$dependencyWord '") | |
} | |
if (dependencyWord != null) { // it is a dependency line check it | |
val substringAfterQuote = line.substringAfter(":") | |
val tomlDependencyName = substringAfterQuote.substringBefore( | |
":", | |
substringAfterQuote.substringBefore( | |
"\"", | |
substringAfterQuote.substringBefore("'") | |
) | |
).replace("_", "-") | |
if (existingLibraries.all { it != tomlDependencyName }) { // add to "librariesToAdd" variable to print not added libraries at the end | |
val moduleWithDependencyWord = line.substringBefore( | |
":\$library", | |
line.substringBeforeLast("\"", line.substringBeforeLast("'")) | |
) | |
val module = moduleWithDependencyWord.substringAfter( | |
"\"", | |
moduleWithDependencyWord.substringAfter("'") | |
) | |
val versionText = if (substringAfterQuote.contains(":")) { | |
", version.ref = \"${ | |
substringAfterQuote.substringAfter( | |
"\$library.", | |
substringAfterQuote.substringAfter(":") | |
).substringBefore( | |
"\"", | |
substringAfterQuote.substringBefore("'") | |
) | |
}\"" | |
} else { | |
"" | |
} | |
val libraryToAdd = | |
"$tomlDependencyName = { module = \"$module\"$versionText }" | |
librariesToAdd.append(libraryToAdd) | |
.appendLine() | |
existingLibraries.add(tomlDependencyName) | |
} | |
val dependencyName = tomlDependencyName | |
.replace("-", ".") | |
val changedLine = line.substring( | |
0, | |
endIndex = line.indexOf(dependencyWord) + dependencyWord.length + 1 | |
) + "libs." + dependencyName | |
println("changed to: $changedLine") | |
changedLine | |
} else if (line.contains("id '")) { // it is a plugin line check it | |
val pluginName = line.substringAfter("id '").substringBefore("'") | |
val newPluginName = | |
replaceablePlugins.find { it.first == pluginName }?.second | |
?: return@map line | |
val changedLine = line.replaceRange( | |
line.indexOf("id '"), | |
line.lastIndexOf("'") + 1, | |
"alias(libs.plugins.$newPluginName)" | |
) | |
println("changed to: $changedLine") | |
changedLine | |
}/* else if (it.contains("apply plugin: '")) { | |
val pluginName = it.substringAfter("apply plugin: '").substringBefore("'") | |
val newPluginName = | |
replaceablePlugins.find { it.first == pluginName }?.second ?: return@map it | |
it.replaceRange( | |
it.indexOf("apply plugin"), | |
it.lastIndexOf("'") + 1, | |
"alias(libs.plugins.$newPluginName)" | |
) | |
} */ else line // non of the above cases just do not touch the line | |
} | |
} | |
println() | |
val joinToString = editedLines.joinToString(System.lineSeparator()) | |
println("result:\n$joinToString") | |
gradleFile.writeText(joinToString) | |
} | |
println() | |
println("librariesToAdd:\n$librariesToAdd") // print libraries to add to toml file | |
} | |
writeDependenciesFromVersionCatalog(path) | |
println() | |
println("Press Enter to close") | |
System.`in`.read() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment