overcommit 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 043d9e4f69b46108c0de597ecf9640f31149c98e
4
- data.tar.gz: 9b61ce0b7846dae6580ec4d8934b4f2ec6484eab
3
+ metadata.gz: 9e7a230157adc2af8bc8cf4b209e6b50d99d67a7
4
+ data.tar.gz: 190432fe93e3a69293a69b93bbd75460923f72b1
5
5
  SHA512:
6
- metadata.gz: c4f4dc8af420e79565d242caf90eb37148fe7cbc4f1cd015627a4f8863a16f8237da519ed738c7620dff9c35b0a6f86614e5fae0923f0a4f1cb2c3f9f1fc2876
7
- data.tar.gz: e1fd1a72991e8e708503cf870c68f333c4321eab536e010bc80eb2cff2b1f116c10f8710a540697d3d4ecd202e3e16e4a326ab8f37ede4762d800323c5d8af71
6
+ metadata.gz: 4e98e7cbe0771bb681380819fc688d27c06b6106ebb884d8bbd71ef132a77916eacf8d4fe42b997e6d70edc868436c47a7a437215258d091e337fe2474b9d001
7
+ data.tar.gz: 8481d1109df9d34d2d6306fbfb56db74e20a002444d91775aba9d5553a3e149cb37b9a0dbfacd33868f7a328fcb1a55f5371fc3f22075e15da679329e7b1b37c
data/config/default.yml CHANGED
@@ -21,12 +21,6 @@ PostCheckout:
21
21
  ALL:
22
22
  required: false
23
23
  quiet: false
24
- BundleCheck:
25
- description: 'Checking Gemfile dependencies'
26
- include:
27
- - 'Gemfile'
28
- - 'Gemfile.lock'
29
- - '*.gemspec'
30
24
  IndexTags:
31
25
  description: 'Generating tags file from source'
32
26
  enabled: false
@@ -8,6 +8,9 @@ module Overcommit::Exceptions
8
8
  # Raised when a {HookContext} is unable to setup the environment before a run.
9
9
  class HookSetupFailed < StandardError; end
10
10
 
11
+ # Raised when a {HookContext} is unable to clean the environment after a run.
12
+ class HookCleanupFailed < StandardError; end
13
+
11
14
  # Raised when a hook run was cancelled by the user.
12
15
  class HookCancelled < StandardError; end
13
16
 
@@ -42,11 +42,11 @@ module Overcommit::HookContext
42
42
  # as if nothing ever changed.
43
43
  def cleanup_environment
44
44
  unless initial_commit? || (@stash_attempted && !@changes_stashed)
45
- `git reset --hard &> /dev/null` # Ensure working tree is clean before popping stash
45
+ clear_working_tree # Ensure working tree is clean before restoring it
46
46
  end
47
47
 
48
48
  if @changes_stashed
49
- `git stash pop --index --quiet`
49
+ restore_working_tree
50
50
  end
51
51
 
52
52
  Overcommit::GitRepo.restore_merge_state
@@ -69,6 +69,26 @@ module Overcommit::HookContext
69
69
 
70
70
  private
71
71
 
72
+ # Clears the working tree so that the stash can be applied.
73
+ def clear_working_tree
74
+ result = Overcommit::Utils.execute(%w[git reset --hard])
75
+ unless result.success?
76
+ raise Overcommit::Exceptions::HookCleanupFailed,
77
+ "Unable to cleanup working tree after #{hook_script_name} hooks run:" \
78
+ "\n#{result.stderr}"
79
+ end
80
+ end
81
+
82
+ # Applies the stash to the working tree to restore the user's state.
83
+ def restore_working_tree
84
+ result = Overcommit::Utils.execute(%w[git stash pop --index --quiet])
85
+ unless result.success?
86
+ raise Overcommit::Exceptions::HookCleanupFailed,
87
+ "Unable to restore working tree after #{hook_script_name} hooks run:" \
88
+ "\n#{result.stderr}"
89
+ end
90
+ end
91
+
72
92
  # Returns whether there are any changes to the working tree, staged or
73
93
  # otherwise.
74
94
  def any_changes?
@@ -17,13 +17,18 @@ module Overcommit
17
17
 
18
18
  # Loads and runs the hooks registered for this {HookRunner}.
19
19
  def run
20
+ # ASSUMPTION: we assume the setup and cleanup calls will never need to be
21
+ # interrupted, i.e. they will finish quickly. Should further evidence
22
+ # suggest this assumption does not hold, we will have to separately wrap
23
+ # these calls to allow some sort of "are you sure?" double-interrupt
24
+ # functionality, but until that's deemed necessary let's keep it simple.
20
25
  InterruptHandler.isolate_from_interrupts do
21
26
  @context.setup_environment
22
27
  load_hooks
23
- run_hooks
28
+ result = run_hooks
29
+ @context.cleanup_environment
30
+ result
24
31
  end
25
- ensure
26
- @context.cleanup_environment
27
32
  end
28
33
 
29
34
  private
@@ -63,20 +68,23 @@ module Overcommit
63
68
 
64
69
  @printer.start_hook(hook)
65
70
 
71
+ status, output = nil, nil
72
+
66
73
  begin
67
74
  # Disable the interrupt handler during individual hook run so that
68
75
  # Ctrl-C actually stops the current hook from being run, but doesn't
69
76
  # halt the entire process.
70
- InterruptHandler.disable!
71
- status, output = hook.run_and_transform
77
+ InterruptHandler.disable_until_finished_or_interrupted do
78
+ status, output = hook.run_and_transform
79
+ end
72
80
  rescue => ex
73
81
  status = :fail
74
82
  output = "Hook raised unexpected error\n#{ex.message}"
75
83
  rescue Interrupt
84
+ # At this point, interrupt has been handled and protection is back in
85
+ # effect thanks to the InterruptHandler.
76
86
  status = :interrupt
77
87
  output = 'Hook was interrupted by Ctrl-C; restoring repo state...'
78
- ensure
79
- InterruptHandler.enable!
80
88
  end
81
89
 
82
90
  @printer.end_hook(hook, status, output)
@@ -5,22 +5,65 @@ require 'singleton'
5
5
  class InterruptHandler
6
6
  include Singleton
7
7
 
8
- attr_accessor :isolate_signals, :signal_received
8
+ attr_accessor :isolate_signals, :signal_received, :reenable_on_interrupt
9
9
 
10
10
  def initialize
11
11
  self.isolate_signals = false
12
12
  self.signal_received = false
13
+ self.reenable_on_interrupt = false
13
14
 
14
15
  Signal.trap('INT') do
15
16
  if isolate_signals
16
17
  self.signal_received = true
17
18
  else
18
- raise Interrupt
19
+ if reenable_on_interrupt
20
+ self.reenable_on_interrupt = false
21
+ self.isolate_signals = true
22
+ end
23
+
24
+ raise Interrupt # Allow interrupt to propagate to code
19
25
  end
20
26
  end
21
27
  end
22
28
 
23
29
  class << self
30
+ # Provide a way to allow a single Ctrl-C interrupt to happen and atomically
31
+ # re-enable interrupt protections once that interrupt is propagated.
32
+ #
33
+ # This prevents a race condition where code like the following:
34
+ #
35
+ # begin
36
+ # InterruptHandler.disable!
37
+ # ... do stuff ...
38
+ # rescue Interrupt
39
+ # ... handle it ...
40
+ # ensure
41
+ # InterruptHandler.enable!
42
+ # end
43
+ #
44
+ # ...could have the `enable!` call to the interrupt handler not called in
45
+ # the event another interrupt was received in between the interrupt being
46
+ # handled and the `ensure` block being entered.
47
+ #
48
+ # Thus you should always write:
49
+ #
50
+ # begin
51
+ # InterruptHandler.disable_until_finished_or_interrupted do
52
+ # ... do stuff ...
53
+ # end
54
+ # rescue Interrupt
55
+ # ... handle it ...
56
+ # rescue
57
+ # ... handle any other exceptions ...
58
+ # end
59
+ def disable_until_finished_or_interrupted
60
+ instance.reenable_on_interrupt = true
61
+ instance.isolate_signals = false
62
+ yield
63
+ ensure
64
+ instance.isolate_signals = true
65
+ end
66
+
24
67
  def disable!
25
68
  instance.isolate_signals = false
26
69
  end
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module Overcommit
3
- VERSION = '0.15.0'
3
+ VERSION = '0.16.0'
4
4
  end
@@ -4,6 +4,14 @@
4
4
  # in all of your git hooks being symlinked to this file, allowing the framework
5
5
  # to manage your hooks for you.
6
6
 
7
+ # Prevent a Ruby stack trace from appearing when we interrupt the hook.
8
+ # Note that this will be overridden when Overcommit is loaded, since the
9
+ # InterruptHandler will redefine the trap at that time.
10
+ Signal.trap('INT') do
11
+ puts 'Hook run interrupted'
12
+ exit 130
13
+ end
14
+
7
15
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
16
  if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
17
  require 'rubygems'
@@ -78,12 +86,13 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
78
86
  puts error
79
87
  puts 'Are you running an old version of Overcommit?'
80
88
  exit 69 # EX_UNAVAILABLE
81
- rescue Overcommit::Exceptions::HookSetupFailed => error
82
- puts error
89
+ rescue Overcommit::Exceptions::HookSetupFailed,
90
+ Overcommit::Exceptions::HookCleanupFailed => error
91
+ puts error.message
83
92
  exit 74 # EX_IOERR
84
93
  rescue Overcommit::Exceptions::HookCancelled
85
94
  puts 'You cancelled the hook run'
86
- exit 1
95
+ exit 130 # Ctrl-C cancel
87
96
  rescue Overcommit::Exceptions::InvalidGitRepo => error
88
97
  puts error
89
98
  exit 64 # EX_USAGE
@@ -4,6 +4,14 @@
4
4
  # in all of your git hooks being symlinked to this file, allowing the framework
5
5
  # to manage your hooks for you.
6
6
 
7
+ # Prevent a Ruby stack trace from appearing when we interrupt the hook.
8
+ # Note that this will be overridden when Overcommit is loaded, since the
9
+ # InterruptHandler will redefine the trap at that time.
10
+ Signal.trap('INT') do
11
+ puts 'Hook run interrupted'
12
+ exit 130
13
+ end
14
+
7
15
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
16
  if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
17
  require 'rubygems'
@@ -78,12 +86,13 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
78
86
  puts error
79
87
  puts 'Are you running an old version of Overcommit?'
80
88
  exit 69 # EX_UNAVAILABLE
81
- rescue Overcommit::Exceptions::HookSetupFailed => error
82
- puts error
89
+ rescue Overcommit::Exceptions::HookSetupFailed,
90
+ Overcommit::Exceptions::HookCleanupFailed => error
91
+ puts error.message
83
92
  exit 74 # EX_IOERR
84
93
  rescue Overcommit::Exceptions::HookCancelled
85
94
  puts 'You cancelled the hook run'
86
- exit 1
95
+ exit 130 # Ctrl-C cancel
87
96
  rescue Overcommit::Exceptions::InvalidGitRepo => error
88
97
  puts error
89
98
  exit 64 # EX_USAGE
@@ -4,6 +4,14 @@
4
4
  # in all of your git hooks being symlinked to this file, allowing the framework
5
5
  # to manage your hooks for you.
6
6
 
7
+ # Prevent a Ruby stack trace from appearing when we interrupt the hook.
8
+ # Note that this will be overridden when Overcommit is loaded, since the
9
+ # InterruptHandler will redefine the trap at that time.
10
+ Signal.trap('INT') do
11
+ puts 'Hook run interrupted'
12
+ exit 130
13
+ end
14
+
7
15
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
16
  if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
17
  require 'rubygems'
@@ -78,12 +86,13 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
78
86
  puts error
79
87
  puts 'Are you running an old version of Overcommit?'
80
88
  exit 69 # EX_UNAVAILABLE
81
- rescue Overcommit::Exceptions::HookSetupFailed => error
82
- puts error
89
+ rescue Overcommit::Exceptions::HookSetupFailed,
90
+ Overcommit::Exceptions::HookCleanupFailed => error
91
+ puts error.message
83
92
  exit 74 # EX_IOERR
84
93
  rescue Overcommit::Exceptions::HookCancelled
85
94
  puts 'You cancelled the hook run'
86
- exit 1
95
+ exit 130 # Ctrl-C cancel
87
96
  rescue Overcommit::Exceptions::InvalidGitRepo => error
88
97
  puts error
89
98
  exit 64 # EX_USAGE
@@ -4,6 +4,14 @@
4
4
  # in all of your git hooks being symlinked to this file, allowing the framework
5
5
  # to manage your hooks for you.
6
6
 
7
+ # Prevent a Ruby stack trace from appearing when we interrupt the hook.
8
+ # Note that this will be overridden when Overcommit is loaded, since the
9
+ # InterruptHandler will redefine the trap at that time.
10
+ Signal.trap('INT') do
11
+ puts 'Hook run interrupted'
12
+ exit 130
13
+ end
14
+
7
15
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
16
  if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
17
  require 'rubygems'
@@ -78,12 +86,13 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
78
86
  puts error
79
87
  puts 'Are you running an old version of Overcommit?'
80
88
  exit 69 # EX_UNAVAILABLE
81
- rescue Overcommit::Exceptions::HookSetupFailed => error
82
- puts error
89
+ rescue Overcommit::Exceptions::HookSetupFailed,
90
+ Overcommit::Exceptions::HookCleanupFailed => error
91
+ puts error.message
83
92
  exit 74 # EX_IOERR
84
93
  rescue Overcommit::Exceptions::HookCancelled
85
94
  puts 'You cancelled the hook run'
86
- exit 1
95
+ exit 130 # Ctrl-C cancel
87
96
  rescue Overcommit::Exceptions::InvalidGitRepo => error
88
97
  puts error
89
98
  exit 64 # EX_USAGE
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: overcommit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Causes Engineering
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-28 00:00:00.000000000 Z
12
+ date: 2014-08-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: childprocess
@@ -94,7 +94,6 @@ files:
94
94
  - lib/overcommit/hook/commit_msg/hard_tabs.rb
95
95
  - lib/overcommit/hook/commit_msg/text_width.rb
96
96
  - lib/overcommit/hook/commit_msg/base.rb
97
- - lib/overcommit/hook/post_checkout/bundle_check.rb
98
97
  - lib/overcommit/hook/post_checkout/index_tags.rb
99
98
  - lib/overcommit/hook/post_checkout/base.rb
100
99
  - lib/overcommit/hook/base.rb
@@ -1,33 +0,0 @@
1
- module Overcommit::Hook::PostCheckout
2
- # If Gemfile dependencies were modified since HEAD was changed, check if
3
- # currently installed gems satisfy the dependencies.
4
- class BundleCheck < Base
5
- def run
6
- unless in_path?('bundle')
7
- return :warn, 'bundler not installed -- run `gem install bundler`'
8
- end
9
-
10
- if dependencies_changed? && !dependencies_satisfied?
11
- return :warn, "#{LOCK_FILE} is not up-to-date -- run `bundle check`"
12
- end
13
-
14
- :pass
15
- end
16
-
17
- private
18
-
19
- LOCK_FILE = 'Gemfile.lock'
20
-
21
- def dependencies_changed?
22
- result = execute(%w[git diff --exit-code --name-only] + [new_head, previous_head])
23
-
24
- result.stdout.split("\n").any? do |file|
25
- Array(config['include']).any? { |glob| Dir[glob].include?(file) }
26
- end
27
- end
28
-
29
- def dependencies_satisfied?
30
- execute(%w[bundle check]).success?
31
- end
32
- end
33
- end