overcommit-jeygeethanmedia 0.53.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/overcommit +50 -0
- data/config/default.yml +1356 -0
- data/config/starter.yml +33 -0
- data/lib/overcommit.rb +26 -0
- data/lib/overcommit/cli.rb +223 -0
- data/lib/overcommit/command_splitter.rb +146 -0
- data/lib/overcommit/configuration.rb +350 -0
- data/lib/overcommit/configuration_loader.rb +96 -0
- data/lib/overcommit/configuration_validator.rb +186 -0
- data/lib/overcommit/constants.rb +12 -0
- data/lib/overcommit/exceptions.rb +52 -0
- data/lib/overcommit/git_config.rb +22 -0
- data/lib/overcommit/git_repo.rb +286 -0
- data/lib/overcommit/git_version.rb +17 -0
- data/lib/overcommit/hook/base.rb +294 -0
- data/lib/overcommit/hook/commit_msg/base.rb +14 -0
- data/lib/overcommit/hook/commit_msg/capitalized_subject.rb +25 -0
- data/lib/overcommit/hook/commit_msg/empty_message.rb +12 -0
- data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +22 -0
- data/lib/overcommit/hook/commit_msg/hard_tabs.rb +17 -0
- data/lib/overcommit/hook/commit_msg/message_format.rb +31 -0
- data/lib/overcommit/hook/commit_msg/russian_novel.rb +16 -0
- data/lib/overcommit/hook/commit_msg/single_line_subject.rb +16 -0
- data/lib/overcommit/hook/commit_msg/spell_check.rb +45 -0
- data/lib/overcommit/hook/commit_msg/text_width.rb +56 -0
- data/lib/overcommit/hook/commit_msg/trailing_period.rb +16 -0
- data/lib/overcommit/hook/post_checkout/base.rb +22 -0
- data/lib/overcommit/hook/post_checkout/bower_install.rb +13 -0
- data/lib/overcommit/hook/post_checkout/bundle_install.rb +13 -0
- data/lib/overcommit/hook/post_checkout/composer_install.rb +13 -0
- data/lib/overcommit/hook/post_checkout/index_tags.rb +12 -0
- data/lib/overcommit/hook/post_checkout/npm_install.rb +13 -0
- data/lib/overcommit/hook/post_checkout/submodule_status.rb +12 -0
- data/lib/overcommit/hook/post_checkout/yarn_install.rb +13 -0
- data/lib/overcommit/hook/post_commit/base.rb +12 -0
- data/lib/overcommit/hook/post_commit/bower_install.rb +13 -0
- data/lib/overcommit/hook/post_commit/bundle_install.rb +13 -0
- data/lib/overcommit/hook/post_commit/commitplease.rb +16 -0
- data/lib/overcommit/hook/post_commit/composer_install.rb +13 -0
- data/lib/overcommit/hook/post_commit/git_guilt.rb +43 -0
- data/lib/overcommit/hook/post_commit/index_tags.rb +12 -0
- data/lib/overcommit/hook/post_commit/npm_install.rb +13 -0
- data/lib/overcommit/hook/post_commit/submodule_status.rb +12 -0
- data/lib/overcommit/hook/post_commit/yarn_install.rb +13 -0
- data/lib/overcommit/hook/post_merge/base.rb +12 -0
- data/lib/overcommit/hook/post_merge/bower_install.rb +13 -0
- data/lib/overcommit/hook/post_merge/bundle_install.rb +13 -0
- data/lib/overcommit/hook/post_merge/composer_install.rb +13 -0
- data/lib/overcommit/hook/post_merge/index_tags.rb +12 -0
- data/lib/overcommit/hook/post_merge/npm_install.rb +13 -0
- data/lib/overcommit/hook/post_merge/submodule_status.rb +12 -0
- data/lib/overcommit/hook/post_merge/yarn_install.rb +13 -0
- data/lib/overcommit/hook/post_rewrite/base.rb +12 -0
- data/lib/overcommit/hook/post_rewrite/bower_install.rb +13 -0
- data/lib/overcommit/hook/post_rewrite/bundle_install.rb +13 -0
- data/lib/overcommit/hook/post_rewrite/composer_install.rb +13 -0
- data/lib/overcommit/hook/post_rewrite/index_tags.rb +19 -0
- data/lib/overcommit/hook/post_rewrite/npm_install.rb +13 -0
- data/lib/overcommit/hook/post_rewrite/submodule_status.rb +12 -0
- data/lib/overcommit/hook/post_rewrite/yarn_install.rb +13 -0
- data/lib/overcommit/hook/pre_commit/author_email.rb +26 -0
- data/lib/overcommit/hook/pre_commit/author_name.rb +25 -0
- data/lib/overcommit/hook/pre_commit/base.rb +19 -0
- data/lib/overcommit/hook/pre_commit/berksfile_check.rb +24 -0
- data/lib/overcommit/hook/pre_commit/broken_symlinks.rb +17 -0
- data/lib/overcommit/hook/pre_commit/bundle_audit.rb +24 -0
- data/lib/overcommit/hook/pre_commit/bundle_check.rb +32 -0
- data/lib/overcommit/hook/pre_commit/bundle_outdated.rb +25 -0
- data/lib/overcommit/hook/pre_commit/case_conflicts.rb +27 -0
- data/lib/overcommit/hook/pre_commit/chamber_compare.rb +43 -0
- data/lib/overcommit/hook/pre_commit/chamber_security.rb +15 -0
- data/lib/overcommit/hook/pre_commit/chamber_verification.rb +36 -0
- data/lib/overcommit/hook/pre_commit/code_spell_check.rb +36 -0
- data/lib/overcommit/hook/pre_commit/coffee_lint.rb +35 -0
- data/lib/overcommit/hook/pre_commit/cook_style.rb +35 -0
- data/lib/overcommit/hook/pre_commit/credo.rb +27 -0
- data/lib/overcommit/hook/pre_commit/css_lint.rb +26 -0
- data/lib/overcommit/hook/pre_commit/dogma.rb +33 -0
- data/lib/overcommit/hook/pre_commit/es_lint.rb +38 -0
- data/lib/overcommit/hook/pre_commit/execute_permissions.rb +76 -0
- data/lib/overcommit/hook/pre_commit/fasterer.rb +25 -0
- data/lib/overcommit/hook/pre_commit/file_size.rb +47 -0
- data/lib/overcommit/hook/pre_commit/fix_me.rb +17 -0
- data/lib/overcommit/hook/pre_commit/flay.rb +38 -0
- data/lib/overcommit/hook/pre_commit/foodcritic.rb +149 -0
- data/lib/overcommit/hook/pre_commit/forbidden_branches.rb +26 -0
- data/lib/overcommit/hook/pre_commit/ginkgo_focus.rb +23 -0
- data/lib/overcommit/hook/pre_commit/go_fmt.rb +17 -0
- data/lib/overcommit/hook/pre_commit/go_lint.rb +29 -0
- data/lib/overcommit/hook/pre_commit/go_vet.rb +24 -0
- data/lib/overcommit/hook/pre_commit/golangci_lint.rb +21 -0
- data/lib/overcommit/hook/pre_commit/hadolint.rb +27 -0
- data/lib/overcommit/hook/pre_commit/haml_lint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/hard_tabs.rb +15 -0
- data/lib/overcommit/hook/pre_commit/hlint.rb +34 -0
- data/lib/overcommit/hook/pre_commit/html_hint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/html_tidy.rb +30 -0
- data/lib/overcommit/hook/pre_commit/image_optim.rb +28 -0
- data/lib/overcommit/hook/pre_commit/java_checkstyle.rb +27 -0
- data/lib/overcommit/hook/pre_commit/js_hint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/js_lint.rb +22 -0
- data/lib/overcommit/hook/pre_commit/jscs.rb +27 -0
- data/lib/overcommit/hook/pre_commit/jsl.rb +28 -0
- data/lib/overcommit/hook/pre_commit/json_syntax.rb +21 -0
- data/lib/overcommit/hook/pre_commit/kt_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/license_finder.rb +14 -0
- data/lib/overcommit/hook/pre_commit/license_header.rb +48 -0
- data/lib/overcommit/hook/pre_commit/line_endings.rb +77 -0
- data/lib/overcommit/hook/pre_commit/local_paths_in_gemfile.rb +16 -0
- data/lib/overcommit/hook/pre_commit/mdl.rb +29 -0
- data/lib/overcommit/hook/pre_commit/merge_conflicts.rb +16 -0
- data/lib/overcommit/hook/pre_commit/nginx_test.rb +26 -0
- data/lib/overcommit/hook/pre_commit/pep257.rb +23 -0
- data/lib/overcommit/hook/pre_commit/pep8.rb +23 -0
- data/lib/overcommit/hook/pre_commit/php_cs.rb +43 -0
- data/lib/overcommit/hook/pre_commit/php_cs_fixer.rb +57 -0
- data/lib/overcommit/hook/pre_commit/php_lint.rb +44 -0
- data/lib/overcommit/hook/pre_commit/php_stan.rb +30 -0
- data/lib/overcommit/hook/pre_commit/pronto.rb +12 -0
- data/lib/overcommit/hook/pre_commit/puppet_lint.rb +26 -0
- data/lib/overcommit/hook/pre_commit/puppet_metadata_json_lint.rb +29 -0
- data/lib/overcommit/hook/pre_commit/pycodestyle.rb +23 -0
- data/lib/overcommit/hook/pre_commit/pydocstyle.rb +23 -0
- data/lib/overcommit/hook/pre_commit/pyflakes.rb +32 -0
- data/lib/overcommit/hook/pre_commit/pylint.rb +32 -0
- data/lib/overcommit/hook/pre_commit/python_flake8.rb +32 -0
- data/lib/overcommit/hook/pre_commit/rails_best_practices.rb +34 -0
- data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +58 -0
- data/lib/overcommit/hook/pre_commit/rake_target.rb +12 -0
- data/lib/overcommit/hook/pre_commit/reek.rb +26 -0
- data/lib/overcommit/hook/pre_commit/rst_lint.rb +27 -0
- data/lib/overcommit/hook/pre_commit/rubo_cop.rb +35 -0
- data/lib/overcommit/hook/pre_commit/ruby_lint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/ruby_syntax.rb +27 -0
- data/lib/overcommit/hook/pre_commit/scalariform.rb +22 -0
- data/lib/overcommit/hook/pre_commit/scalastyle.rb +31 -0
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +43 -0
- data/lib/overcommit/hook/pre_commit/semi_standard.rb +23 -0
- data/lib/overcommit/hook/pre_commit/shell_check.rb +23 -0
- data/lib/overcommit/hook/pre_commit/slim_lint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/sqlint.rb +26 -0
- data/lib/overcommit/hook/pre_commit/standard.rb +23 -0
- data/lib/overcommit/hook/pre_commit/stylelint.rb +23 -0
- data/lib/overcommit/hook/pre_commit/swift_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/terraform_format.rb +19 -0
- data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +15 -0
- data/lib/overcommit/hook/pre_commit/travis_lint.rb +15 -0
- data/lib/overcommit/hook/pre_commit/ts_lint.rb +28 -0
- data/lib/overcommit/hook/pre_commit/vint.rb +22 -0
- data/lib/overcommit/hook/pre_commit/w3c_css.rb +67 -0
- data/lib/overcommit/hook/pre_commit/w3c_html.rb +64 -0
- data/lib/overcommit/hook/pre_commit/xml_lint.rb +24 -0
- data/lib/overcommit/hook/pre_commit/xml_syntax.rb +21 -0
- data/lib/overcommit/hook/pre_commit/yaml_lint.rb +18 -0
- data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +20 -0
- data/lib/overcommit/hook/pre_commit/yard_coverage.rb +90 -0
- data/lib/overcommit/hook/pre_commit/yarn_check.rb +37 -0
- data/lib/overcommit/hook/pre_push/base.rb +33 -0
- data/lib/overcommit/hook/pre_push/brakeman.rb +15 -0
- data/lib/overcommit/hook/pre_push/cargo_test.rb +12 -0
- data/lib/overcommit/hook/pre_push/go_test.rb +14 -0
- data/lib/overcommit/hook/pre_push/golangci_lint.rb +16 -0
- data/lib/overcommit/hook/pre_push/minitest.rb +20 -0
- data/lib/overcommit/hook/pre_push/php_unit.rb +16 -0
- data/lib/overcommit/hook/pre_push/pronto.rb +12 -0
- data/lib/overcommit/hook/pre_push/protected_branches.rb +74 -0
- data/lib/overcommit/hook/pre_push/pytest.rb +16 -0
- data/lib/overcommit/hook/pre_push/python_nose.rb +16 -0
- data/lib/overcommit/hook/pre_push/r_spec.rb +16 -0
- data/lib/overcommit/hook/pre_push/rake_target.rb +12 -0
- data/lib/overcommit/hook/pre_push/test_unit.rb +16 -0
- data/lib/overcommit/hook/pre_rebase/base.rb +14 -0
- data/lib/overcommit/hook/pre_rebase/merged_commits.rb +31 -0
- data/lib/overcommit/hook/prepare_commit_msg/base.rb +25 -0
- data/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb +57 -0
- data/lib/overcommit/hook/shared/bower_install.rb +15 -0
- data/lib/overcommit/hook/shared/bundle_install.rb +15 -0
- data/lib/overcommit/hook/shared/composer_install.rb +15 -0
- data/lib/overcommit/hook/shared/index_tags.rb +14 -0
- data/lib/overcommit/hook/shared/npm_install.rb +15 -0
- data/lib/overcommit/hook/shared/pronto.rb +21 -0
- data/lib/overcommit/hook/shared/rake_target.rb +26 -0
- data/lib/overcommit/hook/shared/submodule_status.rb +32 -0
- data/lib/overcommit/hook/shared/yarn_install.rb +15 -0
- data/lib/overcommit/hook_context.rb +19 -0
- data/lib/overcommit/hook_context/base.rb +139 -0
- data/lib/overcommit/hook_context/commit_msg.rb +48 -0
- data/lib/overcommit/hook_context/post_checkout.rb +36 -0
- data/lib/overcommit/hook_context/post_commit.rb +33 -0
- data/lib/overcommit/hook_context/post_merge.rb +37 -0
- data/lib/overcommit/hook_context/post_rewrite.rb +49 -0
- data/lib/overcommit/hook_context/pre_commit.rb +212 -0
- data/lib/overcommit/hook_context/pre_push.rb +89 -0
- data/lib/overcommit/hook_context/pre_rebase.rb +38 -0
- data/lib/overcommit/hook_context/prepare_commit_msg.rb +34 -0
- data/lib/overcommit/hook_context/run_all.rb +48 -0
- data/lib/overcommit/hook_loader/base.rb +48 -0
- data/lib/overcommit/hook_loader/built_in_hook_loader.rb +14 -0
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +102 -0
- data/lib/overcommit/hook_runner.rb +219 -0
- data/lib/overcommit/hook_signer.rb +123 -0
- data/lib/overcommit/installer.rb +193 -0
- data/lib/overcommit/interrupt_handler.rb +91 -0
- data/lib/overcommit/logger.rb +92 -0
- data/lib/overcommit/message_processor.rb +148 -0
- data/lib/overcommit/os.rb +38 -0
- data/lib/overcommit/printer.rb +145 -0
- data/lib/overcommit/subprocess.rb +98 -0
- data/lib/overcommit/utils.rb +309 -0
- data/lib/overcommit/utils/file_utils.rb +71 -0
- data/lib/overcommit/utils/messages_utils.rb +77 -0
- data/lib/overcommit/version.rb +6 -0
- data/libexec/gerrit-change-id +174 -0
- data/libexec/index-tags +17 -0
- data/template-dir/hooks/commit-msg +116 -0
- data/template-dir/hooks/overcommit-hook +116 -0
- data/template-dir/hooks/post-checkout +116 -0
- data/template-dir/hooks/post-commit +116 -0
- data/template-dir/hooks/post-merge +116 -0
- data/template-dir/hooks/post-rewrite +116 -0
- data/template-dir/hooks/pre-commit +116 -0
- data/template-dir/hooks/pre-push +116 -0
- data/template-dir/hooks/pre-rebase +116 -0
- data/template-dir/hooks/prepare-commit-msg +116 -0
- metadata +303 -0
data/config/starter.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Use this file to configure the Overcommit hooks you wish to use. This will
|
2
|
+
# extend the default configuration defined in:
|
3
|
+
# https://github.com/sds/overcommit/blob/master/config/default.yml
|
4
|
+
#
|
5
|
+
# At the topmost level of this YAML file is a key representing type of hook
|
6
|
+
# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
|
7
|
+
# customize each hook, such as whether to only run it on certain files (via
|
8
|
+
# `include`), whether to only display output if it fails (via `quiet`), etc.
|
9
|
+
#
|
10
|
+
# For a complete list of hooks, see:
|
11
|
+
# https://github.com/sds/overcommit/tree/master/lib/overcommit/hook
|
12
|
+
#
|
13
|
+
# For a complete list of options that you can use to customize hooks, see:
|
14
|
+
# https://github.com/sds/overcommit#configuration
|
15
|
+
#
|
16
|
+
# Uncomment the following lines to make the configuration take effect.
|
17
|
+
|
18
|
+
#PreCommit:
|
19
|
+
# RuboCop:
|
20
|
+
# enabled: true
|
21
|
+
# on_warn: fail # Treat all warnings as failures
|
22
|
+
#
|
23
|
+
# TrailingWhitespace:
|
24
|
+
# enabled: true
|
25
|
+
# exclude:
|
26
|
+
# - '**/db/structure.sql' # Ignore trailing whitespace in generated files
|
27
|
+
#
|
28
|
+
#PostCheckout:
|
29
|
+
# ALL: # Special hook name that customizes all hooks of this type
|
30
|
+
# quiet: true # Change all post-checkout hooks to only display output on failure
|
31
|
+
#
|
32
|
+
# IndexTags:
|
33
|
+
# enabled: true # Generate a tags file with `ctags` each time HEAD changes
|
data/lib/overcommit.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'overcommit/os'
|
4
|
+
require 'overcommit/constants'
|
5
|
+
require 'overcommit/exceptions'
|
6
|
+
require 'overcommit/utils/file_utils'
|
7
|
+
require 'overcommit/utils'
|
8
|
+
require 'overcommit/git_version'
|
9
|
+
require 'overcommit/configuration_validator'
|
10
|
+
require 'overcommit/configuration'
|
11
|
+
require 'overcommit/configuration_loader'
|
12
|
+
require 'overcommit/hook/base'
|
13
|
+
require 'overcommit/hook_context/base'
|
14
|
+
require 'overcommit/hook_context'
|
15
|
+
require 'overcommit/git_config'
|
16
|
+
require 'overcommit/git_repo'
|
17
|
+
require 'overcommit/hook_signer'
|
18
|
+
require 'overcommit/hook_loader/base'
|
19
|
+
require 'overcommit/hook_loader/built_in_hook_loader'
|
20
|
+
require 'overcommit/hook_loader/plugin_hook_loader'
|
21
|
+
require 'overcommit/interrupt_handler'
|
22
|
+
require 'overcommit/printer'
|
23
|
+
require 'overcommit/hook_runner'
|
24
|
+
require 'overcommit/installer'
|
25
|
+
require 'overcommit/logger'
|
26
|
+
require 'overcommit/version'
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'overcommit'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
module Overcommit
|
7
|
+
# Responsible for parsing command-line options and executing appropriate
|
8
|
+
# application logic based on those options.
|
9
|
+
class CLI # rubocop:disable ClassLength
|
10
|
+
def initialize(arguments, input, logger)
|
11
|
+
@arguments = arguments
|
12
|
+
@input = input
|
13
|
+
@log = logger
|
14
|
+
@options = {}
|
15
|
+
|
16
|
+
Overcommit::Utils.log = logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
parse_arguments
|
21
|
+
|
22
|
+
case @options[:action]
|
23
|
+
when :install, :uninstall
|
24
|
+
install_or_uninstall
|
25
|
+
when :template_dir
|
26
|
+
print_template_directory_path
|
27
|
+
when :sign
|
28
|
+
sign
|
29
|
+
when :run_all
|
30
|
+
run_all
|
31
|
+
end
|
32
|
+
rescue Overcommit::Exceptions::ConfigurationSignatureChanged => ex
|
33
|
+
puts ex
|
34
|
+
exit 78 # EX_CONFIG
|
35
|
+
rescue Overcommit::Exceptions::HookContextLoadError => ex
|
36
|
+
puts ex
|
37
|
+
exit 64 # EX_USAGE
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :log
|
43
|
+
|
44
|
+
def parse_arguments
|
45
|
+
@parser = create_option_parser
|
46
|
+
|
47
|
+
begin
|
48
|
+
@parser.parse!(@arguments)
|
49
|
+
|
50
|
+
# Default action is to install
|
51
|
+
@options[:action] ||= :install
|
52
|
+
|
53
|
+
# Unconsumed arguments are our targets
|
54
|
+
@options[:targets] = @arguments
|
55
|
+
rescue OptionParser::InvalidOption => ex
|
56
|
+
print_help @parser.help, ex
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_option_parser
|
61
|
+
OptionParser.new do |opts|
|
62
|
+
opts.banner = "Usage: #{opts.program_name} [options] [target-repo]"
|
63
|
+
|
64
|
+
add_information_options(opts)
|
65
|
+
add_installation_options(opts)
|
66
|
+
add_other_options(opts)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_information_options(opts)
|
71
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
72
|
+
print_help opts.help
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on_tail('-v', '--version', 'Show version') do
|
76
|
+
print_version(opts.program_name)
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on_tail('-l', '--list-hooks', 'List installed hooks') do
|
80
|
+
print_installed_hooks
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_installation_options(opts)
|
85
|
+
opts.on('-u', '--uninstall', 'Remove Overcommit hooks from a repository') do
|
86
|
+
@options[:action] = :uninstall
|
87
|
+
end
|
88
|
+
|
89
|
+
opts.on('-i', '--install', 'Install Overcommit hooks in a repository') do
|
90
|
+
@options[:action] = :install
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on('-f', '--force', 'Overwrite any previously installed hooks') do
|
94
|
+
@options[:force] = true
|
95
|
+
end
|
96
|
+
|
97
|
+
opts.on('-r', '--run', 'Run pre-commit hook against all git tracked files') do
|
98
|
+
@options[:action] = :run_all
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_other_options(opts)
|
103
|
+
opts.on('-s', '--sign [hook]', 'Update hook signatures', String) do |hook_to_sign|
|
104
|
+
@options[:hook_to_sign] = hook_to_sign if hook_to_sign.is_a?(String)
|
105
|
+
@options[:action] = :sign
|
106
|
+
end
|
107
|
+
|
108
|
+
opts.on('-t', '--template-dir', 'Print location of template directory') do
|
109
|
+
@options[:action] = :template_dir
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def install_or_uninstall
|
114
|
+
if Array(@options[:targets]).empty?
|
115
|
+
@options[:targets] = [Overcommit::Utils.repo_root].compact
|
116
|
+
end
|
117
|
+
|
118
|
+
if @options[:targets].empty?
|
119
|
+
log.warning 'You are not in a git repository.'
|
120
|
+
log.log 'You must either specify the path to a repository or ' \
|
121
|
+
'change your current directory to a repository.'
|
122
|
+
halt 64 # EX_USAGE
|
123
|
+
end
|
124
|
+
|
125
|
+
@options[:targets].each do |target|
|
126
|
+
begin
|
127
|
+
Installer.new(log).run(target, @options)
|
128
|
+
rescue Overcommit::Exceptions::InvalidGitRepo => error
|
129
|
+
log.warning "Invalid repo #{target}: #{error}"
|
130
|
+
halt 69 # EX_UNAVAILABLE
|
131
|
+
rescue Overcommit::Exceptions::PreExistingHooks => error
|
132
|
+
log.warning "Unable to install into #{target}: #{error}"
|
133
|
+
halt 73 # EX_CANTCREAT
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def print_template_directory_path
|
139
|
+
puts File.join(Overcommit::HOME, 'template-dir')
|
140
|
+
halt
|
141
|
+
end
|
142
|
+
|
143
|
+
def print_help(message, error = nil)
|
144
|
+
log.error "#{error}\n" if error
|
145
|
+
log.log message
|
146
|
+
halt(error ? 64 : 0) # 64 = EX_USAGE
|
147
|
+
end
|
148
|
+
|
149
|
+
def print_version(program_name)
|
150
|
+
log.log "#{program_name} #{Overcommit::VERSION}"
|
151
|
+
halt
|
152
|
+
end
|
153
|
+
|
154
|
+
# Prints the hooks available in the current repo and whether they're
|
155
|
+
# enabled/disabled.
|
156
|
+
def print_installed_hooks
|
157
|
+
config.all_hook_configs.each do |hook_type, hook_configs|
|
158
|
+
print_hooks_for_hook_type(config, hook_configs, hook_type)
|
159
|
+
end
|
160
|
+
|
161
|
+
halt
|
162
|
+
end
|
163
|
+
|
164
|
+
def print_hooks_for_hook_type(repo_config, hook_configs, hook_type)
|
165
|
+
log.log "#{hook_type}:"
|
166
|
+
hook_configs.each do |hook_name, config|
|
167
|
+
log.partial " #{hook_name}: "
|
168
|
+
|
169
|
+
if config['enabled']
|
170
|
+
log.success('enabled', true)
|
171
|
+
else
|
172
|
+
log.error('disabled', true)
|
173
|
+
end
|
174
|
+
|
175
|
+
if repo_config.plugin_hook?(hook_type, hook_name)
|
176
|
+
log.warning(' (plugin)')
|
177
|
+
else
|
178
|
+
log.newline
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def sign
|
184
|
+
if @options[:hook_to_sign]
|
185
|
+
context = Overcommit::HookContext.create(@options[:hook_to_sign],
|
186
|
+
config,
|
187
|
+
@arguments,
|
188
|
+
@input)
|
189
|
+
Overcommit::HookLoader::PluginHookLoader.new(config,
|
190
|
+
context,
|
191
|
+
log).update_signatures
|
192
|
+
else
|
193
|
+
log.log 'Updating signature for configuration file...'
|
194
|
+
config(verify: false).update_signature!
|
195
|
+
end
|
196
|
+
|
197
|
+
halt
|
198
|
+
end
|
199
|
+
|
200
|
+
def run_all
|
201
|
+
empty_stdin = File.open(File::NULL) # pre-commit hooks don't take input
|
202
|
+
context = Overcommit::HookContext.create('run-all', config, @arguments, empty_stdin)
|
203
|
+
config.apply_environment!(context, ENV)
|
204
|
+
|
205
|
+
printer = Overcommit::Printer.new(config, log, context)
|
206
|
+
runner = Overcommit::HookRunner.new(config, log, context, printer)
|
207
|
+
|
208
|
+
status = runner.run
|
209
|
+
|
210
|
+
halt(status ? 0 : 65)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Used for ease of stubbing in tests
|
214
|
+
def halt(status = 0)
|
215
|
+
exit status
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns the configuration for this repository.
|
219
|
+
def config(options = {})
|
220
|
+
@config ||= Overcommit::ConfigurationLoader.new(log, options).load_repo_config
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Overcommit
|
4
|
+
# Distributes a list of arguments over multiple invocations of a command.
|
5
|
+
#
|
6
|
+
# This accomplishes the same functionality provided by `xargs` but in a
|
7
|
+
# cross-platform way that does not require any pre-existing tools.
|
8
|
+
#
|
9
|
+
# One of the tradeoffs with this approach is that we no longer deal with a
|
10
|
+
# single exit status from a command, but multiple (one for each invocation).
|
11
|
+
#
|
12
|
+
# This will return a struct similar to `Subprocess::Result` but with
|
13
|
+
# additional `statuses`, `stdouts`, and `stderrs` fields so hook authors can
|
14
|
+
# actually see the results of each invocation. If they don't care, the
|
15
|
+
# standard `status`, `stdout`, and `stderr` will still work but be a
|
16
|
+
# aggregation/concatenation of all statuses/outputs.
|
17
|
+
class CommandSplitter
|
18
|
+
# Encapsulates the result of a split argument run.
|
19
|
+
#
|
20
|
+
# @attr_reader statuses [Array<Integer>] status codes for invocations
|
21
|
+
# @attr_reader stdouts [Array<String>] standard outputs from invocations
|
22
|
+
# @attr_reader stderrs [Array<String>] standard error outputs from invocations
|
23
|
+
Result = Struct.new(:statuses, :stdouts, :stderrs) do
|
24
|
+
# Returns whether all invocations were successful.
|
25
|
+
#
|
26
|
+
# @return [true,false]
|
27
|
+
def success?
|
28
|
+
status == 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns `0` if all invocations returned `0`; `1` otherwise.
|
32
|
+
#
|
33
|
+
# @return [true,false]
|
34
|
+
def status
|
35
|
+
statuses.all? { |code| code == 0 } ? 0 : 1
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns concatenated standard output streams of all invocations in the
|
39
|
+
# order they were executed.
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def stdout
|
43
|
+
stdouts.join
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns concatenated standard error streams of all invocations in the
|
47
|
+
# order they were executed.
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
def stderr
|
51
|
+
stderrs.join
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class << self
|
56
|
+
def execute(initial_args, options)
|
57
|
+
options = options.dup
|
58
|
+
|
59
|
+
if (splittable_args = (options.delete(:args) { [] })).empty?
|
60
|
+
raise Overcommit::Exceptions::InvalidCommandArgs,
|
61
|
+
'Must specify list of arguments to split on'
|
62
|
+
end
|
63
|
+
|
64
|
+
# Execute each chunk of arguments in serial. We don't parallelize (yet)
|
65
|
+
# since in theory we want to support parallelization at the hook level
|
66
|
+
# and not within individual hooks.
|
67
|
+
results = extract_argument_lists(initial_args, splittable_args).map do |arg_list|
|
68
|
+
Overcommit::Subprocess.spawn(arg_list, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
Result.new(results.map(&:status), results.map(&:stdout), results.map(&:stderr))
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# Given a list of prefix arguments and suffix arguments that can be split,
|
77
|
+
# returns a list of argument lists that are executable on the current OS
|
78
|
+
# without exceeding command line limitations.
|
79
|
+
def extract_argument_lists(args, splittable_args)
|
80
|
+
# Total number of bytes needed to contain the prefix command
|
81
|
+
# (including byte separators between each argument)
|
82
|
+
prefix_bytes = (args.size - 1) + args.reduce(0) { |sum, arg| sum + arg.bytesize }
|
83
|
+
|
84
|
+
if prefix_bytes >= max_command_length
|
85
|
+
raise Overcommit::Exceptions::InvalidCommandArgs,
|
86
|
+
"Command `#{args.take(5).join(' ')} ...` is longer than the " \
|
87
|
+
'maximum number of bytes allowed by the operating system ' \
|
88
|
+
"(#{max_command_length})"
|
89
|
+
end
|
90
|
+
|
91
|
+
arg_lists = []
|
92
|
+
index = 0
|
93
|
+
while index <= splittable_args.length - 1
|
94
|
+
arg_list, index = arguments_under_limit(splittable_args,
|
95
|
+
index,
|
96
|
+
max_command_length - prefix_bytes)
|
97
|
+
arg_lists << args + arg_list
|
98
|
+
end
|
99
|
+
|
100
|
+
arg_lists
|
101
|
+
end
|
102
|
+
|
103
|
+
# @return [Array<Array<String>, Integer>] tuple of arguments and new index
|
104
|
+
def arguments_under_limit(splittable_args, start_index, byte_limit)
|
105
|
+
index = start_index
|
106
|
+
total_bytes = 0
|
107
|
+
|
108
|
+
loop do
|
109
|
+
break if index > splittable_args.length - 1
|
110
|
+
total_bytes += splittable_args[index].bytesize
|
111
|
+
break if total_bytes > byte_limit # Not enough room
|
112
|
+
index += 1
|
113
|
+
end
|
114
|
+
|
115
|
+
if index == start_index
|
116
|
+
# No argument was consumed; perhaps a really long argument?
|
117
|
+
raise Overcommit::Exceptions::InvalidCommandArgs,
|
118
|
+
"Argument `#{splittable_args[index][0..5]}...` exceeds the " \
|
119
|
+
'maximum command length when appended to command prefix and ' \
|
120
|
+
"can't be split further"
|
121
|
+
end
|
122
|
+
|
123
|
+
[splittable_args[start_index...index], index]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns the maximum number of arguments allowed in a single command on
|
127
|
+
# this system.
|
128
|
+
#
|
129
|
+
# @return [Integer]
|
130
|
+
def max_command_length
|
131
|
+
@max_command_length ||=
|
132
|
+
if Gem.win_platform?
|
133
|
+
# Windows is limited to 2048 since that is a worst-case scenario.
|
134
|
+
# http://blogs.msdn.com/b/oldnewthing/archive/2003/12/10/56028.aspx
|
135
|
+
2048
|
136
|
+
else
|
137
|
+
# We fudge factor this by halving the buffer size since *nix systems
|
138
|
+
# usually have pretty large limits, and the actual limit changes
|
139
|
+
# depending on how much of your stack is environment variables.
|
140
|
+
# Definitely erring on the side of overly cautious.
|
141
|
+
`getconf ARG_MAX`.to_i / 2
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,350 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Overcommit
|
7
|
+
# Stores configuration for Overcommit and the hooks it runs.
|
8
|
+
class Configuration # rubocop:disable ClassLength
|
9
|
+
# Creates a configuration from the given hash.
|
10
|
+
#
|
11
|
+
# @param hash [Hash] loaded YAML config file as a hash
|
12
|
+
# @param options [Hash]
|
13
|
+
# @option default [Boolean] whether this is the default built-in configuration
|
14
|
+
# @option logger [Overcommit::Logger]
|
15
|
+
def initialize(hash, options = {})
|
16
|
+
@options = options.dup
|
17
|
+
@options[:logger] ||= Overcommit::Logger.silent
|
18
|
+
@hash = hash # Assign so validator can read original values
|
19
|
+
unless options[:validate] == false
|
20
|
+
@hash = Overcommit::ConfigurationValidator.new.validate(self, hash, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
super || @hash == other.hash
|
26
|
+
end
|
27
|
+
|
28
|
+
# Access the configuration as if it were a hash.
|
29
|
+
#
|
30
|
+
# @param key [String]
|
31
|
+
# @return [Array,Hash,Number,String]
|
32
|
+
def [](key)
|
33
|
+
@hash[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns absolute path to the directory that external hook plugins should
|
37
|
+
# be loaded from.
|
38
|
+
def plugin_directory
|
39
|
+
File.join(Overcommit::Utils.repo_root, @hash['plugin_directory'] || '.git-hooks')
|
40
|
+
end
|
41
|
+
|
42
|
+
def concurrency
|
43
|
+
@concurrency ||=
|
44
|
+
begin
|
45
|
+
cores = Overcommit::Utils.processor_count
|
46
|
+
content = @hash.fetch('concurrency') { '%<processors>d' }
|
47
|
+
if content.is_a?(String)
|
48
|
+
concurrency_expr = content % { processors: cores }
|
49
|
+
|
50
|
+
a, op, b = concurrency_expr.scan(%r{(\d+)\s*([+\-*\/])\s*(\d+)})[0]
|
51
|
+
if a
|
52
|
+
a.to_i.send(op, b.to_i)
|
53
|
+
else
|
54
|
+
concurrency_expr.to_i
|
55
|
+
end
|
56
|
+
else
|
57
|
+
content.to_i
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns configuration for all hooks in each hook type.
|
63
|
+
#
|
64
|
+
# @return [Hash]
|
65
|
+
def all_hook_configs
|
66
|
+
smart_merge(all_builtin_hook_configs, all_plugin_hook_configs)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns configuration for all built-in hooks in each hook type.
|
70
|
+
#
|
71
|
+
# @return [Hash]
|
72
|
+
def all_builtin_hook_configs
|
73
|
+
hook_configs = {}
|
74
|
+
|
75
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
76
|
+
hook_names = @hash[hook_type].keys.reject { |name| name == 'ALL' }
|
77
|
+
|
78
|
+
hook_configs[hook_type] = Hash[
|
79
|
+
hook_names.map do |hook_name|
|
80
|
+
[hook_name, for_hook(hook_name, hook_type)]
|
81
|
+
end
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
hook_configs
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns configuration for all plugin hooks in each hook type.
|
89
|
+
#
|
90
|
+
# @return [Hash]
|
91
|
+
def all_plugin_hook_configs
|
92
|
+
hook_configs = {}
|
93
|
+
|
94
|
+
Overcommit::Utils.supported_hook_types.each do |hook_type|
|
95
|
+
hook_type_class_name = Overcommit::Utils.camel_case(hook_type)
|
96
|
+
|
97
|
+
directory = File.join(plugin_directory, hook_type.tr('-', '_'))
|
98
|
+
plugin_paths = Dir[File.join(directory, '*.rb')].sort
|
99
|
+
|
100
|
+
hook_names = plugin_paths.map do |path|
|
101
|
+
Overcommit::Utils.camel_case(File.basename(path, '.rb'))
|
102
|
+
end
|
103
|
+
|
104
|
+
hook_configs[hook_type_class_name] = Hash[
|
105
|
+
hook_names.map do |hook_name|
|
106
|
+
[hook_name, for_hook(hook_name, Overcommit::Utils.camel_case(hook_type))]
|
107
|
+
end
|
108
|
+
]
|
109
|
+
end
|
110
|
+
|
111
|
+
hook_configs
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the built-in hooks that have been enabled for a hook type.
|
115
|
+
def enabled_builtin_hooks(hook_context)
|
116
|
+
@hash[hook_context.hook_class_name].keys.
|
117
|
+
reject { |hook_name| hook_name == 'ALL' }.
|
118
|
+
select { |hook_name| built_in_hook?(hook_context, hook_name) }.
|
119
|
+
select { |hook_name| hook_enabled?(hook_context, hook_name) }
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the ad hoc hooks that have been enabled for a hook type.
|
123
|
+
def enabled_ad_hoc_hooks(hook_context)
|
124
|
+
@hash[hook_context.hook_class_name].keys.
|
125
|
+
reject { |hook_name| hook_name == 'ALL' }.
|
126
|
+
select { |hook_name| ad_hoc_hook?(hook_context, hook_name) }.
|
127
|
+
select { |hook_name| hook_enabled?(hook_context, hook_name) }
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns a non-modifiable configuration for a hook.
|
131
|
+
def for_hook(hook, hook_type = nil)
|
132
|
+
unless hook_type
|
133
|
+
components = hook.class.name.split('::')
|
134
|
+
hook = components.last
|
135
|
+
hook_type = components[-2]
|
136
|
+
end
|
137
|
+
|
138
|
+
# Merge hook configuration with special 'ALL' config
|
139
|
+
hook_config = smart_merge(@hash[hook_type]['ALL'], @hash[hook_type][hook] || {})
|
140
|
+
|
141
|
+
# Need to specially handle `enabled` option since not setting it does not
|
142
|
+
# necessarily mean the hook is disabled
|
143
|
+
hook_config['enabled'] = hook_enabled?(hook_type, hook)
|
144
|
+
|
145
|
+
hook_config.freeze
|
146
|
+
end
|
147
|
+
|
148
|
+
# Merges the given configuration with this one, returning a new
|
149
|
+
# {Configuration}. The provided configuration will either add to or replace
|
150
|
+
# any options defined in this configuration.
|
151
|
+
def merge(config)
|
152
|
+
self.class.new(smart_merge(@hash, config.hash))
|
153
|
+
end
|
154
|
+
|
155
|
+
# Applies additional configuration settings based on the provided
|
156
|
+
# environment variables.
|
157
|
+
def apply_environment!(hook_context, env)
|
158
|
+
skipped_hooks = "#{env['SKIP']} #{env['SKIP_CHECKS']} #{env['SKIP_HOOKS']}".split(/[:, ]/)
|
159
|
+
only_hooks = env.fetch('ONLY') { '' }.split(/[:, ]/)
|
160
|
+
hook_type = hook_context.hook_class_name
|
161
|
+
|
162
|
+
if only_hooks.any? || skipped_hooks.include?('all') || skipped_hooks.include?('ALL')
|
163
|
+
@hash[hook_type]['ALL']['skip'] = true
|
164
|
+
end
|
165
|
+
|
166
|
+
only_hooks.select { |hook_name| hook_exists?(hook_context, hook_name) }.
|
167
|
+
map { |hook_name| Overcommit::Utils.camel_case(hook_name) }.
|
168
|
+
each do |hook_name|
|
169
|
+
@hash[hook_type][hook_name] ||= {}
|
170
|
+
@hash[hook_type][hook_name]['skip'] = false
|
171
|
+
end
|
172
|
+
|
173
|
+
skipped_hooks.select { |hook_name| hook_exists?(hook_context, hook_name) }.
|
174
|
+
map { |hook_name| Overcommit::Utils.camel_case(hook_name) }.
|
175
|
+
each do |hook_name|
|
176
|
+
@hash[hook_type][hook_name] ||= {}
|
177
|
+
@hash[hook_type][hook_name]['skip'] = true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def plugin_hook?(hook_context_or_type, hook_name)
|
182
|
+
hook_type_name =
|
183
|
+
if hook_context_or_type.is_a?(String)
|
184
|
+
Overcommit::Utils.snake_case(hook_context_or_type)
|
185
|
+
else
|
186
|
+
hook_context_or_type.hook_type_name
|
187
|
+
end
|
188
|
+
hook_name = Overcommit::Utils.snake_case(hook_name)
|
189
|
+
|
190
|
+
File.exist?(File.join(plugin_directory, hook_type_name, "#{hook_name}.rb"))
|
191
|
+
end
|
192
|
+
|
193
|
+
# Return whether the signature for this configuration has changed since it
|
194
|
+
# was last calculated.
|
195
|
+
#
|
196
|
+
# @return [true,false]
|
197
|
+
def signature_changed?
|
198
|
+
signature != stored_signature
|
199
|
+
end
|
200
|
+
|
201
|
+
# Return whether a previous signature has been recorded for this
|
202
|
+
# configuration.
|
203
|
+
#
|
204
|
+
# @return [true,false]
|
205
|
+
def previous_signature?
|
206
|
+
!stored_signature.empty?
|
207
|
+
end
|
208
|
+
|
209
|
+
# Returns whether this configuration should verify itself by checking the
|
210
|
+
# stored configuration for the repo.
|
211
|
+
#
|
212
|
+
# @return [true,false]
|
213
|
+
def verify_signatures?
|
214
|
+
return false if ENV['OVERCOMMIT_NO_VERIFY']
|
215
|
+
return true if @hash['verify_signatures'] != false
|
216
|
+
|
217
|
+
result = Overcommit::Utils.execute(
|
218
|
+
%W[git config --local --get #{verify_signature_config_key}]
|
219
|
+
)
|
220
|
+
|
221
|
+
if result.status == 1 # Key doesn't exist
|
222
|
+
return true
|
223
|
+
elsif result.status != 0
|
224
|
+
raise Overcommit::Exceptions::GitConfigError,
|
225
|
+
"Unable to read from local repo git config: #{result.stderr}"
|
226
|
+
end
|
227
|
+
|
228
|
+
# We don't cast since we want to allow anything to count as "true" except
|
229
|
+
# a literal zero
|
230
|
+
result.stdout.strip != '0'
|
231
|
+
end
|
232
|
+
|
233
|
+
# Update the currently stored signature for this hook.
|
234
|
+
def update_signature!
|
235
|
+
result = Overcommit::Utils.execute(
|
236
|
+
%w[git config --local] + [signature_config_key, signature]
|
237
|
+
)
|
238
|
+
|
239
|
+
verify_signature_value = @hash['verify_signatures'] ? 1 : 0
|
240
|
+
result &&= Overcommit::Utils.execute(
|
241
|
+
%W[git config --local #{verify_signature_config_key} #{verify_signature_value}]
|
242
|
+
)
|
243
|
+
|
244
|
+
unless result.success?
|
245
|
+
raise Overcommit::Exceptions::GitConfigError,
|
246
|
+
"Unable to write to local repo git config: #{result.stderr}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
protected
|
251
|
+
|
252
|
+
attr_reader :hash
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
def ad_hoc_hook?(hook_context, hook_name)
|
257
|
+
ad_hoc_conf = @hash.fetch(hook_context.hook_class_name) { {} }.fetch(hook_name) { {} }
|
258
|
+
|
259
|
+
# Ad hoc hooks are neither built-in nor have a plugin file written but
|
260
|
+
# still have a `command` specified to be run
|
261
|
+
!built_in_hook?(hook_context, hook_name) &&
|
262
|
+
!plugin_hook?(hook_context, hook_name) &&
|
263
|
+
(ad_hoc_conf['command'] || ad_hoc_conf['required_executable'])
|
264
|
+
end
|
265
|
+
|
266
|
+
def built_in_hook?(hook_context, hook_name)
|
267
|
+
hook_name = Overcommit::Utils.snake_case(hook_name)
|
268
|
+
|
269
|
+
File.exist?(File.join(Overcommit::HOME, 'lib', 'overcommit', 'hook',
|
270
|
+
hook_context.hook_type_name, "#{hook_name}.rb"))
|
271
|
+
end
|
272
|
+
|
273
|
+
def hook_exists?(hook_context, hook_name)
|
274
|
+
built_in_hook?(hook_context, hook_name) ||
|
275
|
+
plugin_hook?(hook_context, hook_name) ||
|
276
|
+
ad_hoc_hook?(hook_context, hook_name)
|
277
|
+
end
|
278
|
+
|
279
|
+
def hook_enabled?(hook_context_or_type, hook_name)
|
280
|
+
hook_type =
|
281
|
+
if hook_context_or_type.is_a?(String)
|
282
|
+
hook_context_or_type
|
283
|
+
else
|
284
|
+
hook_context_or_type.hook_class_name
|
285
|
+
end
|
286
|
+
|
287
|
+
individual_enabled = @hash[hook_type].fetch(hook_name) { {} }['enabled']
|
288
|
+
return individual_enabled unless individual_enabled.nil?
|
289
|
+
|
290
|
+
all_enabled = @hash[hook_type]['ALL']['enabled']
|
291
|
+
return all_enabled unless all_enabled.nil?
|
292
|
+
|
293
|
+
false
|
294
|
+
end
|
295
|
+
|
296
|
+
def smart_merge(parent, child)
|
297
|
+
# Treat the ALL hook specially so that it overrides any configuration
|
298
|
+
# specified by the default configuration.
|
299
|
+
child_all = child['ALL']
|
300
|
+
unless child_all.nil?
|
301
|
+
parent = Hash[parent.collect { |k, v| [k, smart_merge(v, child_all)] }]
|
302
|
+
end
|
303
|
+
|
304
|
+
parent.merge(child) do |_key, old, new|
|
305
|
+
case old
|
306
|
+
when Hash
|
307
|
+
smart_merge(old, new)
|
308
|
+
else
|
309
|
+
new
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# Returns the unique signature of this configuration.
|
315
|
+
#
|
316
|
+
# @return [String]
|
317
|
+
def signature
|
318
|
+
Digest::SHA256.hexdigest(@hash.to_json)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns the stored signature of this repo's Overcommit configuration.
|
322
|
+
#
|
323
|
+
# This is intended to be compared against the current signature of this
|
324
|
+
# configuration object.
|
325
|
+
#
|
326
|
+
# @return [String]
|
327
|
+
def stored_signature
|
328
|
+
result = Overcommit::Utils.execute(
|
329
|
+
%w[git config --local --get] + [signature_config_key]
|
330
|
+
)
|
331
|
+
|
332
|
+
if result.status == 1 # Key doesn't exist
|
333
|
+
return ''
|
334
|
+
elsif result.status != 0
|
335
|
+
raise Overcommit::Exceptions::GitConfigError,
|
336
|
+
"Unable to read from local repo git config: #{result.stderr}"
|
337
|
+
end
|
338
|
+
|
339
|
+
result.stdout.chomp
|
340
|
+
end
|
341
|
+
|
342
|
+
def signature_config_key
|
343
|
+
'overcommit.configuration.signature'
|
344
|
+
end
|
345
|
+
|
346
|
+
def verify_signature_config_key
|
347
|
+
'overcommit.configuration.verifysignatures'
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|