jawshooah-overcommit 0.22.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 +7 -0
- data/bin/overcommit +8 -0
- data/config/default.yml +275 -0
- data/config/starter.yml +31 -0
- data/lib/overcommit.rb +20 -0
- data/lib/overcommit/cli.rb +205 -0
- data/lib/overcommit/configuration.rb +183 -0
- data/lib/overcommit/configuration_loader.rb +49 -0
- data/lib/overcommit/configuration_validator.rb +40 -0
- data/lib/overcommit/constants.rb +8 -0
- data/lib/overcommit/exceptions.rb +35 -0
- data/lib/overcommit/git_repo.rb +147 -0
- data/lib/overcommit/hook/base.rb +174 -0
- data/lib/overcommit/hook/commit_msg/base.rb +11 -0
- data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +18 -0
- data/lib/overcommit/hook/commit_msg/hard_tabs.rb +13 -0
- data/lib/overcommit/hook/commit_msg/russian_novel.rb +14 -0
- data/lib/overcommit/hook/commit_msg/single_line_subject.rb +12 -0
- data/lib/overcommit/hook/commit_msg/text_width.rb +38 -0
- data/lib/overcommit/hook/commit_msg/trailing_period.rb +12 -0
- data/lib/overcommit/hook/post_checkout/base.rb +11 -0
- data/lib/overcommit/hook/post_checkout/index_tags.rb +26 -0
- data/lib/overcommit/hook/post_commit/base.rb +11 -0
- data/lib/overcommit/hook/post_commit/git_guilt.rb +9 -0
- data/lib/overcommit/hook/pre_commit/author_email.rb +18 -0
- data/lib/overcommit/hook/pre_commit/author_name.rb +17 -0
- data/lib/overcommit/hook/pre_commit/base.rb +70 -0
- data/lib/overcommit/hook/pre_commit/berksfile_check.rb +20 -0
- data/lib/overcommit/hook/pre_commit/brakeman.rb +12 -0
- data/lib/overcommit/hook/pre_commit/broken_symlinks.rb +15 -0
- data/lib/overcommit/hook/pre_commit/bundle_check.rb +25 -0
- data/lib/overcommit/hook/pre_commit/chamber_security.rb +11 -0
- data/lib/overcommit/hook/pre_commit/coffee_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/css_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/go_lint.rb +12 -0
- data/lib/overcommit/hook/pre_commit/haml_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/hard_tabs.rb +14 -0
- data/lib/overcommit/hook/pre_commit/image_optim.rb +41 -0
- data/lib/overcommit/hook/pre_commit/js_hint.rb +13 -0
- data/lib/overcommit/hook/pre_commit/jscs.rb +22 -0
- data/lib/overcommit/hook/pre_commit/json_syntax.rb +22 -0
- data/lib/overcommit/hook/pre_commit/jsx_hint.rb +13 -0
- data/lib/overcommit/hook/pre_commit/jsxcs.rb +20 -0
- data/lib/overcommit/hook/pre_commit/local_paths_in_gemfile.rb +14 -0
- data/lib/overcommit/hook/pre_commit/merge_conflicts.rb +14 -0
- data/lib/overcommit/hook/pre_commit/pry_binding.rb +14 -0
- data/lib/overcommit/hook/pre_commit/python_flake8.rb +11 -0
- data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +45 -0
- data/lib/overcommit/hook/pre_commit/reek.rb +22 -0
- data/lib/overcommit/hook/pre_commit/rubocop.rb +19 -0
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/shell_check.rb +19 -0
- data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +13 -0
- data/lib/overcommit/hook/pre_commit/travis_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +22 -0
- data/lib/overcommit/hook_context.rb +17 -0
- data/lib/overcommit/hook_context/base.rb +69 -0
- data/lib/overcommit/hook_context/commit_msg.rb +32 -0
- data/lib/overcommit/hook_context/post_checkout.rb +26 -0
- data/lib/overcommit/hook_context/post_commit.rb +19 -0
- data/lib/overcommit/hook_context/pre_commit.rb +148 -0
- data/lib/overcommit/hook_context/run_all.rb +39 -0
- data/lib/overcommit/hook_loader/base.rb +36 -0
- data/lib/overcommit/hook_loader/built_in_hook_loader.rb +12 -0
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +61 -0
- data/lib/overcommit/hook_runner.rb +129 -0
- data/lib/overcommit/hook_signer.rb +79 -0
- data/lib/overcommit/installer.rb +148 -0
- data/lib/overcommit/interrupt_handler.rb +87 -0
- data/lib/overcommit/logger.rb +79 -0
- data/lib/overcommit/message_processor.rb +132 -0
- data/lib/overcommit/printer.rb +116 -0
- data/lib/overcommit/subprocess.rb +46 -0
- data/lib/overcommit/utils.rb +163 -0
- data/lib/overcommit/version.rb +4 -0
- data/libexec/gerrit-change-id +174 -0
- data/libexec/index-tags +17 -0
- data/template-dir/hooks/commit-msg +81 -0
- data/template-dir/hooks/overcommit-hook +81 -0
- data/template-dir/hooks/post-checkout +81 -0
- data/template-dir/hooks/pre-commit +81 -0
- metadata +184 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module Overcommit::HookLoader
|
2
|
+
# Responsible for loading hooks from a file.
|
3
|
+
class Base
|
4
|
+
# @param config [Overcommit::Configuration]
|
5
|
+
# @param context [Overcommit::HookContext]
|
6
|
+
# @param logger [Overcommit::Logger]
|
7
|
+
def initialize(config, context, logger)
|
8
|
+
@config = config
|
9
|
+
@context = context
|
10
|
+
@log = logger
|
11
|
+
end
|
12
|
+
|
13
|
+
# When implemented in subclasses, loads the hooks for which that subclass is
|
14
|
+
# responsible.
|
15
|
+
#
|
16
|
+
# @return [Array<Hook>]
|
17
|
+
def load_hooks
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :log
|
24
|
+
|
25
|
+
# Load and return a {Hook} from a CamelCase hook name.
|
26
|
+
def create_hook(hook_name)
|
27
|
+
Overcommit::Hook.const_get(@context.hook_class_name).
|
28
|
+
const_get(hook_name).
|
29
|
+
new(@config, @context)
|
30
|
+
rescue LoadError, NameError => error
|
31
|
+
raise Overcommit::Exceptions::HookLoadError,
|
32
|
+
"Unable to load hook '#{hook_name}': #{error}",
|
33
|
+
error.backtrace
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Overcommit::HookLoader
|
2
|
+
# Responsible for loading hooks that ship with Overcommit.
|
3
|
+
class BuiltInHookLoader < Base
|
4
|
+
def load_hooks
|
5
|
+
@config.enabled_builtin_hooks(@context).map do |hook_name|
|
6
|
+
underscored_hook_name = Overcommit::Utils.snake_case(hook_name)
|
7
|
+
require "overcommit/hook/#{@context.hook_type_name}/#{underscored_hook_name}"
|
8
|
+
create_hook(hook_name)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Overcommit::HookLoader
|
4
|
+
# Responsible for loading hooks that are specific to the repository Overcommit
|
5
|
+
# is running in.
|
6
|
+
class PluginHookLoader < Base
|
7
|
+
def load_hooks
|
8
|
+
check_for_modified_plugins if @config.verify_plugin_signatures?
|
9
|
+
|
10
|
+
plugin_paths.map do |plugin_path|
|
11
|
+
require plugin_path
|
12
|
+
|
13
|
+
hook_name = Overcommit::Utils.camel_case(File.basename(plugin_path, '.rb'))
|
14
|
+
create_hook(hook_name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_signatures
|
19
|
+
log.success('No plugin signatures have changed') if modified_plugins.empty?
|
20
|
+
|
21
|
+
modified_plugins.each do |plugin|
|
22
|
+
plugin.update_signature!
|
23
|
+
log.warning "Updated signature of plugin #{plugin.hook_name}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def plugin_paths
|
30
|
+
directory = File.join(@config.plugin_directory, @context.hook_type_name)
|
31
|
+
Dir[File.join(directory, '*.rb')].sort
|
32
|
+
end
|
33
|
+
|
34
|
+
def modified_plugins
|
35
|
+
plugin_paths.
|
36
|
+
map { |path| Overcommit::HookSigner.new(path, @config, @context) }.
|
37
|
+
select(&:signature_changed?)
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_for_modified_plugins
|
41
|
+
return if modified_plugins.empty?
|
42
|
+
|
43
|
+
log.bold_warning "The following #{@context.hook_script_name} plugins " \
|
44
|
+
'have been added, changed, or had their configuration modified:'
|
45
|
+
log.newline
|
46
|
+
|
47
|
+
modified_plugins.each do |signer|
|
48
|
+
log.warning " * #{signer.hook_name} in #{signer.hook_path}"
|
49
|
+
end
|
50
|
+
|
51
|
+
log.newline
|
52
|
+
log.bold_warning 'You should verify the changes and then run:'
|
53
|
+
log.newline
|
54
|
+
log.warning "overcommit --sign #{@context.hook_script_name}"
|
55
|
+
log.newline
|
56
|
+
log.log "For more information, see #{Overcommit::REPO_URL}#security"
|
57
|
+
|
58
|
+
raise Overcommit::Exceptions::InvalidHookSignature
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Overcommit
|
2
|
+
# Responsible for loading the hooks the repository has configured and running
|
3
|
+
# them, collecting and displaying the results.
|
4
|
+
class HookRunner
|
5
|
+
# @param config [Overcommit::Configuration]
|
6
|
+
# @param logger [Overcommit::Logger]
|
7
|
+
# @param context [Overcommit::HookContext]
|
8
|
+
# @param printer [Overcommit::Printer]
|
9
|
+
def initialize(config, logger, context, printer)
|
10
|
+
@config = config
|
11
|
+
@log = logger
|
12
|
+
@context = context
|
13
|
+
@printer = printer
|
14
|
+
@hooks = []
|
15
|
+
end
|
16
|
+
|
17
|
+
# Loads and runs the hooks registered for this {HookRunner}.
|
18
|
+
def run
|
19
|
+
# ASSUMPTION: we assume the setup and cleanup calls will never need to be
|
20
|
+
# interrupted, i.e. they will finish quickly. Should further evidence
|
21
|
+
# suggest this assumption does not hold, we will have to separately wrap
|
22
|
+
# these calls to allow some sort of "are you sure?" double-interrupt
|
23
|
+
# functionality, but until that's deemed necessary let's keep it simple.
|
24
|
+
InterruptHandler.isolate_from_interrupts do
|
25
|
+
@context.setup_environment
|
26
|
+
load_hooks
|
27
|
+
result = run_hooks
|
28
|
+
@context.cleanup_environment
|
29
|
+
result
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :log
|
36
|
+
|
37
|
+
def run_hooks
|
38
|
+
if @hooks.any?(&:enabled?)
|
39
|
+
@printer.start_run
|
40
|
+
|
41
|
+
interrupted = false
|
42
|
+
run_failed = false
|
43
|
+
|
44
|
+
@hooks.each do |hook|
|
45
|
+
hook_status = run_hook(hook)
|
46
|
+
|
47
|
+
run_failed = true if [:bad, :fail].include?(hook_status)
|
48
|
+
|
49
|
+
if hook_status == :interrupt
|
50
|
+
# Stop running any more hooks and assume a bad result
|
51
|
+
interrupted = true
|
52
|
+
break
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
print_results(run_failed, interrupted)
|
57
|
+
|
58
|
+
!(run_failed || interrupted)
|
59
|
+
else
|
60
|
+
@printer.nothing_to_run
|
61
|
+
true # Run was successful
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def print_results(failed, interrupted)
|
66
|
+
if interrupted
|
67
|
+
@printer.run_interrupted
|
68
|
+
elsif failed
|
69
|
+
@printer.run_failed
|
70
|
+
else
|
71
|
+
@printer.run_succeeded
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_hook(hook)
|
76
|
+
return if should_skip?(hook)
|
77
|
+
|
78
|
+
@printer.start_hook(hook)
|
79
|
+
|
80
|
+
status, output = nil, nil
|
81
|
+
|
82
|
+
begin
|
83
|
+
# Disable the interrupt handler during individual hook run so that
|
84
|
+
# Ctrl-C actually stops the current hook from being run, but doesn't
|
85
|
+
# halt the entire process.
|
86
|
+
InterruptHandler.disable_until_finished_or_interrupted do
|
87
|
+
status, output = hook.run_and_transform
|
88
|
+
end
|
89
|
+
rescue => ex
|
90
|
+
status = :fail
|
91
|
+
output = "Hook raised unexpected error\n#{ex.message}\n#{ex.backtrace.join("\n")}"
|
92
|
+
rescue Interrupt
|
93
|
+
# At this point, interrupt has been handled and protection is back in
|
94
|
+
# effect thanks to the InterruptHandler.
|
95
|
+
status = :interrupt
|
96
|
+
output = 'Hook was interrupted by Ctrl-C; restoring repo state...'
|
97
|
+
end
|
98
|
+
|
99
|
+
@printer.end_hook(hook, status, output)
|
100
|
+
|
101
|
+
status
|
102
|
+
end
|
103
|
+
|
104
|
+
def should_skip?(hook)
|
105
|
+
return true unless hook.enabled?
|
106
|
+
|
107
|
+
if hook.skip?
|
108
|
+
if hook.required?
|
109
|
+
@printer.required_hook_not_skipped(hook)
|
110
|
+
else
|
111
|
+
# Tell user if hook was skipped only if it actually would have run
|
112
|
+
@printer.hook_skipped(hook) if hook.run?
|
113
|
+
return true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
!hook.run?
|
118
|
+
end
|
119
|
+
|
120
|
+
def load_hooks
|
121
|
+
require "overcommit/hook/#{@context.hook_type_name}/base"
|
122
|
+
|
123
|
+
@hooks += HookLoader::BuiltInHookLoader.new(@config, @context, @log).load_hooks
|
124
|
+
|
125
|
+
# Load plugin hooks after so they can subclass existing hooks
|
126
|
+
@hooks += HookLoader::PluginHookLoader.new(@config, @context, @log).load_hooks
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Overcommit
|
2
|
+
# Calculates, stores, and retrieves stored signatures of hook plugins.
|
3
|
+
class HookSigner
|
4
|
+
attr_reader :hook_path, :hook_name
|
5
|
+
|
6
|
+
# We don't want to include the skip setting as it is set by Overcommit
|
7
|
+
# itself
|
8
|
+
IGNORED_CONFIG_KEYS = %w[skip]
|
9
|
+
|
10
|
+
# @param hook_path [String] path to the actual hook definition
|
11
|
+
# @param config [Overcommit::Configuration]
|
12
|
+
# @param context [Overcommit::HookContext]
|
13
|
+
def initialize(hook_path, config, context)
|
14
|
+
@hook_path = hook_path
|
15
|
+
@config = config
|
16
|
+
@context = context
|
17
|
+
|
18
|
+
@hook_name = Overcommit::Utils.camel_case(File.basename(@hook_path, '.rb'))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return whether the signature for this hook has changed since it was last
|
22
|
+
# calculated.
|
23
|
+
#
|
24
|
+
# @return [true,false]
|
25
|
+
def signature_changed?
|
26
|
+
signature != stored_signature
|
27
|
+
end
|
28
|
+
|
29
|
+
# Update the current stored signature for this hook.
|
30
|
+
def update_signature!
|
31
|
+
result = Overcommit::Utils.execute(
|
32
|
+
%w[git config --local] + [signature_config_key, signature]
|
33
|
+
)
|
34
|
+
|
35
|
+
unless result.success?
|
36
|
+
raise Overcommit::Exceptions::GitConfigError,
|
37
|
+
"Unable to write to local repo git config: #{result.stderr}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Calculates a hash of a hook using a combination of its configuration and
|
44
|
+
# file contents.
|
45
|
+
#
|
46
|
+
# This way, if either the plugin code changes or its configuration changes,
|
47
|
+
# the hash will change and we can alert the user to this change.
|
48
|
+
def signature
|
49
|
+
hook_config = @config.for_hook(@hook_name, @context.hook_class_name).
|
50
|
+
dup.
|
51
|
+
tap { |config| IGNORED_CONFIG_KEYS.each { |k| config.delete(k) } }
|
52
|
+
|
53
|
+
Digest::SHA256.hexdigest(hook_contents + hook_config.to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
def hook_contents
|
57
|
+
File.open(@hook_path, 'r').read
|
58
|
+
end
|
59
|
+
|
60
|
+
def stored_signature
|
61
|
+
result = Overcommit::Utils.execute(
|
62
|
+
%w[git config --local --get] + [signature_config_key]
|
63
|
+
)
|
64
|
+
|
65
|
+
if result.status == 1 # Key doesn't exist
|
66
|
+
return ''
|
67
|
+
elsif result.status != 0
|
68
|
+
raise Overcommit::Exceptions::GitConfigError,
|
69
|
+
"Unable to read from local repo git config: #{result.stderr}"
|
70
|
+
end
|
71
|
+
|
72
|
+
result.stdout.chomp
|
73
|
+
end
|
74
|
+
|
75
|
+
def signature_config_key
|
76
|
+
"overcommit.#{@context.hook_class_name}.#{@hook_name}.signature"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Overcommit
|
4
|
+
# Manages the installation of Overcommit hooks in a git repository.
|
5
|
+
class Installer # rubocop:disable ClassLength
|
6
|
+
TEMPLATE_DIRECTORY = File.join(OVERCOMMIT_HOME, 'template-dir')
|
7
|
+
MASTER_HOOK = File.join(TEMPLATE_DIRECTORY, 'hooks', 'overcommit-hook')
|
8
|
+
|
9
|
+
def initialize(logger)
|
10
|
+
@log = logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target, options)
|
14
|
+
@target = target
|
15
|
+
@options = options
|
16
|
+
validate_target
|
17
|
+
|
18
|
+
case @options[:action]
|
19
|
+
when :uninstall then uninstall
|
20
|
+
when :update then update
|
21
|
+
else
|
22
|
+
install
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :log
|
29
|
+
|
30
|
+
def install
|
31
|
+
log.log "Installing hooks into #{@target}"
|
32
|
+
|
33
|
+
ensure_hooks_directory
|
34
|
+
install_master_hook
|
35
|
+
install_hook_symlinks
|
36
|
+
install_starter_config
|
37
|
+
|
38
|
+
log.success "Successfully installed hooks into #{@target}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def uninstall
|
42
|
+
log.log "Removing hooks from #{@target}"
|
43
|
+
|
44
|
+
uninstall_master_hook
|
45
|
+
uninstall_hook_symlinks
|
46
|
+
|
47
|
+
log.success "Successfully removed hooks from #{@target}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [true,false] whether the hooks were updated
|
51
|
+
def update
|
52
|
+
unless FileUtils.compare_file(MASTER_HOOK, master_hook_install_path)
|
53
|
+
install_master_hook
|
54
|
+
install_hook_symlinks
|
55
|
+
|
56
|
+
log.success "Hooks updated to Overcommit version #{Overcommit::VERSION}"
|
57
|
+
true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def hooks_path
|
62
|
+
absolute_target = File.expand_path(@target)
|
63
|
+
File.join(Overcommit::Utils.git_dir(absolute_target), 'hooks')
|
64
|
+
end
|
65
|
+
|
66
|
+
def master_hook_install_path
|
67
|
+
File.join(hooks_path, 'overcommit-hook')
|
68
|
+
end
|
69
|
+
|
70
|
+
def ensure_hooks_directory
|
71
|
+
FileUtils.mkdir_p(hooks_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_target
|
75
|
+
absolute_target = File.expand_path(@target)
|
76
|
+
|
77
|
+
unless File.directory?(absolute_target)
|
78
|
+
raise Overcommit::Exceptions::InvalidGitRepo, 'is not a directory'
|
79
|
+
end
|
80
|
+
|
81
|
+
git_dir_check = Dir.chdir(absolute_target) do
|
82
|
+
Overcommit::Utils.execute(%w[git rev-parse --git-dir])
|
83
|
+
end
|
84
|
+
|
85
|
+
unless git_dir_check.success?
|
86
|
+
raise Overcommit::Exceptions::InvalidGitRepo, 'does not appear to be a git repository'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def install_master_hook
|
91
|
+
FileUtils.mkdir_p(hooks_path)
|
92
|
+
FileUtils.cp(MASTER_HOOK, master_hook_install_path)
|
93
|
+
end
|
94
|
+
|
95
|
+
def uninstall_master_hook
|
96
|
+
FileUtils.rm_rf(master_hook_install_path)
|
97
|
+
end
|
98
|
+
|
99
|
+
def install_hook_symlinks
|
100
|
+
# Link each hook type (pre-commit, commit-msg, etc.) to the master hook.
|
101
|
+
# We change directories so that the relative symlink paths work regardless
|
102
|
+
# of where the repository is located.
|
103
|
+
Dir.chdir(hooks_path) do
|
104
|
+
Overcommit::Utils.supported_hook_types.each do |hook_type|
|
105
|
+
unless can_replace_file?(hook_type)
|
106
|
+
raise Overcommit::Exceptions::PreExistingHooks,
|
107
|
+
"Hook '#{File.expand_path(hook_type)}' already exists and " \
|
108
|
+
'was not installed by Overcommit'
|
109
|
+
end
|
110
|
+
FileUtils.ln_sf('overcommit-hook', hook_type)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def can_replace_file?(file)
|
116
|
+
@options[:force] ||
|
117
|
+
!File.exist?(file) ||
|
118
|
+
overcommit_hook?(file)
|
119
|
+
end
|
120
|
+
|
121
|
+
def uninstall_hook_symlinks
|
122
|
+
return unless File.directory?(hooks_path)
|
123
|
+
|
124
|
+
Dir.chdir(hooks_path) do
|
125
|
+
Overcommit::Utils.supported_hook_types.each do |hook_type|
|
126
|
+
FileUtils.rm_rf(hook_type) if overcommit_hook?(hook_type)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def install_starter_config
|
132
|
+
repo_config_file = File.join(@target, OVERCOMMIT_CONFIG_FILE_NAME)
|
133
|
+
|
134
|
+
return if File.exist?(repo_config_file)
|
135
|
+
FileUtils.cp(File.join(OVERCOMMIT_HOME, 'config', 'starter.yml'), repo_config_file)
|
136
|
+
end
|
137
|
+
|
138
|
+
def overcommit_hook?(file)
|
139
|
+
return true if File.read(file) =~ /OVERCOMMIT_DISABLE/
|
140
|
+
# TODO: Remove these checks once we hit version 1.0
|
141
|
+
File.symlink?(file) && File.readlink(file) == 'overcommit-hook'
|
142
|
+
rescue Errno::ENOENT
|
143
|
+
# Some Ruby implementations (e.g. JRuby) raise an error when the file
|
144
|
+
# doesn't exist. Standardize the behavior to return false.
|
145
|
+
false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|