Created
June 18, 2012 15:32
-
-
Save futuraprime/2948929 to your computer and use it in GitHub Desktop.
Pre-commit error catcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's really no good reason this is in Ruby, apart from I didn't write any of it.