Spotless code with a git hook
When developing software in a team, a source of constant annoyment is code formatting. Each IDE has slightly different ideas about it, not even getting into the tabs vs. spaces debate. Especially annoying in Java land is the import sort order
Automation to the rescue
I switch between editors (if you need to know: Eclipse, Visual Studio Code, OxygenXML, IntelliJ, Sublime, Geany, nano or vi (ESC :!wq)) frequently, so an editor specific solution isn't an option.
Spotless to the rescue. It's a neat project using Maven or Gradle to format pretty (pun inteded) much all code types I use. The documentation states:
Spotless can format <antlr | c | c# | c++ | css | flow | graphql | groovy | html | java | javascript | json | jsx | kotlin | less | license headers | markdown | objective-c | protobuf | python | scala | scss | sql | typeScript | vue | yaml | anything> using <gradle | maven | anything>.
Setup
I opted for the eclipse defined Java formatting, using almost the Google formatting rules with the notable exception not merging line breaks back.
There are 3 steps involved for the Maven setup:
- Obtaining the formatting files, outlined here. Just make sure you are happy with the format first
- Add the maven plugin (see below)
- Add a git hook (see below)
pom.xml
This is what I added to my pom.xml
. By default spotless would run check
only, so I added apply
to enforce the formatting
<properties>
<spotless.version>2.4.1</spotless.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.version}</version>
<executions>
<execution>
<goals>
<goal>apply</goal>
</goals>
</execution>
</executions>
<configuration>
<formats>
<format>
<!-- Markdown, JSON and gitignore -->
<includes>
<include>*.md</include>
<include>*.json</include>
<include>.gitignore</include>
</includes>
<trimTrailingWhitespace />
<endWithNewline />
<indent>
<spaces>true</spaces>
<spacesPerTab>2</spacesPerTab>
</indent>
</format>
</formats>
<!-- ECLIPSE Java format -->
<java>
<toggleOffOn />
<importOrder>
<file>${maven.multiModuleProjectDirectory}/spotless.importorder</file>
</importOrder>
<removeUnusedImports />
<eclipse>
<file>${maven.multiModuleProjectDirectory}/eclipse-java-keep-style.xml</file>
</eclipse>
</java>
</configuration>
</plugin>
</plugins>
</build>
A few remarks:
- I run
apply
rather thancheck
- the directory variable
${maven.multiModuleProjectDirectory}
is needed, so sub projects work - you want to extend the configuration to include JS/TS eventually
.git/hooks/pre-commit
Create or edit your [projectroot]/.git/hooks/pre-commit
file:
#!/bin/bash
# Run formatting on pre-commit
files=`git status --porcelain | cut -c 4-`
fulllist=''
for f in $files; do
fulllist+=(.*)$(basename $f)$'\n'
done;
list=`echo "${fulllist}" | paste -s -d, /dev/stdin`
echo Working on $list
# Activate Java 11
export JAVA_HOME=`/usr/libexec/java_home -v 11.0`
/usr/local/bin/mvn spotless:apply -Dspotless.check.skip=false -DspotlessFiles=$list
- You might not need the line with Java
- swap
apply
forcheck
when you just want to check
As usual YMMV
Posted by Stephan H Wissel on 10 December 2021 | Comments (0) | categories: GitHub Java Maven Software