diff --git a/README.md b/README.md index ba04f67b8b..4056b40537 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,37 @@ - Hit `Download`. - Hit `Apply`. +5. Setup `detekt` pre-commit hook (optional): + +Run the following script from the root of the repository to install the hook. This will overwrite any existing pre-commit hook if present. + +```shell +echo "Writing detekt pre-commit hook..." +cat << 'EOL' > .git/hooks/pre-commit +#!/usr/bin/env bash + +echo "Running detekt check..." +OUTPUT="/tmp/detekt-$(date +%s)" +./gradlew -Pprecommit=true detekt > $OUTPUT +EXIT_CODE=$? +if [ $EXIT_CODE -ne 0 ]; then + cat $OUTPUT + rm $OUTPUT + echo "***********************************************" + echo " detekt failed " + echo " Please fix the above issues before committing " + echo "***********************************************" + exit $EXIT_CODE +fi +rm $OUTPUT +EOL +echo "detekt pre-commit hook written to .git/hooks/pre-commit" +echo "Making the hook executable" +chmod +x .git/hooks/pre-commit + +echo "detekt pre-commit hook installed successfully to .git/hooks/pre-commit" +``` + ## Theme ### Icons & Illustrations diff --git a/build.gradle.kts b/build.gradle.kts index bd1ad054a5..882c7d7175 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import io.gitlab.arturbosch.detekt.Detekt + plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false @@ -129,10 +131,57 @@ tasks { dependsOn("koverXmlReportMergedCoverage") } - withType().configureEach { + withType().configureEach { jvmTarget = libs.versions.jvmTarget.get() + // If run as a precommit hook, only run on staged files. + // This can be manually trigger by adding `-Pprecommit=true` to the gradle command. + if (project.hasProperty("precommit")) { + val rootDir = project.rootDir + val projectDir = projectDir + + val fileCollection = files() + + setSource( + getGitStagedFiles(rootDir) + .map { stagedFiles -> + val stagedFilesFromThisProject = stagedFiles + .filter { it.startsWith(projectDir) } + + fileCollection.setFrom(*stagedFilesFromThisProject.toTypedArray()) + + fileCollection.asFileTree + }, + ) + } } withType().configureEach { jvmTarget = libs.versions.jvmTarget.get() } } + +/** + * Gets the staged files in the current Git repository. + */ +fun Project.getGitStagedFiles(rootDir: File): Provider> { + return providers + .exec { commandLine("git", "--no-pager", "diff", "--name-only", "--cached") } + .standardOutput.asText + .map { outputText -> + outputText + .trim() + .split("\n") + .filter { it.isNotBlank() } + .map { File(rootDir, it) } + } +} + +afterEvaluate { + tasks.withType(Detekt::class.java).configureEach { + val typeResolutionEnabled = !classpath.isEmpty + if (typeResolutionEnabled && project.hasProperty("precommit")) { + // We must exclude kts files from pre-commit hook to prevent detekt from crashing + // This is a workaround for the https://github.com/detekt/detekt/issues/5501 + exclude("*.gradle.kts") + } + } +}