views:

28

answers:

1

I'm trying to add some commit hooks to my git repo. I want to leverage Rspec and create commit message specs that will run each time I commit. I have figured out how to run rspec outside of the 'spec' command, but I now have an interesting problem.

Here is my current code:

.git/hooks/commit-msg

#!/usr/bin/env ruby

require 'rubygems'
require 'spec/autorun'

message = File.read(ARGV[0])

describe "failing" do
    it "should fail" do
        true.should == false
    end
end

This is throwing an error when it gets to the describe call. Basically, it thinks that the commit message it receives is the file to load and run the specs against. Here is the actually error

./.git/COMMIT_EDITMSG:1: undefined local variable or method `commit-message-here' for main:Object (NameError)
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `load'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `load_files'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `each'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `load_files'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner/options.rb:133:in `run_examples'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner.rb:61:in `run'
from /Users/roykolak/.gem/ruby/1.8/gems/rspec-1.3.0/lib/spec/runner.rb:45:in `autorun'
from .git/hooks/commit-msg:12

I am looking for a way to tell rspec to not load files. I have a suspicion that I will need to create my own spec runner. I came to this conclusion after viewing these lines in rspec-1.3.0/lib/spec/runner/example_group_runner.rb

  def load_files(files)
    $KCODE = 'u' if RUBY_VERSION.to_f < 1.9
    # It's important that loading files (or choosing not to) stays the
    # responsibility of the ExampleGroupRunner. Some implementations (like)
    # the one using DRb may choose *not* to load files, but instead tell
    # someone else to do it over the wire.
    files.each do |file|
      load file
    end
  end

But, I would like some feedback before I do that. Any thoughts?

A: 

Do you even really need all the special stuff that RSpec provides (should and the various matchers) just to verify the contents of a single file? It really seems like overkill for the problem.


spec/autorun eventually calls Spec::Runner.autorun which parses ARGV as if it held normal arguments for a spec command line.

When you install a bare “spec” file as a Git hook, it will get arguments that are appropriate for the whatever Git hook is being used, not spec-style arguments (spec filenames/directories/patterns and spec options).

You might be able to hack around the problem like this:

# Save original ARGV, replace its elements with spec arguments
orig_argv = ARGV.dup
%w(--format nested).inject(ARGV.clear, :<<)

require 'rubygems'
require 'spec/autorun'

# rest of your code/spec
# NOTE: to refer to the Git hook arguments use orig_argv instead of ARGV 
Chris Johnsen
Thanks for the idea Chris. I wanted to use rspec exactly for that reason: the matchers, organization, reporting, pass/fail.I wanted to be able to run checks like: "The first line of the commit message should be less than 51 characters", or "The message should contain a bug number", etc...rspec gives me all this functionality, plus a unified (and familiar) reporting output
Roy Kolak