diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a9fbdf4..f454eb94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [10.3.0-SNAPSHOT] - Unreleased ### Added + - Added git hook update notifier ([#474](https://github.com/JLLeitschuh/ktlint-gradle/pull/474)) - ? ### Changed diff --git a/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/GitHook.kt b/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/GitHook.kt index 73f5f266..25ed7b6b 100644 --- a/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/GitHook.kt +++ b/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/GitHook.kt @@ -15,6 +15,19 @@ import javax.inject.Inject internal const val FILTER_INCLUDE_PROPERTY_NAME = "internalKtlintGitFilter" +/** + * The version of the git hook, + * + * When this value is passed to the gradle task it is validated to ensure users don't have outdated + * ktlint git hooks installed. + * + * This should be manually updated when changes are made to the git hook. + * + * TODO: Implement a CI/build step that will look for changes to either GitHook.kt or the git hook output and + * automatically increment this value + */ +internal const val hookVersion = "1" + @Language("Bash") internal val shShebang = """ @@ -34,7 +47,7 @@ private fun generateGradleCommand( } else { "./gradlew" } - return "$gradleCommand --quiet $taskName -P$FILTER_INCLUDE_PROPERTY_NAME=\"${'$'}CHANGED_FILES\"" + return "$gradleCommand --quiet $taskName -P$FILTER_INCLUDE_PROPERTY_NAME=\"${'$'}CHANGED_FILES\" -phookVersion=$hookVersion" } private fun generateGitCommand( @@ -54,7 +67,7 @@ private fun postCheck( git add ${'$'}file fi done - """.trimIndent() + """.trim('\n', ' ') } else { "" } @@ -90,6 +103,7 @@ internal fun generateGitHook( $gradleCommandExitCode=$? echo "Completed ktlint run." + ${postCheck(shouldUpdateCommit)} if [ -s ${'$'}diff ]; then diff --git a/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/tasks/BaseKtLintCheckTask.kt b/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/tasks/BaseKtLintCheckTask.kt index 09921134..f56fbe4a 100644 --- a/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/tasks/BaseKtLintCheckTask.kt +++ b/plugin/src/main/kotlin/org/jlleitschuh/gradle/ktlint/tasks/BaseKtLintCheckTask.kt @@ -33,6 +33,7 @@ import org.jlleitschuh.gradle.ktlint.FILTER_INCLUDE_PROPERTY_NAME import org.jlleitschuh.gradle.ktlint.KOTLIN_EXTENSIONS import org.jlleitschuh.gradle.ktlint.applyGitFilter import org.jlleitschuh.gradle.ktlint.getEditorConfigFiles +import org.jlleitschuh.gradle.ktlint.hookVersion import org.jlleitschuh.gradle.ktlint.intermediateResultsBuildDir import org.jlleitschuh.gradle.ktlint.property import org.jlleitschuh.gradle.ktlint.worker.KtLintWorkAction @@ -96,6 +97,10 @@ abstract class BaseKtLintCheckTask @Inject constructor( init { if (project.hasProperty(FILTER_INCLUDE_PROPERTY_NAME)) { + // if FILTER_INCLUDE_PROPERTY_NAME exists then we are invoked from a git hook, check hook version + if (project.findProperty(hookVersion) != hookVersion) { + logger.warn("Your ktlint git hook is outdated, please update by running the addKtlint*GitPreCommitHook Gradle task.") + } applyGitFilter() } else { KOTLIN_EXTENSIONS.forEach { diff --git a/plugin/src/test/kotlin/org/jlleitschuh/gradle/ktlint/GitHookTasksTest.kt b/plugin/src/test/kotlin/org/jlleitschuh/gradle/ktlint/GitHookTasksTest.kt index 0059117c..5145d2c6 100644 --- a/plugin/src/test/kotlin/org/jlleitschuh/gradle/ktlint/GitHookTasksTest.kt +++ b/plugin/src/test/kotlin/org/jlleitschuh/gradle/ktlint/GitHookTasksTest.kt @@ -271,6 +271,23 @@ class GitHookTasksTest : AbstractPluginTest() { } } + @Test + internal fun `Git hook should send the hook version to gradle`() { + projectRoot.setupGradleProject() + val gitDir = projectRoot.initGit() + + build(":$INSTALL_GIT_HOOK_FORMAT_TASK").run { + assertThat(task(":$INSTALL_GIT_HOOK_FORMAT_TASK")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(gitDir.preCommitGitHook().readText()).contains("""-phookVersion=$hookVersion""") + } + } + + private fun File.initGit(): File { + val repo = RepositoryBuilder().setWorkTree(this).setMustExist(false).build() + repo.create() + return repo.directory + } + private fun File.preCommitGitHook(): File = gitHookFolder().resolve("pre-commit") private fun File.gitHookFolder(): File = resolve("hooks/")