Skip to content

Commit ccfabd4

Browse files
author
Jean-Michel Fayard
authored
Solves #64 #65 #58 (#66)
Solves #64 #65 #58
2 parents 687c16d + aa3966a commit ccfabd4

27 files changed

+423
-116
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ versionsOnlyMode for simple Gradle projects who just need the versions
55
5 modes supported: KOTLIN_VAL, KOTLIN_OBJECT, GROOVY_DEF, GROOVY_EXT, GRADLE_PROPERTIES
66
See https://github.com/jmfayard/buildSrcVersions/issues/55
77

8-
98
- Upgrade to Gradle 5.6.2
9+
- Upgrade to gradle-versions-plugins 0.25.0
10+
- Typo useFqdnFor() #64
11+
- Order dependencies by length #65
12+
- Detect ident from EditorConfig file 58
13+
- rejectVersionsIf { ... } from https://github.com/ben-manes/gradle-versions-plugin/issues/325
14+
- Order dependencies by length #65
1015
- Improve code quality
1116
- Write more and better tests
1217
- Use a local maven repo in the samples in order to have a stable output

composite/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tasks.register("publishLocally") {
1616
group = "Custom"
1717
description = "Publish the plugin locally"
1818
dependsOn(":checkAll")
19-
dependsOn(PLUGIN.task(":publish"))
19+
dependsOn(PLUGIN.task(":publishToMavenLocal"))
2020
}
2121

2222
tasks.register("publishPlugins") {

plugin/build.gradle.kts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ publishing {
2929
}
3030

3131
repositories {
32+
mavenLocal()
3233
mavenCentral()
33-
jcenter()
3434
}
3535

3636
pluginBundle {
3737
website = "https://github.com/jmfayard/buildSrcVersions"
3838
vcsUrl = "https://github.com/jmfayard/buildSrcVersions"
3939
tags = listOf("dependencies", "versions", "buildSrc", "kotlin", "kotlin-dsl")
4040
}
41+
4142
dependencies {
4243
testImplementation("io.kotlintest:kotlintest-runner-junit5:3.1.9")
4344

44-
implementation("com.github.ben-manes:gradle-versions-plugin:0.22.0")
45-
45+
implementation("com.github.ben-manes:gradle-versions-plugin:0.25.0")
4646
implementation("com.squareup.okio:okio:2.1.0")
4747
implementation( "com.squareup.moshi:moshi:1.7.0")
4848
implementation("com.squareup:kotlinpoet:1.3.0")
Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package de.fayard
22

3-
interface BuildSrcVersionsExtension {
4-
var useFdqnFor: MutableList<String>
3+
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
4+
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentFilter
55

6-
fun useFdqnFor(vararg dependencyName: String)
76

8-
var rejectedVersionKeywords: MutableList<String>
7+
interface BuildSrcVersionsExtension {
8+
fun useFqdnFor(vararg dependencyName: String)
99

10-
fun rejectedVersionKeywords(vararg keyword: String)
10+
fun rejectVersionIf(filter: ComponentFilter)
1111

1212
var renameLibs : String
1313

@@ -19,28 +19,53 @@ interface BuildSrcVersionsExtension {
1919

2020
var versionsOnlyFile : String?
2121

22+
23+
@Deprecated("Deprecated, see #64", ReplaceWith("useFqdnFor()"))
24+
var useFdqnFor: MutableList<String>
25+
26+
@Deprecated("Deprecated, see #64", ReplaceWith("useFqdnFor(dependencyName)"))
27+
fun useFdqnFor(vararg dependencyName: String)
28+
29+
30+
@Deprecated("Remove or use rejectVersionIf { ... }", replaceWith = ReplaceWith(""))
31+
var rejectedVersionKeywords: MutableList<String>
32+
33+
@Deprecated("Remove or use rejectVersionIf { selection -> ... }", replaceWith = ReplaceWith(""))
34+
fun rejectedVersionKeywords(vararg keyword: String)
2235
}
2336

24-
open class BuildSrcVersionsExtensionImpl(
25-
override var useFdqnFor: MutableList<String> = mutableListOf(),
37+
internal open class BuildSrcVersionsExtensionImpl(
2638
override var renameLibs: String = PluginConfig.DEFAULT_LIBS,
2739
override var renameVersions: String = PluginConfig.DEFAULT_VERSIONS,
2840
override var indent: String = PluginConfig.DEFAULT_INDENT,
2941
override var versionsOnlyMode: VersionsOnlyMode? = null,
30-
override var versionsOnlyFile: String? = null,
31-
override var rejectedVersionKeywords: MutableList<String> = PluginConfig.DEFAULT_REJECTED_KEYWORDS
42+
override var versionsOnlyFile: String? = null
3243
) : BuildSrcVersionsExtension {
44+
var useFqqnFor: List<String> = emptyList()
3345

46+
// Use @Transient for fields that should not be present in toString()
47+
override fun toString() : String = PluginConfig.extensionAdapter.toJson(this)
48+
49+
@Transient lateinit var upstream: DependencyUpdatesTask
50+
51+
override fun rejectVersionIf(filter: ComponentFilter) {
52+
upstream.rejectVersionIf(filter)
53+
}
54+
55+
override fun useFqdnFor(vararg dependencyName: String) {
56+
useFqqnFor = dependencyName.toList()
57+
}
3458

3559
override fun rejectedVersionKeywords(vararg keyword: String) {
36-
rejectedVersionKeywords = keyword.toMutableList()
60+
println("Warning: rejectedVersionKeywords is deprecated, see ${PluginConfig.issue53PluginConfiguration}")
3761
}
3862

3963
override fun useFdqnFor(vararg dependencyName: String) {
40-
useFdqnFor = dependencyName.toMutableList()
64+
println("Warning: useFdqnFor is deprecated, use useFqqnFor() instead. ${PluginConfig.issue53PluginConfiguration}")
65+
useFqdnFor(*dependencyName)
4166
}
4267

43-
override fun toString() : String =
44-
PluginConfig.extensionAdapter.toJson(this)
68+
@Transient override var useFdqnFor: MutableList<String> = mutableListOf()
69+
@Transient override var rejectedVersionKeywords: MutableList<String> = mutableListOf()
4570

4671
}
Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,34 @@
11
package de.fayard
22

33
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
4+
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent
5+
import de.fayard.PluginConfig.isNonStable
46
import org.gradle.api.Plugin
57
import org.gradle.api.Project
68
import org.gradle.kotlin.dsl.create
7-
import org.gradle.kotlin.dsl.getByType
89

910
open class BuildSrcVersionsPlugin : Plugin<Project> {
1011

1112
override fun apply(project: Project) = project.run {
1213

13-
configureBenManesVersions()
14-
15-
extensions.create(BuildSrcVersionsExtension::class, PluginConfig.EXTENSION_NAME, BuildSrcVersionsExtensionImpl::class)
14+
val extension = extensions.create(BuildSrcVersionsExtension::class, PluginConfig.EXTENSION_NAME, BuildSrcVersionsExtensionImpl::class)
15+
(extension as BuildSrcVersionsExtensionImpl).upstream = configureBenManesVersions()
16+
extension.rejectVersionIf {
17+
isNonStable(candidate.version)
18+
}
1619

1720
tasks.create("buildSrcVersions", BuildSrcVersionsTask::class) {
1821
group = "Help"
1922
description = "Update buildSrc/src/main/kotlin/{Versions.kt,Libs.kt}"
2023
dependsOn(":dependencyUpdates")
2124
outputs.upToDateWhen { false }
2225
}
23-
2426
Unit
2527
}
2628

27-
fun Project.configureBenManesVersions(): DependencyUpdatesTask {
28-
val rejectedKeywordsRegexps: List<Regex> by lazy {
29-
project.extensions.getByType<BuildSrcVersionsExtension>().rejectedVersionKeywords
30-
.map { qualifier -> Regex("(?i).*[.-]$qualifier[.\\d-]*") }
29+
fun Project.configureBenManesVersions(): DependencyUpdatesTask =
30+
tasks.maybeCreate("dependencyUpdates", DependencyUpdatesTask::class.java).also { task: DependencyUpdatesTask ->
31+
task.checkForGradleUpdate = true
32+
task.outputFormatter = "json"
3133
}
32-
33-
val benManesVersions: DependencyUpdatesTask =
34-
tasks.maybeCreate("dependencyUpdates", DependencyUpdatesTask::class.java)
35-
36-
benManesVersions.outputFormatter = "json"
37-
benManesVersions.checkForGradleUpdate = true
38-
benManesVersions.resolutionStrategy {
39-
40-
componentSelection {
41-
all {
42-
if (rejectedKeywordsRegexps.any { it.matches(candidate.version) }) {
43-
reject("Release candidate")
44-
}
45-
}
46-
}
47-
48-
}
49-
return benManesVersions
50-
}
5134
}

plugin/src/main/kotlin/de/fayard/BuildSrcVersionsTask.kt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package de.fayard
22

3-
import com.squareup.kotlinpoet.CodeBlock
3+
import org.gradle.api.Action
44
import org.gradle.api.DefaultTask
55
import org.gradle.api.Project
66
import org.gradle.api.tasks.Input
@@ -11,12 +11,20 @@ import org.gradle.kotlin.dsl.getByType
1111
@Suppress("UnstableApiUsage")
1212
open class BuildSrcVersionsTask : DefaultTask() {
1313

14+
fun configure(action: Action<BuildSrcVersionsExtension>) {
15+
this.extension = BuildSrcVersionsExtensionImpl()
16+
action.execute(this.extension!!)
17+
}
18+
1419
@Input @Optional
1520
var extension: BuildSrcVersionsExtension? = null
1621

1722
@TaskAction
1823
fun taskAction() {
1924
val extension : BuildSrcVersionsExtension = extension ?: project.extensions.getByType()
25+
if (extension.indent == PluginConfig.DEFAULT_INDENT) {
26+
extension.indent = EditorConfig.findIndentForKotlin(project.file("buildSrc/src/main/kotlin")) ?: " "
27+
}
2028
println("""
2129
|Plugin configuration: $extension
2230
|See documentation at ${PluginConfig.issue53PluginConfiguration}
@@ -49,20 +57,25 @@ open class BuildSrcVersionsTask : DefaultTask() {
4957
checkIfFilesExistInitiallyAndCreateThem(project)
5058
}
5159

52-
val kotlinPoetry: KotlinPoetry = kotlinpoet(dependencies, dependencyGraph.gradle, extension)
60+
val sortedDependencies = when {
61+
OutputFile.VERSIONS.existed -> dependencies
62+
else -> dependencies.sortedByDescending { it.versionName.length }
63+
}
64+
65+
val kotlinPoetry: KotlinPoetry = kotlinpoet(sortedDependencies, dependencyGraph.gradle, extension)
5366

5467
if (generatesAll) {
5568
kotlinPoetry.Libs.writeTo(outputDir)
56-
OutputFile.LIBS.logFileWasModified()
69+
OutputFile.logFileWasModified(OutputFile.LIBS.path, OutputFile.LIBS.existed)
5770
}
5871

5972
kotlinPoetry.Versions.writeTo(outputDir)
60-
OutputFile.VERSIONS.logFileWasModified()
73+
OutputFile.logFileWasModified(OutputFile.VERSIONS.path, OutputFile.VERSIONS.existed)
6174

6275
val file = extension.versionsOnlyFile?.let { project.file(it) }
6376
if (file != null && generatesAll.not()) {
6477
project.file(OutputFile.VERSIONS.path).renameTo(file)
65-
println("File $file updated")
78+
OutputFile.logFileWasModified(file.relativeTo(project.projectDir).path, existed = true)
6679
}
6780
}
6881

@@ -71,6 +84,8 @@ open class BuildSrcVersionsTask : DefaultTask() {
7184
val file = extension.versionsOnlyFile?.let { project.file(it) }
7285
val projectUseKotlin = project.file("build.gradle.kts").exists()
7386
regenerateBuildFile(file, extension, dependencies, projectUseKotlin)
87+
if (file != null) OutputFile.logFileWasModified(file.relativeTo(project.projectDir).path, existed = true)
88+
7489
}
7590

7691
fun checkIfFilesExistInitiallyAndCreateThem(project: Project) {
@@ -90,7 +105,7 @@ open class BuildSrcVersionsTask : DefaultTask() {
90105
for ((outputFile, initialContent) in initializationMap) {
91106
if (outputFile.existed.not()) {
92107
project.file(outputFile.path).writeText(initialContent)
93-
outputFile.logFileWasModified()
108+
OutputFile.logFileWasModified(outputFile.path, outputFile.existed)
94109
}
95110
}
96111
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package de.fayard
2+
3+
import java.io.File
4+
5+
data class Section(val name: String, val lines: MutableList<Pair<String, String>>) {
6+
operator fun get(key: String): String? {
7+
return lines.firstOrNull { it.first == key }?.second
8+
}
9+
}
10+
11+
object EditorConfig {
12+
const val NAME = ".editorconfig"
13+
const val INDENT_STYLE = "indent_style"
14+
const val INDENT_SIZE = "indent_size"
15+
const val SPACE = "space"
16+
const val TAB = "tab"
17+
18+
fun findIndentForKotlin(fromDir: File) : String? {
19+
return findEditorConfig(fromDir)
20+
.flatMap { file -> file.parseSections() }
21+
.findIndentForKotlinFiles()
22+
}
23+
24+
fun List<Section>.findIndentForKotlinFiles() : String? {
25+
val section = this.sortedByDescending { it.priority() }
26+
.filter { s ->
27+
s[INDENT_STYLE] != null && s.priority() > 0
28+
}.firstOrNull()
29+
return section?.findIndent()
30+
}
31+
32+
fun Section.findIndent() : String? {
33+
val size = this[INDENT_SIZE]?.toIntOrNull()
34+
val style = this[INDENT_STYLE]
35+
return when {
36+
style == TAB -> "\t"
37+
style == SPACE && size != null -> List(size) { " " }.joinToString(separator = "")
38+
else -> null
39+
}
40+
}
41+
42+
43+
fun File.isRootEditorConfig() : Boolean = when {
44+
name != NAME -> false
45+
this.exists().not() -> false
46+
else -> readLines().any { it.replace(" ", "").contains("root=true") }
47+
}
48+
49+
fun Section.priority() = when {
50+
name.contains("kt") -> 4
51+
name.contains("gradle") -> 3
52+
name.contains("java") -> 2
53+
name == "*" -> 1
54+
else -> -1
55+
}
56+
57+
fun File.parseSections(): List<Section> {
58+
assert(name == NAME)
59+
assert(canRead())
60+
val result = mutableListOf<Section>()
61+
var currentSection: Section? = null
62+
readLines().map { line ->
63+
line.substringBefore("#").substringBefore(";")
64+
}.forEach { line ->
65+
val section = line.parseSection()
66+
val split = line.split("=").map { it.trim() }
67+
when {
68+
section != null -> {
69+
currentSection = Section(section, mutableListOf())
70+
result.add(currentSection!!)
71+
}
72+
currentSection == null || line.isBlank() || split.size != 2 -> { }
73+
else -> currentSection!!.lines.add(split.first() to split.last())
74+
}
75+
}
76+
return result
77+
}
78+
79+
fun String.parseSection() : String? {
80+
val section = this.substringAfter("[", "").substringBefore("]", "").trim()
81+
return if (section.isBlank()) null else section
82+
}
83+
84+
fun findEditorConfig(fromDir: File) : List<File> {
85+
val result = mutableListOf<File>()
86+
var current: File? = fromDir
87+
while (current != null) {
88+
val ec = current.resolve(NAME)
89+
if (ec.exists()) {
90+
assert(ec.name == NAME)
91+
result += ec
92+
}
93+
if (ec.isRootEditorConfig()) {
94+
break
95+
}
96+
current = current.parentFile
97+
}
98+
return result
99+
}
100+
}

0 commit comments

Comments
 (0)