Skip to content

Instantly share code, notes, and snippets.

@futuraprime
Created June 18, 2012 15:32
Show Gist options
  • Save futuraprime/2948929 to your computer and use it in GitHub Desktop.
Save futuraprime/2948929 to your computer and use it in GitHub Desktop.
Pre-commit error catcher
#!/usr/bin/env ruby
# Git pre-commit hook that prevents accidentally committing things that shouldn't be, like:
#
# * ":focus", used with RSpec/Guard
# * "show_page", used to debug request specs
# * "console.log" or "console.debug", used in JavaScript debugging
# * "DO NOT COMMIT!" comments
#
# Modify the regexps to suit your needs. The error message shows the full regexp match, or just the first capture group, if there is one.
#
# To bypass this commit hook (and others), perhaps when defining ":focus" or "show_page" for the first time, commit with the "--no-verify" option.
#
# By Henrik Nyh <http://henrik.nyh.se> 2011-10-08 under the MIT License.
#
#
# Install:
#
# cd your_project
# curl https://raw.github.com/henrik/dotfiles/master/githooks/pre-commit -o .git/hooks/pre-commit && chmod u+x .git/hooks/pre-commit
#
# Or store it centrally and symlink in your projects:
#
# curl --create-dirs https://raw.github.com/henrik/dotfiles/master/githooks/pre-commit -o ~/.githooks/pre-commit && chmod u+x ~/.githooks/pre-commit
# cd your_project
# ln -s ~/.githooks/pre-commit .git/hooks
FORBIDDEN = [
/[\s,](:focus)\b/,
/\bshow_page\b/,
/\bconsole\.log\b/,
/\bconsole\.debug\b/,
/\bdo not commit\b/i
]
full_diff = `git diff --cached --`
full_diff.scan(%r{^\+\+\+ b/(.+)\n@@.*\n([\s\S]*?)(?:^diff|\z)}).each do |file, diff|
added = diff.split("\n").select { |x| x.start_with?("+") }.join("\n")
if FORBIDDEN.any? { |re| added.match(re) }
puts %{Git hook forbids adding "#{$1 || $&}" to #{file}}
puts "To commit anyway, use --no-verify"
exit 1
end
end
# remove trailing whitespace
# https://github.com/mkaschenko/trailing_spaces_remover
class Parser
def initialize
result = system 'git rev-parse --verify HEAD >/dev/null 2>&1'
rev = '4b825dc642cb6eb9a060e54bf8d69288fbee4904' unless result
@output = `git diff --cached --check #{rev} | grep -e ^[^+]`
end
def exists_problem_files?
@output.length.nonzero?
end
def problem_files
files = {}
lines = @output.lines
lines.each do |line|
filename = parse_filename(line)
files[filename] = { :lines => [], :flag => false } unless files.has_key? filename
line.include?('whitespace') ? files[filename][:lines] << parse_lineno(line) : files[filename][:flag] = true
end
files
end
private
def parse_filename(string)
string.scan(/[\w\-\/\.]+/)[0]
end
def parse_lineno(string)
string.scan(/\d+:/)[0].chop.to_i
end
end
class TrailingSpacesRemover
def from(files)
files.each_key do |filename|
l = File.readlines(filename).to_a.insert(0, nil)
bad_file = files[filename]
File.open(filename, 'w') do |f|
bad_file[:lines].each { |num| l[num].rstrip!.concat("\n") }
if bad_file[:flag]
index = l.length - 1
while l[index] == "\n"
l.delete_at(index)
index -= 1
end
end
f.print l.join
end
end
files.keys
end
def add_to_index(files)
files = files.join(' ')
system "git add #{files}"
end
end
parser = Parser.new
trailing_spaces_remover = TrailingSpacesRemover.new
if parser.exists_problem_files?
problem_files = parser.problem_files
good_files = trailing_spaces_remover.from problem_files
trailing_spaces_remover.add_to_index good_files
end
@futuraprime
Copy link
Author

There's really no good reason this is in Ruby, apart from I didn't write any of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment