overcommit 0.15.0 → 0.16.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 +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
|