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 +4 -4
- data/config/default.yml +0 -6
- data/lib/overcommit/exceptions.rb +3 -0
- data/lib/overcommit/hook_context/pre_commit.rb +22 -2
- data/lib/overcommit/hook_runner.rb +15 -7
- data/lib/overcommit/interrupt_handler.rb +45 -2
- data/lib/overcommit/version.rb +1 -1
- data/template-dir/hooks/commit-msg +12 -3
- data/template-dir/hooks/overcommit-hook +12 -3
- data/template-dir/hooks/post-checkout +12 -3
- data/template-dir/hooks/pre-commit +12 -3
- metadata +2 -3
- data/lib/overcommit/hook/post_checkout/bundle_check.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e7a230157adc2af8bc8cf4b209e6b50d99d67a7
|
4
|
+
data.tar.gz: 190432fe93e3a69293a69b93bbd75460923f72b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
45
|
+
clear_working_tree # Ensure working tree is clean before restoring it
|
46
46
|
end
|
47
47
|
|
48
48
|
if @changes_stashed
|
49
|
-
|
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.
|
71
|
-
|
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
|
-
|
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
|
data/lib/overcommit/version.rb
CHANGED
@@ -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
|
82
|
-
|
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
|
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
|
82
|
-
|
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
|
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
|
82
|
-
|
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
|
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
|
82
|
-
|
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
|
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.
|
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-
|
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
|