diff --git a/README.md b/README.md index 7f996177..af718032 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,7 @@ Option | Description `processors` | The number of processing units to reserve for this hook. This does not reserve CPUs, but indicates that out of the total number of possible concurrent hooks allowed by the global `concurrency` option, this hook requires the specified number. Thus in the typical case where `concurrency` is set to the number of available cores (default), and you have a hook that executes an application which itself creates 2 threads (or is otherwise scheduled on 2 cores), you can indicate that Overcommit should allocate 2 `processors` to the hook. Ideally this means your hooks won't put undue load on your available cores. `install_command` | Command the user can run to install the `required_executable` (or alternately the specified `required_libraries`). This is intended for documentation purposes, as Overcommit does not install software on your behalf since there are too many edge cases where such behavior would result in incorrectly configured installations (e.g. installing a Python package in the global package space instead of in a virtual environment). `skip_file_checkout` | Whether to skip this hook for file checkouts (e.g. `git checkout some-ref -- file`). Only applicable to `PostCheckout` hooks. +`skip_if` | Array of arguments to be executed to determine whether or not the hook should run. For example, setting this to a value of `['bash', '-c', '! which my-executable']` would allow you to skip running this hook if `my-executable` was not in the bin path. In addition to the built-in configuration options, each hook can expose its own unique configuration options. The `AuthorEmail` hook, for example, allows diff --git a/lib/overcommit/hook/base.rb b/lib/overcommit/hook/base.rb index 4f48d770..37696d08 100644 --- a/lib/overcommit/hook/base.rb +++ b/lib/overcommit/hook/base.rb @@ -84,7 +84,8 @@ def excluded? end def skip? - @config['skip'] + @config['skip'] || + (@config['skip_if'] ? execute(@config['skip_if']).success? : false) end def run? diff --git a/spec/overcommit/hook/base_spec.rb b/spec/overcommit/hook/base_spec.rb index 8a0e5d46..0c8c7af7 100644 --- a/spec/overcommit/hook/base_spec.rb +++ b/spec/overcommit/hook/base_spec.rb @@ -122,4 +122,69 @@ end end end + + context '#skip?' do + before do + config.stub(:for_hook).and_return(hook_config) + end + + subject { hook.skip? } + + context 'with skip_if not specified' do + let(:hook_config) do + { 'skip' => skip } + end + + context 'with skip true' do + let(:skip) { true } + + it { subject.should == true } + end + + context 'with skip false' do + let(:skip) { false } + + it { subject.should == false } + end + end + + context 'with skip_if specified' do + before do + result = Overcommit::Subprocess::Result.new(success ? 0 : 1, '', '') + allow(Overcommit::Utils).to receive(:execute).and_return(result) + end + + let(:hook_config) do + { 'skip' => skip, 'skip_if' => ['bash', '-c', '! which my-executable'] } + end + + context 'with skip true and skip_if returning true' do + let(:skip) { true } + let(:success) { true } + + it { subject.should == true } + end + + context 'with skip true and skip_if returning false' do + let(:skip) { true } + let(:success) { false } + + it { subject.should == true } + end + + context 'with skip false and skip_if returning true' do + let(:skip) { false } + let(:success) { true } + + it { subject.should == true } + end + + context 'with skip false and skip_if returning false' do + let(:skip) { false } + let(:success) { false } + + it { subject.should == false } + end + end + end end