Rubocop Pre Commit Hook With Pipes

We use RuboCop to check our code for style on each push to Github. I was tired of having builds fail because I forgot to run rubocop so I want a little git pre-commit hook to prevent that from happening.

#!/bin/sh
# This would go in your .git/hooks/pre-commit file

if command -v rubocop > /dev/null; then
  rubocop
fi

That takes too long. Lets use pipes to only run RuboCop on files that have actually changed so that it is fast.

We get a list of changed files

mccalljt master % git status --porcelain
M  config.rb
D  deleted_file.rb
A  new_file.rb
M  source/index.html.haml

We only want Added and Modified, not Deleted

mccalljt master % git status --porcelain | grep -E '^A|^M'
M  config.rb
A  new_file.rb
M  source/index.html.haml

Rubocop only works on ruby files so we can ignore the others

mccalljt master % git status --porcelain | grep -E '^A|^M' | grep '.rb'
M  config.rb
A  new_file.rb

We just want the file names

mccalljt master % git status --porcelain | grep -E '^A|^M' | grep '.rb' | awk '{print $2}'
config.rb
new_file.rb

Perfect - lets pass them to rubocop

mccalljt master % git status --porcelain | grep -E '^A|^M' | grep '.rb' | awk '{print $2}' | xargs rubocop
Inspecting 2 files
..

2 files inspected, no offenses detected

Much better. Lets clean it up and put it back into the pre-commit hook.

#!/bin/sh

if command -v rubocop > /dev/null; then
  git status --porcelain \
  | grep -E '^A|^M' \
  | grep '.rb' \
  | awk '{print $2}' \
  | xargs rubocop
fi

Always fun to use the Unix Chainsaw

-JM

comments powered by Disqus