we have ktlintformat that we have it in each modul...
# ktlint
s
we have ktlintformat that we have it in each module. it is super annoying to run the Gradle command individually in each module every time you create PR. ./gradlew ktlintformat. : I wanna get off this 😎
s
I think that's probably more of a git trickery question than a ktlint question. A quick Google search reveals this gist where they're trying to do something similar with a different linter https://gist.github.com/sampart/089e269f8628c8320aff
s
hard to decipher, but I'll try. ❤️ You are right, its more of git question, I think we can still do that, ktlint can work on independent files, its just that only for the changed files
e
why do you need to run it in every module individually? if you don't qualify the task name, Gradle should run it in all subprojects. https://docs.gradle.org/current/userguide/command_line_interface.html#executing_tasks_in_multi_project_builds
but for one project I'm working on, we decided to register the ktlint tasks at the root only; this way it checks the buildSrc and build.gradle.kts files too
slower since it can't be parallelized, but it's still fast enough
r
Copy code
#!/bin/bash

function join_by { local IFS="$1"; shift; echo "$*"; }

# grep the unstaged files and concat them into one string using '|' delimiter to supply it to grep -Ev later on
# to exclude the files from formatting, which are staged and unstaged at the same time (meaning that only a part of a file is being
# commited --> ktlint can run only over the complete files)
unstaged_files=$(git diff --name-only --diff-filter=ACM | grep '\.kt[s"]\?$')
unstaged_files=$(join_by , $unstaged_files)
unstaged_files=${unstaged_files//,/|}

if [ -z "$unstaged_files" ] ; then
    files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.kt[s"]\?$')
else
    files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.kt[s"]\?$' | grep -Ev $unstaged_files)
fi

if [ -z "$files" ] ; then
    echo 'No .kt files to commit, skip formatting'
    exit 0
fi

echo "Running ktlint formatter..."

parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
project_path=${parent_path%/*/*}

# Format only staged files using ktlint
chmod a+x $project_path/scripts/ktlint/run-format
bash $project_path/scripts/ktlint/run-format $files

status=$?

# Stage the changes after formatting
git add $files

echo "ktlint formatted the code successfully."
exit 0
that’s the script that I use on majority of my projects - worked fine so far. It runs only over staged files, and excludes files when you are doing a partial commit, as ktlint can only run over the entire file. After formatting, it adds everything to the current commit so you get a nice auto-format
also I bundle ktlint executable within the project, as it’s way faster than running it via gradle on big codebases (gradle configuration itself can take tens of seconds)
alternatively you can rely on having ktlint in the user’s PATH, but you need to make sure that every dev in the company is having ktlint in their PATH
t
alternatively if you are using
ktlint-gradle
- it has such hook that runs only on files that will be committed
☝️ 1