Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interactive mode #72

Merged
merged 4 commits into from
Aug 19, 2022
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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Changelog
Version 0.5.4
Version 0.6.0
-------------
* New feature: `--incremental` command line option to stage changes without updating the TOML file [(#63)](https://github.com/littlerobots/version-catalog-update-plugin/issues/63)
* Shadow (bundle) dependencies to prevent conflicts with other plugins [(#39)](https://github.com/littlerobots/version-catalog-update-plugin/issues/39)
* Fix an issue with unused kept pinned dependencies causing the update task to fail [(#61)](https://github.com/littlerobots/version-catalog-update-plugin/issues/61)
* Removed `--add` option. [(#69)](https://github.com/littlerobots/version-catalog-update-plugin/issues/69)

Version 0.5.3
-------------
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,49 @@ To update the catalog file at any time run `./gradlew versionCatalogUpdate`. Thi
No new entries will be added to the catalog, but unused entries will be removed. Any dependency that is not reported by the versions plugin, but still appears
in the version catalog file will be considered unused. This is [configurable](#configuration).

### Interactive mode
Updating all dependencies at once is without testing is generally not recommended. When using a version control system, changes to the version catalog can be rolled back
by comparing a diff, but for large updates this may be inconvenient. In these cases, interactive mode might help.

When running `./gradlew versionCatalogUpdate --interactive` the `libs.versions.toml` file will not be directly be updated, in stead
a `libs.versions.updates.toml` file will be created containing the entries that would be updated and any pinned entries
that can be updated. This file uses the short form dependency notation without any `version.ref`s. Pinned entries are commented
by default, all other entries are uncommented. To skip updating an entry in the TOML file it can be commented out or removed completely.
It's also possible to edit the entry if that's desired.

To apply the changes to the `libs.versions.toml` file, run `./gradlew versionCatalogApplyUpdates`. This will also
update `version.ref`s and `versions` in the same way as `versionCatalogUpdate` would.

Note that any comments and any other TOML tables than `[libraries]` and `[plugins]` will be ignored when applying the changes.

<details>
<summary>Example libs.versions.updates.toml</summary>

```
# Version catalog updates generated at 2022-08-19T16:00:29.757349
#
# Contents of this file will be applied to libs.versions.toml when running versionCatalogApplyUpdates.
#
# Comments will not be applied to the version catalog when updating.
# To prevent a version upgrade, comment out the entry or remove it.
#
[libraries]
# @pinned version 4.9.3 (antlr) --> 4.10.1
#antlr = "org.antlr:antlr4:4.10.1"
# From version 2.5.4 (asciidoctorj) --> 2.5.5
asciidoctorj = "org.asciidoctor:asciidoctorj:2.5.5"
# From version 2.1.2 (asciidoctorjPdf) --> 2.1.6
asciidoctorjPdf = "org.asciidoctor:asciidoctorj-pdf:2.1.6"

[plugins]
# Updated from version 1.20.0
detekt = "io.gitlab.arturbosch.detekt:1.21.0"
# Updated from version 1.7.0
dokka = "org.jetbrains.dokka:1.7.10"
```

</details>

### Formatting only
To format the existing `libs.versions.toml` file without updating library versions, you can run `./gradlew versionCatalogFormat`.
This will format the version catalog and create new version references, just like the `versionCatalogUpdate` task would do.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package nl.littlerobots.vcu

import nl.littlerobots.vcu.model.HasVersion
import nl.littlerobots.vcu.model.Library
import nl.littlerobots.vcu.model.Plugin
import nl.littlerobots.vcu.model.VersionCatalog
Expand All @@ -25,7 +26,7 @@ import java.io.Writer
private const val BUNDLE_INDENT = 4

class VersionCatalogWriter {
fun write(versionCatalog: VersionCatalog, writer: Writer) {
fun write(versionCatalog: VersionCatalog, writer: Writer, commentEntry: (HasVersion) -> Boolean = { false }) {
val printWriter = PrintWriter(writer)
if (versionCatalog.versions.isNotEmpty()) {
for (line in versionCatalog.versionComments.tableComments) {
Expand All @@ -51,6 +52,9 @@ class VersionCatalogWriter {
for (comment in versionCatalog.libraryComments.getCommentsForKey(library.key)) {
printWriter.println(comment)
}
if (commentEntry(library.value)) {
printWriter.print("#")
}
printWriter.println("""${library.key} = ${formatLibrary(library.value)}""")
}
}
Expand Down Expand Up @@ -90,6 +94,9 @@ class VersionCatalogWriter {
for (comment in versionCatalog.pluginComments.getCommentsForKey(plugin.key)) {
printWriter.println(comment)
}
if (commentEntry(plugin.value)) {
printWriter.print("#")
}
printWriter.println("${plugin.key} = ${formatPlugin(plugin.value)}")
}
}
Expand All @@ -111,6 +118,7 @@ class VersionCatalogWriter {
append(" } }")
}.toString()
}

is VersionDefinition.Unspecified -> "{ id = \"${plugin.id}\" }"
}

Expand All @@ -132,6 +140,7 @@ class VersionCatalogWriter {
append(" } }")
}.toString()
}

is VersionDefinition.Unspecified -> "{ module = \"${library.module}\" }"
}

Expand All @@ -142,6 +151,7 @@ class VersionCatalogWriter {
"${it.key} = \"${it.value}\""
}
}

else -> throw IllegalStateException("Invalid version definition $versionDefinition")
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ org.gradle.caching=true
kotlin.stdlib.default.dependency=false

GROUP=nl.littlerobots.vcu
VERSION_NAME=0.5.4-SNAPSHOT
VERSION_NAME=0.6.0-SNAPSHOT

POM_NAME=Version catalog updates plugin
POM_DESCRIPTION=A gradle plugin that updates the version catalog file
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2021 Hugo Visser
*
* 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 nl.littlerobots.vcu.plugin

import nl.littlerobots.vcu.VersionCatalogParser
import nl.littlerobots.vcu.VersionCatalogWriter
import nl.littlerobots.vcu.model.resolveVersions
import nl.littlerobots.vcu.model.sortKeys
import nl.littlerobots.vcu.model.updateFrom
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction

abstract class VersionCatalogApplyUpdatesTask : DefaultTask() {
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val catalogFile: RegularFileProperty

@get:Input
@get:Optional
abstract val sortByKey: Property<Boolean>

@get:Internal
abstract val keep: Property<KeepConfigurationInput>

private val keepRefs by lazy {
keep.orNull?.getVersionCatalogRefs() ?: emptySet()
}

@TaskAction
fun applyUpdates() {
val updatesFile = catalogFile.asFile.get().updatesFile
val versionCatalogParser = VersionCatalogParser()
if (updatesFile.exists()) {
val catalog = catalogFile.asFile.get().inputStream().use {
versionCatalogParser.parse(it)
}
val updates = updatesFile.inputStream().use {
versionCatalogParser.parse(it)
}
if (updates.libraries.isEmpty() && updates.plugins.isEmpty()) {
updatesFile.delete()
return
}

// reconstruct an update from the current catalog + the updates, as if manually edited
val fullUpdate = catalog.resolveVersions()
.copy(versions = emptyMap(), bundles = emptyMap())
.updateFrom(updates, purge = false)
// undo any version grouping
.resolveVersions()
.copy(versions = emptyMap())

val updatedCatalog = catalog.updateFrom(fullUpdate, addNew = false, purge = false)
.withKeepUnusedVersions(catalog, keep.orNull?.keepUnusedVersions?.getOrElse(false) ?: false)
.withKeptVersions(catalog, keepRefs)
.let {
if (sortByKey.getOrElse(true)) {
it.sortKeys()
} else {
it
}
}
VersionCatalogWriter().write(updatedCatalog, catalogFile.get().asFile.writer())
updatesFile.delete()
}
}

companion object {
const val TASK_NAME = "versionCatalogApplyUpdates"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class VersionCatalogUpdatePlugin : Plugin<Project> {

val catalogUpdatesTask = project.tasks.register(UPDATE_TASK_NAME, VersionCatalogUpdateTask::class.java)
val catalogFormatTask = project.tasks.register(FORMAT_TASK_NAME, VersionCatalogFormatTask::class.java)
val catalogApplyUpdatesTask = project.tasks.register(VersionCatalogApplyUpdatesTask.TASK_NAME, VersionCatalogApplyUpdatesTask::class.java)

catalogUpdatesTask.configure { task ->
task.reportJson.set(reportJson)
Expand All @@ -65,6 +66,15 @@ class VersionCatalogUpdatePlugin : Plugin<Project> {
}
}

catalogApplyUpdatesTask.configure { task ->
task.sortByKey.set(extension.sortByKey)
task.keep.set(project.objects.newInstance(KeepConfigurationInput::class.java, extension.keep))

if (!task.catalogFile.isPresent) {
task.catalogFile.set(project.rootProject.file("gradle/libs.versions.toml"))
}
}

project.pluginManager.withPlugin(VERSIONS_PLUGIN_ID) {
val dependencyUpdatesTask =
project.tasks.named(DEPENDENCY_UPDATES_TASK_NAME, DependencyUpdatesTask::class.java) {
Expand Down
Loading