Skip to content

Instantly share code, notes, and snippets.

@drmartell
Last active Jun 30, 2021
Embed
What would you like to do?
run RuboCop on staged files with pre-commit hook
#!/usr/bin/env ruby
# frozen-string-literal: true
# SEE: https://gist.github.com/mpeteuil/6147292
require 'rubocop'
VALID_FILE_CODES = %w[A M].freeze
# staged files have both a valid code and a `git status --porcelain` line that doesn't start with a space
staged_files = `git status --porcelain`
.split(/\n/) # one file per line
.filter { |status_and_file| status_and_file[0] != ' ' }
.map { |status_and_file| status_and_file.split(' ', 2) } # each line has a status and a filename
.select { |status, filename| VALID_FILE_CODES.include?(status[0]) && File.extname(filename) == '.rb' }
.map { |_status, filename| filename.delete('"') } # --porcelain may add "
system("bundle exec rubocop #{staged_files.shelljoin}") unless staged_files.empty?
exit $CHILD_STATUS.to_s[-1].to_i
@TylerRick

This comment has been minimized.

Copy link

@TylerRick TylerRick commented Jun 30, 2021

git diff-index --name-status --relative --cached @ might be a bit easier to parse (and only includes staged files so you don't have to do an extra step to filter them).

Also, I couldn't use git status --porcelain because my Rails app is in a sub-folder so I needed the list of files to be relative to the Rails root instead of relative to the git repo root (although git status in general seems to respect the --relative option, git status --porcelain seems to not).

@TylerRick

This comment has been minimized.

Copy link

@TylerRick TylerRick commented Jun 30, 2021

Never mind, it looks like git diff-index --name-status --relative --cached @ from within the pre-commit hook (not sure why).

But since I'm using https://github.com/rycus86/githooks, I can just get the list from:

changed = ENV['STAGED_FILES'].split("\n")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment