git-hooks 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e9ac25d07132d4f6863fd59f76a6701a50f722e
4
- data.tar.gz: 49d1ca7b2397c04777d52e2b4640a5adab33ba63
3
+ metadata.gz: 1eb1b43db79e2fee7f1e80b606a5f179d9ef6e01
4
+ data.tar.gz: 4c406f7fa4c304979c38479a7b7e3aee4e3775d1
5
5
  SHA512:
6
- metadata.gz: 7a098c47f8872d7e8ecc6ac350d791d07f760e5e316e00a956b6dd9bd238b8582687b6218e55289d3b5de9fa7b0b4ad73875cf4c3ed5de25a054e5c79793ace1
7
- data.tar.gz: 2927c77962ac840deac371dc161de5cf7502e76082df7ee183bfb626dc383ada485c353fbc94ed526ab758787da93e8908b4c1b882b58a76cfa506b63a838952
6
+ metadata.gz: 8e738a492bf589e366da29a5355a85c54c5d7990e369b0479f2cd3a325b7c78b619bd1d0df26fb25932fdcc19ca30ae600699ffd9b9689f58b26d57f897a4eb8
7
+ data.tar.gz: ce5edbedf28705755913ef38b183ad64d8e60fe58dec7837be37350ff0779aad3c49213932ced1c7d755f476bc9e355b1142150702ee9904c05374c902dcebbe
@@ -0,0 +1,8 @@
1
+ ---
2
+ pre_commits:
3
+ GitHooks::PreCommit::TrailingWhitespace:
4
+ GitHooks::PreCommit::PreventDebugger:
5
+ GitHooks::PreCommit::PreventMaster:
6
+ GitHooks::PreCommit::Rubocop:
7
+ use_stash: true
8
+ GitHooks::PreCommit::Rspec:
@@ -2,4 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - '2.0.0'
4
4
  - '2.1.0'
5
+ - '2.1.5'
6
+ - '2.2.0'
5
7
  script: bundle exec rspec
data/README.md CHANGED
@@ -6,8 +6,8 @@
6
6
 
7
7
  # GitHooks
8
8
 
9
- Some usefull git hooks, it's written on ruby but can be used for other
10
- languages.
9
+ This gem provides an interface to write useful git hooks in Ruby. Those hooks
10
+ can be used when working in projects in any programming language.
11
11
 
12
12
  ## Installation
13
13
 
@@ -48,17 +48,21 @@ By now you will find the following built-in hooks:
48
48
  - Prevent commits with debugger.
49
49
  - Prevent commits with trailing white space.
50
50
 
51
+ ### Warning about `Rubocop` pre-commit `use_stash` option:
52
+
53
+ This feature is yet experimental. Be aware that in some odd circumstances you
54
+ may encounter merge conflicts when applying the stash.
55
+
51
56
  ### Ensure hooks existence
52
57
 
53
- To ensure that hooks exists on `.git/hooks`, include this line
58
+ To ensure that hooks exists on `.git/hooks`, include the following line on your
59
+ application's start-up code (e.g. `config/environments/development.rb` or
60
+ `config/environments/test.rb` for a rails app).
54
61
 
55
62
  ```ruby
56
63
  GitHooks.validate_hooks!
57
64
  ```
58
65
 
59
- on your application's start up (e.g. `config/environments/development.rb` or
60
- `config/environments/test.rb` for a rails app).
61
-
62
66
  This will force `git_hooks` installation before your application's start.
63
67
 
64
68
  ## Contributing
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  pre_commits:
3
- - GitHooks::PreCommit::TrailingWhitespace
4
- - GitHooks::PreCommit::PreventDebugger
5
- - GitHooks::PreCommit::PreventMaster
6
- - GitHooks::PreCommit::Rubocop
7
- - GitHooks::PreCommit::Rspec
3
+ GitHooks::PreCommit::TrailingWhitespace:
4
+ GitHooks::PreCommit::PreventDebugger:
5
+ GitHooks::PreCommit::PreventMaster:
6
+ GitHooks::PreCommit::Rubocop:
7
+ use_stash: false
8
+ GitHooks::PreCommit::Rspec:
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'git-hooks'
3
3
 
4
+ puts 'Running pre-commit hooks...'
5
+
4
6
  GitHooks.execute_pre_commits
@@ -24,9 +24,10 @@ module GitHooks
24
24
  attr_writer :configurations
25
25
 
26
26
  def execute_pre_commits
27
- configurations.pre_commits.each do |pre_commit|
27
+ configurations.pre_commits.each do |pre_commit, options|
28
28
  puts "Executing #{pre_commit}"
29
- GitHooks::PreCommit.const_get(pre_commit).validate
29
+ pre_commit_checker = GitHooks::PreCommit.const_get(pre_commit)
30
+ pre_commit_checker.validate(options)
30
31
  end
31
32
  end
32
33
 
@@ -54,3 +55,19 @@ module GitHooks
54
55
  end
55
56
  end
56
57
  end
58
+
59
+ # TODO: Fix this in the ruby-git gem.
60
+
61
+ # Since the `Git` gem does not provide us with an api that allows you to use the
62
+ # '--keep-index' option when stashing, we are stuck with this monkey patch.
63
+ module Git
64
+ class Lib
65
+ def stash_pop(_ = nil)
66
+ command('stash pop')
67
+ end
68
+
69
+ def stash_save(message)
70
+ command('stash save', ['--keep-index', message])
71
+ end
72
+ end
73
+ end
@@ -3,7 +3,7 @@ module GitHooks
3
3
  class PreventDebugger
4
4
  attr_reader :git_repository
5
5
 
6
- def self.validate
6
+ def self.validate(*)
7
7
  new(GitHooks.configurations.git_repository).validate
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ module GitHooks
3
3
  class PreventMaster
4
4
  attr_reader :git_repository
5
5
 
6
- def self.validate
6
+ def self.validate(*)
7
7
  new(GitHooks.configurations.git_repository).validate
8
8
  end
9
9
 
@@ -1,16 +1,16 @@
1
1
  module GitHooks
2
2
  module PreCommit
3
3
  class Rspec
4
- attr_reader :git_repository, :rspec_executor
5
-
6
- def self.validate
4
+ def self.validate(*)
7
5
  new(
8
- GitHooks.configurations.git_repository, RspecExecutor.new
6
+ GitHooks.configurations.git_repository,
7
+ RspecExecutor.new
9
8
  ).validate
10
9
  end
11
10
 
12
11
  def initialize(git_repository, rspec_executor)
13
- @git_repository, @rspec_executor = git_repository, rspec_executor
12
+ @git_repository = git_repository
13
+ @rspec_executor = rspec_executor
14
14
  end
15
15
 
16
16
  def validate
@@ -18,6 +18,10 @@ module GitHooks
18
18
 
19
19
  abort 'Prevented broken commit' if rspec_executor.errors?
20
20
  end
21
+
22
+ protected
23
+
24
+ attr_reader :git_repository, :rspec_executor
21
25
  end
22
26
  end
23
27
  end
@@ -1,32 +1,73 @@
1
1
  module GitHooks
2
2
  module PreCommit
3
3
  class Rubocop
4
- attr_reader :git_repository, :rubocop_validator
4
+ RUBOCOP_STASH_NAME = 'rubocop-stash'
5
5
 
6
- def self.validate
6
+ def self.validate(options = {})
7
7
  new(
8
- GitHooks.configurations.git_repository, RubocopValidator.new
8
+ GitHooks.configurations.git_repository,
9
+ RubocopValidator.new,
10
+ options
9
11
  ).validate
10
12
  end
11
13
 
12
- def initialize(git_repository, rubocop_validator)
13
- @git_repository, @rubocop_validator = git_repository, rubocop_validator
14
+ def initialize(git, rubocop_validator, options = {})
15
+ @git = git
16
+ @rubocop_validator = rubocop_validator
17
+ @options = options
14
18
  end
15
19
 
16
20
  def validate
17
21
  abort 'Check rubocop offences' if offences?
18
22
  end
19
23
 
24
+ protected
25
+
26
+ attr_reader :git, :rubocop_validator, :options
27
+
20
28
  private
21
29
 
22
30
  def changed_files
23
- git_repository
31
+ git
24
32
  .added_or_modified
25
- .select { |file| File.extname(file) == '.rb' }
33
+ .select(&ruby_files)
26
34
  end
27
35
 
28
36
  def offences?
29
- rubocop_validator.errors?(changed_files)
37
+ stash_me_maybe { rubocop_validator.errors?(changed_files) }
38
+ end
39
+
40
+ def ruby_files
41
+ -> (file) { File.extname(file) == '.rb' }
42
+ end
43
+
44
+ def stash_me_maybe(&blk)
45
+ return yield unless stash_around?
46
+
47
+ stash_around(&blk)
48
+ end
49
+
50
+ def stash_around
51
+ git.repository.lib.stash_save(RUBOCOP_STASH_NAME)
52
+ yield
53
+ ensure
54
+ git.repository.lib.stash_pop(rubocop_stash_id) if rubocop_stash?
55
+ end
56
+
57
+ def stash_around?
58
+ options['use_stash']
59
+ end
60
+
61
+ def rubocop_stash?
62
+ rubocop_stash_id
63
+ end
64
+
65
+ def rubocop_stash_id
66
+ Array(
67
+ git.repository.lib
68
+ .stashes_all
69
+ .rassoc(RUBOCOP_STASH_NAME)
70
+ ).first
30
71
  end
31
72
  end
32
73
  end
@@ -3,7 +3,7 @@ module GitHooks
3
3
  class TrailingWhitespace
4
4
  attr_reader :git_repository, :trailing_whitespace_validator
5
5
 
6
- def self.validate
6
+ def self.validate(*)
7
7
  new(
8
8
  GitHooks.configurations.git_repository,
9
9
  TrailingWhitespaceValidator.new
@@ -1,3 +1,3 @@
1
1
  module GitHooks
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -1,4 +1,5 @@
1
1
  ---
2
2
  pre_commits:
3
- - foo
4
- - bar
3
+ Rubocop:
4
+ use_stash: true
5
+ Rspec:
@@ -0,0 +1,121 @@
1
+ describe GitHooks do
2
+ subject(:git_hooks) { described_class }
3
+
4
+ let(:configs) do
5
+ GitHooks::Configurations.new(config_file: config_file)
6
+ end
7
+
8
+ let(:config_file) do
9
+ GitHooks::ConfigFile.new(fixture_path('git_hooks.yml'))
10
+ end
11
+
12
+ before do
13
+ GitHooks.configurations = configs
14
+ allow($stdout).to receive(:write)
15
+ end
16
+
17
+ describe '#validate_hooks!' do
18
+ subject { -> { git_hooks.validate_hooks! } }
19
+
20
+ let(:installed?) { true }
21
+ let(:installer) { instance_double(GitHooks::Installer) }
22
+
23
+ before do
24
+ allow(GitHooks::Installer)
25
+ .to receive(:new)
26
+ .with(GitHooks::PRE_COMMIT)
27
+ .and_return(installer)
28
+ end
29
+
30
+ before do
31
+ allow(installer).to receive(:installed?).and_return(installed?)
32
+ end
33
+
34
+ it { is_expected.to_not raise_error }
35
+
36
+ context 'but without pre-commit installed' do
37
+ let(:installed?) { false }
38
+
39
+ let(:message) do
40
+ "Please install pre-commit hook with `git_hooks install pre-commit'"
41
+ end
42
+
43
+ it do
44
+ is_expected.to raise_error(GitHooks::Exceptions::MissingHook, message)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '.base_path' do
50
+ subject { described_class.base_path }
51
+
52
+ it "has gem's root path" do
53
+ is_expected.to eq(
54
+ File.absolute_path(
55
+ File.join(File.expand_path(__FILE__), '..', '..')
56
+ )
57
+ )
58
+ end
59
+ end
60
+
61
+ describe '.configurations' do
62
+ subject(:configurations) { described_class.configurations }
63
+
64
+ before { GitHooks.configurations = nil }
65
+
66
+ let(:configs) { double(:probe) }
67
+
68
+ it 'creates with default params' do
69
+ expect(GitHooks::Configurations)
70
+ .to receive(:new)
71
+ .with(no_args)
72
+ .and_return(configs)
73
+
74
+ is_expected.to eq(configs)
75
+ end
76
+ end
77
+
78
+ describe 'configurations=' do
79
+ subject { -> { GitHooks.configurations = configs } }
80
+
81
+ let!(:configs) { double(:probe) }
82
+
83
+ before { GitHooks.configurations = nil }
84
+ after { GitHooks.configurations = nil }
85
+
86
+ it 'updates configurations' do
87
+ is_expected.to change { GitHooks.configurations }.to(configs)
88
+ end
89
+ end
90
+
91
+ describe '#execute_pre_commits' do
92
+ subject(:execute_pre_commits) { GitHooks.execute_pre_commits }
93
+
94
+ let(:rubocop_options) do
95
+ { 'use_stash' => true }
96
+ end
97
+
98
+ before do
99
+ allow(GitHooks::PreCommit::Rspec).to receive(:validate)
100
+ allow(GitHooks::PreCommit::Rubocop).to receive(:validate)
101
+ end
102
+
103
+ it 'instantiates each pre commit' do
104
+ expect(GitHooks::PreCommit).to receive(:const_get)
105
+ .with('Rubocop').and_call_original
106
+ expect(GitHooks::PreCommit).to receive(:const_get)
107
+ .with('Rspec').and_call_original
108
+
109
+ execute_pre_commits
110
+ end
111
+
112
+ it 'validates the hook, passing its options when available' do
113
+ expect(GitHooks::PreCommit::Rubocop).to receive(:validate)
114
+ .with(rubocop_options)
115
+ expect(GitHooks::PreCommit::Rspec).to receive(:validate)
116
+ .with(nil)
117
+
118
+ execute_pre_commits
119
+ end
120
+ end
121
+ end
@@ -4,7 +4,12 @@ module GitHooks
4
4
 
5
5
  let(:path) { 'some-not-existent-file' }
6
6
  let(:content) { { 'pre_commits' => pre_commits } }
7
- let(:pre_commits) { %w(foo bar) }
7
+ let(:pre_commits) do
8
+ {
9
+ 'Rubocop' => { 'use_stash' => true },
10
+ 'Rspec' => nil
11
+ }
12
+ end
8
13
 
9
14
  describe '#pre_commits' do
10
15
  subject { config.pre_commits }
@@ -12,11 +17,11 @@ module GitHooks
12
17
  let(:path) { fixture_path('git_hooks.yml') }
13
18
 
14
19
  it 'has the pre commits specified on hook file' do
15
- is_expected.to eq(%w(foo bar))
20
+ is_expected.to eq(pre_commits)
16
21
  end
17
22
 
18
23
  context 'when the given file does not exist' do
19
- let(:path) { 'some-not-existent-file' }
24
+ let(:path) { 'some-non-existing-file' }
20
25
 
21
26
  it { is_expected.to eq([]) }
22
27
  end
@@ -1,7 +1,7 @@
1
1
  module GitHooks
2
2
  module PreCommit
3
3
  describe Rspec do
4
- subject(:rspec) { described_class.new git_repository, rspec_executor }
4
+ subject(:rspec) { described_class.new(git_repository, rspec_executor) }
5
5
 
6
6
  let(:git_repository) do
7
7
  instance_double(GitHooks::Git, clean?: clean?)
@@ -44,6 +44,44 @@ module GitHooks
44
44
 
45
45
  it { expect(-> { validate }).to_not raise_error }
46
46
  end
47
+
48
+ context 'with stash option' do
49
+ let(:rubocop) do
50
+ described_class.new(
51
+ git_repository, rubocop_validator, 'use_stash' => true
52
+ )
53
+ end
54
+
55
+ let(:repository) { instance_double(::Git::Base) }
56
+ let(:lib) { instance_double(::Git::Lib) }
57
+
58
+ before do
59
+ allow(repository).to receive(:lib).and_return(lib)
60
+ allow(git_repository).to receive(:repository).and_return(repository)
61
+ allow(lib).to receive(:stash_save).and_return(true)
62
+ allow(lib).to receive(:stash_pop).and_return(true)
63
+ allow(lib).to receive(:stashes_all).and_return([[0, 'rubocop-stash']])
64
+ end
65
+
66
+ it 'stashes working directory changes and reapplies them' do
67
+ expect(lib).to receive(:stash_save).with('rubocop-stash')
68
+ expect(lib).to receive(:stash_pop)
69
+
70
+ expect(-> { validate }).not_to raise_error
71
+ end
72
+
73
+ context 'with validation error' do
74
+ let(:errors?) { true }
75
+
76
+ it 'stashes working directory changes and reapplies them' do
77
+ expect(lib).to receive(:stash_save).with('rubocop-stash')
78
+ expect(lib).to receive(:stash_pop)
79
+
80
+ expect(-> { validate }).to raise_error(SystemExit)
81
+ .and output("Check rubocop offences\n").to_stderr
82
+ end
83
+ end
84
+ end
47
85
  end
48
86
 
49
87
  describe '.validate' do
@@ -62,7 +100,7 @@ module GitHooks
62
100
  end
63
101
 
64
102
  it 'creates object with git_repository and rubocop_validator' do
65
- expect(Rubocop).to receive(:new).with(git, rubocop_validator)
103
+ expect(Rubocop).to receive(:new).with(git, rubocop_validator, {})
66
104
 
67
105
  validate
68
106
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-hooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael da Silva Almeida
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -130,6 +130,7 @@ executables:
130
130
  extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
+ - ".git_hooks.yml"
133
134
  - ".gitignore"
134
135
  - ".rspec"
135
136
  - ".rubocop.yml"
@@ -138,6 +139,7 @@ files:
138
139
  - CHANGELOG
139
140
  - Gemfile
140
141
  - README.md
142
+ - Rakefile
141
143
  - bin/git_hooks
142
144
  - git-hooks.gemspec
143
145
  - git_hooks.yml.example
@@ -162,6 +164,7 @@ files:
162
164
  - lib/git_hooks/trailing_whitespace_validator.rb
163
165
  - lib/git_hooks/version.rb
164
166
  - spec/fixtures/git_hooks.yml
167
+ - spec/git-hooks_spec.rb
165
168
  - spec/git_hooks/config_file_spec.rb
166
169
  - spec/git_hooks/configurations_spec.rb
167
170
  - spec/git_hooks/git_spec.rb
@@ -174,7 +177,6 @@ files:
174
177
  - spec/git_hooks/rspec_executor_spec.rb
175
178
  - spec/git_hooks/rubocop_validator_spec.rb
176
179
  - spec/git_hooks/trailing_space_validator.rb
177
- - spec/git_hooks_spec.rb
178
180
  - spec/spec_helper.rb
179
181
  homepage: http://github.com/stupied4ever/ruby-git-hooks
180
182
  licenses:
@@ -202,6 +204,7 @@ specification_version: 4
202
204
  summary: Help to keep git hooks organized.
203
205
  test_files:
204
206
  - spec/fixtures/git_hooks.yml
207
+ - spec/git-hooks_spec.rb
205
208
  - spec/git_hooks/config_file_spec.rb
206
209
  - spec/git_hooks/configurations_spec.rb
207
210
  - spec/git_hooks/git_spec.rb
@@ -214,6 +217,5 @@ test_files:
214
217
  - spec/git_hooks/rspec_executor_spec.rb
215
218
  - spec/git_hooks/rubocop_validator_spec.rb
216
219
  - spec/git_hooks/trailing_space_validator.rb
217
- - spec/git_hooks_spec.rb
218
220
  - spec/spec_helper.rb
219
221
  has_rdoc:
@@ -1,89 +0,0 @@
1
- describe GitHooks do
2
- describe '#validate_hooks!' do
3
- subject { -> { described_class.validate_hooks! } }
4
-
5
- before do
6
- allow(GitHooks::Installer)
7
- .to receive(:new)
8
- .with(GitHooks::PRE_COMMIT)
9
- .and_return(installer)
10
-
11
- GitHooks.configurations = configs
12
- end
13
-
14
- let(:configs) do
15
- GitHooks::Configurations.new(config_file: config_file)
16
- end
17
-
18
- let(:config_file) do
19
- GitHooks::ConfigFile.new(fixture_path('git_hooks.yml'))
20
- end
21
-
22
- let(:installed?) { true }
23
- let(:installer) { instance_double(GitHooks::Installer) }
24
-
25
- before do
26
- allow(installer).to receive(:installed?).and_return(installed?)
27
- end
28
-
29
- it { is_expected.to_not raise_error }
30
-
31
- context 'but without pre-commit installed' do
32
- let(:installed?) { false }
33
-
34
- let(:message) do
35
- "Please install pre-commit hook with `git_hooks install pre-commit'"
36
- end
37
-
38
- it do
39
- is_expected.to raise_error(GitHooks::Exceptions::MissingHook, message)
40
- end
41
- end
42
- end
43
-
44
- describe '.base_path' do
45
- subject { described_class.base_path }
46
-
47
- it "has gem's root path" do
48
- is_expected.to eq(
49
- File.absolute_path(
50
- File.join(File.expand_path(__FILE__), '..', '..')
51
- )
52
- )
53
- end
54
- end
55
-
56
- describe '.configurations' do
57
- subject(:configurations) { described_class.configurations }
58
-
59
- before { GitHooks.configurations = nil }
60
-
61
- let(:configs) { instance_double(GitHooks::Configurations) }
62
-
63
- it 'creates with default params' do
64
- expect(GitHooks::Configurations)
65
- .to receive(:new)
66
- .with(no_args)
67
- .and_return(configs)
68
-
69
- is_expected.to eq(configs)
70
- end
71
- end
72
-
73
- describe 'configurations=' do
74
- subject(:set_configurations) { GitHooks.configurations = configs }
75
-
76
- let(:configs) { instance_double(GitHooks::Configurations) }
77
-
78
- before do
79
- GitHooks.configurations = nil
80
- allow(GitHooks::Configurations).to receive(:new).and_return(nil)
81
- end
82
-
83
- it 'updates configurations' do
84
- expect { set_configurations }.to change {
85
- GitHooks.configurations
86
- }.to(configs)
87
- end
88
- end
89
- end