overcommit-jeygeethanmedia 0.53.1
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 +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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module Overcommit
|
|
6
|
+
# Manages configuration file loading.
|
|
7
|
+
class ConfigurationLoader
|
|
8
|
+
DEFAULT_CONFIG_PATH = File.join(Overcommit::HOME, 'config', 'default.yml')
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
# Loads and returns the default configuration.
|
|
12
|
+
#
|
|
13
|
+
# @return [Overcommit::Configuration]
|
|
14
|
+
def default_configuration
|
|
15
|
+
@default_configuration ||= load_from_file(DEFAULT_CONFIG_PATH, default: true, verify: false)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Loads configuration from file.
|
|
19
|
+
#
|
|
20
|
+
# @param file [String] path to file
|
|
21
|
+
# @param options [Hash]
|
|
22
|
+
# @option default [Boolean] whether this is the default built-in configuration
|
|
23
|
+
# @option verify [Boolean] whether to verify the signature of the configuration
|
|
24
|
+
# @option logger [Overcommit::Logger]
|
|
25
|
+
# @return [Overcommit::Configuration]
|
|
26
|
+
def load_from_file(file, options = {})
|
|
27
|
+
hash =
|
|
28
|
+
if yaml = YAML.load_file(file)
|
|
29
|
+
yaml.to_hash
|
|
30
|
+
else
|
|
31
|
+
{}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
Overcommit::Configuration.new(hash, options)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Create a configuration loader which writes warnings/errors to the given
|
|
39
|
+
# {Overcommit::Logger} instance.
|
|
40
|
+
#
|
|
41
|
+
# @param logger [Overcommit::Logger]
|
|
42
|
+
# @param options [Hash]
|
|
43
|
+
# @option verify [Boolean] whether to verify signatures
|
|
44
|
+
def initialize(logger, options = {})
|
|
45
|
+
@log = logger
|
|
46
|
+
@options = options
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Loads and returns the configuration for the repository we're running in.
|
|
50
|
+
#
|
|
51
|
+
# @return [Overcommit::Configuration]
|
|
52
|
+
def load_repo_config
|
|
53
|
+
overcommit_yml = File.join(Overcommit::Utils.repo_root,
|
|
54
|
+
Overcommit::CONFIG_FILE_NAME)
|
|
55
|
+
|
|
56
|
+
if File.exist?(overcommit_yml)
|
|
57
|
+
load_file(overcommit_yml)
|
|
58
|
+
else
|
|
59
|
+
self.class.default_configuration
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Loads a configuration, ensuring it extends the default configuration.
|
|
64
|
+
def load_file(file)
|
|
65
|
+
config = self.class.load_from_file(file, default: false, logger: @log)
|
|
66
|
+
config = self.class.default_configuration.merge(config)
|
|
67
|
+
|
|
68
|
+
if @options.fetch(:verify) { config.verify_signatures? }
|
|
69
|
+
verify_signatures(config)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
config
|
|
73
|
+
rescue Overcommit::Exceptions::ConfigurationSignatureChanged
|
|
74
|
+
raise
|
|
75
|
+
rescue StandardError => error
|
|
76
|
+
raise Overcommit::Exceptions::ConfigurationError,
|
|
77
|
+
"Unable to load configuration from '#{file}': #{error}",
|
|
78
|
+
error.backtrace
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def verify_signatures(config)
|
|
84
|
+
if !config.previous_signature?
|
|
85
|
+
raise Overcommit::Exceptions::ConfigurationSignatureChanged,
|
|
86
|
+
"No previously recorded signature for configuration file.\n" \
|
|
87
|
+
'Run `overcommit --sign` if you trust the hooks in this repository.'
|
|
88
|
+
|
|
89
|
+
elsif config.signature_changed?
|
|
90
|
+
raise Overcommit::Exceptions::ConfigurationSignatureChanged,
|
|
91
|
+
"Signature of configuration file has changed!\n" \
|
|
92
|
+
"Run `overcommit --sign` once you've verified the configuration changes."
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/ClassLength, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
4
|
+
module Overcommit
|
|
5
|
+
# Validates and normalizes a configuration.
|
|
6
|
+
class ConfigurationValidator
|
|
7
|
+
# Validates hash for any invalid options, normalizing where possible.
|
|
8
|
+
#
|
|
9
|
+
# @param config [Overcommit::Configuration]
|
|
10
|
+
# @param hash [Hash] hash representation of YAML config
|
|
11
|
+
# @param options[Hash]
|
|
12
|
+
# @option default [Boolean] whether hash represents the default built-in config
|
|
13
|
+
# @option logger [Overcommit::Logger] logger to output warnings to
|
|
14
|
+
# @return [Hash] validated hash (potentially modified)
|
|
15
|
+
def validate(config, hash, options)
|
|
16
|
+
@options = options.dup
|
|
17
|
+
@log = options[:logger]
|
|
18
|
+
|
|
19
|
+
hash = convert_nils_to_empty_hashes(hash)
|
|
20
|
+
ensure_hook_type_sections_exist(hash)
|
|
21
|
+
check_hook_name_format(hash)
|
|
22
|
+
check_hook_env(hash)
|
|
23
|
+
check_for_missing_enabled_option(hash) unless @options[:default]
|
|
24
|
+
check_for_too_many_processors(config, hash)
|
|
25
|
+
check_for_verify_plugin_signatures_option(hash)
|
|
26
|
+
|
|
27
|
+
hash
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Ensures that keys for all supported hook types exist (PreCommit,
|
|
33
|
+
# CommitMsg, etc.)
|
|
34
|
+
def ensure_hook_type_sections_exist(hash)
|
|
35
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
|
36
|
+
hash[hook_type] ||= {}
|
|
37
|
+
hash[hook_type]['ALL'] ||= {}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Normalizes `nil` values to empty hashes.
|
|
42
|
+
#
|
|
43
|
+
# This is useful for when we want to merge two configuration hashes
|
|
44
|
+
# together, since it's easier to merge two hashes than to have to check if
|
|
45
|
+
# one of the values is nil.
|
|
46
|
+
def convert_nils_to_empty_hashes(hash)
|
|
47
|
+
hash.each_with_object({}) do |(key, value), h|
|
|
48
|
+
h[key] =
|
|
49
|
+
case value
|
|
50
|
+
when nil then {}
|
|
51
|
+
when Hash then convert_nils_to_empty_hashes(value)
|
|
52
|
+
else
|
|
53
|
+
value
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def check_hook_env(hash)
|
|
59
|
+
errors = []
|
|
60
|
+
|
|
61
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
|
62
|
+
hash.fetch(hook_type) { {} }.each do |hook_name, hook_config|
|
|
63
|
+
hook_env = hook_config.fetch('env') { {} }
|
|
64
|
+
|
|
65
|
+
unless hook_env.is_a?(Hash)
|
|
66
|
+
errors << "#{hook_type}::#{hook_name} has an invalid `env` specified: " \
|
|
67
|
+
'must be a hash of environment variable name to string value.'
|
|
68
|
+
next
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
hook_env.each do |var_name, var_value|
|
|
72
|
+
if var_name.include?('=')
|
|
73
|
+
errors << "#{hook_type}::#{hook_name} has an invalid `env` specified: " \
|
|
74
|
+
"variable name `#{var_name}` cannot contain `=`."
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
unless var_value.nil? || var_value.is_a?(String)
|
|
78
|
+
errors << "#{hook_type}::#{hook_name} has an invalid `env` specified: " \
|
|
79
|
+
"value of `#{var_name}` must be a string or `nil`, but was " \
|
|
80
|
+
"#{var_value.inspect} (#{var_value.class})"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if errors.any?
|
|
87
|
+
if @log
|
|
88
|
+
@log.error errors.join("\n")
|
|
89
|
+
@log.newline
|
|
90
|
+
end
|
|
91
|
+
raise Overcommit::Exceptions::ConfigurationError,
|
|
92
|
+
'One or more hooks had an invalid `env` configuration option'
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Prints an error message and raises an exception if a hook has an
|
|
97
|
+
# invalid name, since this can result in strange errors elsewhere.
|
|
98
|
+
def check_hook_name_format(hash)
|
|
99
|
+
errors = []
|
|
100
|
+
|
|
101
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
|
102
|
+
hash.fetch(hook_type) { {} }.each_key do |hook_name|
|
|
103
|
+
next if hook_name == 'ALL'
|
|
104
|
+
|
|
105
|
+
unless hook_name.match?(/\A[A-Za-z0-9]+\z/)
|
|
106
|
+
errors << "#{hook_type}::#{hook_name} has an invalid name " \
|
|
107
|
+
"#{hook_name}. It must contain only alphanumeric " \
|
|
108
|
+
'characters (no underscores or dashes, etc.)'
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
if errors.any?
|
|
114
|
+
if @log
|
|
115
|
+
@log.error errors.join("\n")
|
|
116
|
+
@log.newline
|
|
117
|
+
end
|
|
118
|
+
raise Overcommit::Exceptions::ConfigurationError,
|
|
119
|
+
'One or more hooks had invalid names'
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Prints a warning if there are any hooks listed in the configuration
|
|
124
|
+
# without `enabled` explicitly set.
|
|
125
|
+
def check_for_missing_enabled_option(hash)
|
|
126
|
+
return unless @log
|
|
127
|
+
|
|
128
|
+
any_warnings = false
|
|
129
|
+
|
|
130
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
|
131
|
+
hash.fetch(hook_type) { {} }.each do |hook_name, hook_config|
|
|
132
|
+
next if hook_name == 'ALL'
|
|
133
|
+
|
|
134
|
+
if hook_config['enabled'].nil?
|
|
135
|
+
@log.warning "#{hook_type}::#{hook_name} hook does not explicitly " \
|
|
136
|
+
'set `enabled` option in .overcommit.yml'
|
|
137
|
+
any_warnings = true
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
@log.newline if any_warnings
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Prints a warning if any hook has a number of processors larger than the
|
|
146
|
+
# global `concurrency` setting.
|
|
147
|
+
def check_for_too_many_processors(config, hash)
|
|
148
|
+
concurrency = config.concurrency
|
|
149
|
+
|
|
150
|
+
errors = []
|
|
151
|
+
Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
|
|
152
|
+
hash.fetch(hook_type) { {} }.each do |hook_name, hook_config|
|
|
153
|
+
processors = hook_config.fetch('processors') { 1 }
|
|
154
|
+
if processors > concurrency
|
|
155
|
+
errors << "#{hook_type}::#{hook_name} `processors` value " \
|
|
156
|
+
"(#{processors}) is larger than the global `concurrency` " \
|
|
157
|
+
"option (#{concurrency})"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if errors.any?
|
|
163
|
+
if @log
|
|
164
|
+
@log.error errors.join("\n")
|
|
165
|
+
@log.newline
|
|
166
|
+
end
|
|
167
|
+
raise Overcommit::Exceptions::ConfigurationError,
|
|
168
|
+
'One or more hooks had invalid `processor` value configured'
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Prints a warning if the `verify_plugin_signatures` option is used instead
|
|
173
|
+
# of the new `verify_signatures` option.
|
|
174
|
+
def check_for_verify_plugin_signatures_option(hash)
|
|
175
|
+
return unless @log
|
|
176
|
+
|
|
177
|
+
if hash.key?('verify_plugin_signatures')
|
|
178
|
+
@log.warning '`verify_plugin_signatures` has been renamed to ' \
|
|
179
|
+
'`verify_signatures`. Defaulting to verifying signatures.'
|
|
180
|
+
@log.warning "See change log at #{REPO_URL}/blob/v0.29.0/CHANGELOG.md for details."
|
|
181
|
+
@log.newline
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
# rubocop:enable Metrics/ClassLength, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Global application constants.
|
|
4
|
+
module Overcommit
|
|
5
|
+
HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
|
|
6
|
+
CONFIG_FILE_NAME = '.overcommit.yml'
|
|
7
|
+
|
|
8
|
+
HOOK_DIRECTORY = File.join(HOME, 'lib', 'overcommit', 'hook').freeze
|
|
9
|
+
|
|
10
|
+
REPO_URL = 'https://github.com/sds/overcommit'
|
|
11
|
+
BUG_REPORT_URL = "#{REPO_URL}/issues"
|
|
12
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overcommit::Exceptions
|
|
4
|
+
# Raised when a {Configuration} could not be loaded from a file.
|
|
5
|
+
class ConfigurationError < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Raised when the Overcommit configuration file signature has changed.
|
|
8
|
+
class ConfigurationSignatureChanged < StandardError; end
|
|
9
|
+
|
|
10
|
+
# Raised when trying to read/write to/from the local repo git config fails.
|
|
11
|
+
class GitConfigError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Raised when there was a problem reading submodule information for a repo.
|
|
14
|
+
class GitSubmoduleError < StandardError; end
|
|
15
|
+
|
|
16
|
+
# Raised when there was a problem reading git revision information with `rev-list`.
|
|
17
|
+
class GitRevListError < StandardError; end
|
|
18
|
+
|
|
19
|
+
# Raised when a {HookContext} is unable to setup the environment before a run.
|
|
20
|
+
class HookSetupFailed < StandardError; end
|
|
21
|
+
|
|
22
|
+
# Raised when a {HookContext} is unable to clean the environment after a run.
|
|
23
|
+
class HookCleanupFailed < StandardError; end
|
|
24
|
+
|
|
25
|
+
# Raised when a hook run was cancelled by the user.
|
|
26
|
+
class HookCancelled < StandardError; end
|
|
27
|
+
|
|
28
|
+
# Raised when a hook could not be loaded by a {HookRunner}.
|
|
29
|
+
class HookLoadError < StandardError; end
|
|
30
|
+
|
|
31
|
+
# Raised when a {HookRunner} could not be loaded.
|
|
32
|
+
class HookContextLoadError < StandardError; end
|
|
33
|
+
|
|
34
|
+
# Raised when a pipe character is used in the `execute` helper, as this was
|
|
35
|
+
# likely used in error.
|
|
36
|
+
class InvalidCommandArgs < StandardError; end
|
|
37
|
+
|
|
38
|
+
# Raised when an installation target is not a valid git repository.
|
|
39
|
+
class InvalidGitRepo < StandardError; end
|
|
40
|
+
|
|
41
|
+
# Raised when a hook was defined incorrectly.
|
|
42
|
+
class InvalidHookDefinition < StandardError; end
|
|
43
|
+
|
|
44
|
+
# Raised when one or more hook plugin signatures have changed.
|
|
45
|
+
class InvalidHookSignature < StandardError; end
|
|
46
|
+
|
|
47
|
+
# Raised when there is a problem processing output into {Hook::Messages}s.
|
|
48
|
+
class MessageProcessingError < StandardError; end
|
|
49
|
+
|
|
50
|
+
# Raised when an installation target already contains non-Overcommit hooks.
|
|
51
|
+
class PreExistingHooks < StandardError; end
|
|
52
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'overcommit/utils'
|
|
4
|
+
|
|
5
|
+
module Overcommit
|
|
6
|
+
# Get configuration options from git
|
|
7
|
+
module GitConfig
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def comment_character
|
|
11
|
+
char = `git config --get core.commentchar`.chomp
|
|
12
|
+
char = '#' if char == ''
|
|
13
|
+
char
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def hooks_path
|
|
17
|
+
path = `git config --get core.hooksPath`.chomp
|
|
18
|
+
return File.join(Overcommit::Utils.git_dir, 'hooks') if path.empty?
|
|
19
|
+
File.absolute_path(path, Dir.pwd)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'iniparse'
|
|
4
|
+
require 'shellwords'
|
|
5
|
+
|
|
6
|
+
module Overcommit
|
|
7
|
+
# Provide a set of utilities for certain interactions with `git`.
|
|
8
|
+
module GitRepo
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
# Regular expression used to extract diff ranges from hunks of diff output.
|
|
12
|
+
DIFF_HUNK_REGEX = /
|
|
13
|
+
^@@\s
|
|
14
|
+
[^\s]+\s # Ignore old file range
|
|
15
|
+
\+(\d+)(?:,(\d+))? # Extract range of hunk containing start line and number of lines
|
|
16
|
+
\s@@.*$
|
|
17
|
+
/x
|
|
18
|
+
|
|
19
|
+
# Regular expression used to extract information from lines of
|
|
20
|
+
# `git submodule status` output
|
|
21
|
+
SUBMODULE_STATUS_REGEX = /
|
|
22
|
+
^\s*(?<prefix>[-+U]?)(?<sha1>\w+)
|
|
23
|
+
\s(?<path>[^\s]+?)
|
|
24
|
+
(?:\s\((?<describe>.+)\))?$
|
|
25
|
+
/x
|
|
26
|
+
|
|
27
|
+
# Struct encapsulating submodule information extracted from the
|
|
28
|
+
# output of `git submodule status`
|
|
29
|
+
SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do
|
|
30
|
+
# Returns whether the submodule has not been initialized
|
|
31
|
+
def uninitialized?
|
|
32
|
+
prefix == '-'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns whether the submodule is out of date with the current
|
|
36
|
+
# index, i.e. its checked-out commit differs from that stored in
|
|
37
|
+
# the index of the parent repo
|
|
38
|
+
def outdated?
|
|
39
|
+
prefix == '+'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns whether the submodule reference has a merge conflict
|
|
43
|
+
def merge_conflict?
|
|
44
|
+
prefix == 'U'
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns a list of SubmoduleStatus objects, one for each submodule in the
|
|
49
|
+
# parent repository.
|
|
50
|
+
#
|
|
51
|
+
# @option options [Boolean] recursive check submodules recursively
|
|
52
|
+
# @return [Array<SubmoduleStatus>]
|
|
53
|
+
def submodule_statuses(options = {})
|
|
54
|
+
flags = '--recursive' if options[:recursive]
|
|
55
|
+
|
|
56
|
+
`git submodule status #{flags}`.
|
|
57
|
+
scan(SUBMODULE_STATUS_REGEX).
|
|
58
|
+
map do |prefix, sha1, path, describe|
|
|
59
|
+
SubmoduleStatus.new(prefix, sha1, path, describe)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Extract the set of modified lines from a given file.
|
|
64
|
+
#
|
|
65
|
+
# @param file_path [String]
|
|
66
|
+
# @param options [Hash]
|
|
67
|
+
# @return [Set] line numbers that have been modified in file
|
|
68
|
+
def extract_modified_lines(file_path, options)
|
|
69
|
+
lines = Set.new
|
|
70
|
+
|
|
71
|
+
flags = '--cached' if options[:staged]
|
|
72
|
+
refs = options[:refs]
|
|
73
|
+
subcmd = options[:subcmd] || 'diff'
|
|
74
|
+
|
|
75
|
+
`git #{subcmd} --no-color --no-ext-diff -U0 #{flags} #{refs} -- "#{file_path}"`.
|
|
76
|
+
scan(DIFF_HUNK_REGEX) do |start_line, lines_added|
|
|
77
|
+
lines_added = (lines_added || 1).to_i # When blank, one line was added
|
|
78
|
+
cur_line = start_line.to_i
|
|
79
|
+
|
|
80
|
+
lines_added.times do
|
|
81
|
+
lines.add cur_line
|
|
82
|
+
cur_line += 1
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
lines
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Returns the names of all files that have been modified compared to HEAD.
|
|
90
|
+
#
|
|
91
|
+
# @param options [Hash]
|
|
92
|
+
# @return [Array<String>] list of absolute file paths
|
|
93
|
+
def modified_files(options)
|
|
94
|
+
flags = '--cached' if options[:staged]
|
|
95
|
+
refs = options[:refs]
|
|
96
|
+
subcmd = options[:subcmd] || 'diff'
|
|
97
|
+
|
|
98
|
+
`git #{subcmd} --name-only -z --diff-filter=ACMR --ignore-submodules=all #{flags} #{refs}`.
|
|
99
|
+
split("\0").
|
|
100
|
+
map(&:strip).
|
|
101
|
+
reject(&:empty?).
|
|
102
|
+
map { |relative_file| File.expand_path(relative_file) }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns the names of files in the given paths that are tracked by git.
|
|
106
|
+
#
|
|
107
|
+
# @param paths [Array<String>] list of paths to check
|
|
108
|
+
# @option options [String] ref ('HEAD') Git ref to check
|
|
109
|
+
# @return [Array<String>] list of absolute file paths
|
|
110
|
+
def list_files(paths = [], options = {})
|
|
111
|
+
ref = options[:ref] || 'HEAD'
|
|
112
|
+
path_list =
|
|
113
|
+
if OS.windows?
|
|
114
|
+
paths = paths.map { |path| path.gsub('"', '""') }
|
|
115
|
+
paths.empty? ? '' : "\"#{paths.join('" "')}\""
|
|
116
|
+
else
|
|
117
|
+
paths.shelljoin
|
|
118
|
+
end
|
|
119
|
+
`git ls-tree --name-only #{ref} #{path_list}`.
|
|
120
|
+
split(/\n/).
|
|
121
|
+
map { |relative_file| File.expand_path(relative_file) }.
|
|
122
|
+
reject { |file| File.directory?(file) } # Exclude submodule directories
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Returns whether the specified file/path is tracked by this repository.
|
|
126
|
+
#
|
|
127
|
+
# @param path [String]
|
|
128
|
+
# @return [true,false]
|
|
129
|
+
def tracked?(path)
|
|
130
|
+
Overcommit::Utils.execute(%W[git ls-files #{path} --error-unmatch]).success?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Returns the names of all files that are tracked by git.
|
|
134
|
+
#
|
|
135
|
+
# @return [Array<String>] list of absolute file paths
|
|
136
|
+
def all_files
|
|
137
|
+
`git ls-files`.
|
|
138
|
+
split(/\n/).
|
|
139
|
+
map { |relative_file| File.expand_path(relative_file) }.
|
|
140
|
+
reject { |file| File.directory?(file) } # Exclude submodule directories
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Returns whether the current git branch is empty (has no commits).
|
|
144
|
+
# @return [true,false]
|
|
145
|
+
def initial_commit?
|
|
146
|
+
!Overcommit::Utils.execute(%w[git rev-parse HEAD]).success?
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Store any relevant files that are present when repo is in the middle of a
|
|
150
|
+
# merge.
|
|
151
|
+
#
|
|
152
|
+
# Restored via [#restore_merge_state].
|
|
153
|
+
def store_merge_state
|
|
154
|
+
merge_head = `git rev-parse MERGE_HEAD 2> #{File::NULL}`.chomp
|
|
155
|
+
|
|
156
|
+
# Store the merge state if we're in the middle of resolving a merge
|
|
157
|
+
# conflict. This is necessary since stashing removes the merge state.
|
|
158
|
+
if merge_head != 'MERGE_HEAD'
|
|
159
|
+
@merge_head = merge_head
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
merge_msg_file = File.expand_path('MERGE_MSG', Overcommit::Utils.git_dir)
|
|
163
|
+
@merge_msg = File.open(merge_msg_file).read if File.exist?(merge_msg_file)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Store any relevant files that are present when repo is in the middle of a
|
|
167
|
+
# cherry-pick.
|
|
168
|
+
#
|
|
169
|
+
# Restored via [#restore_cherry_pick_state].
|
|
170
|
+
def store_cherry_pick_state
|
|
171
|
+
cherry_head = `git rev-parse CHERRY_PICK_HEAD 2> #{File::NULL}`.chomp
|
|
172
|
+
|
|
173
|
+
# Store the merge state if we're in the middle of resolving a merge
|
|
174
|
+
# conflict. This is necessary since stashing removes the merge state.
|
|
175
|
+
if cherry_head != 'CHERRY_PICK_HEAD'
|
|
176
|
+
@cherry_head = cherry_head
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Restore any relevant files that were present when repo was in the middle
|
|
181
|
+
# of a merge.
|
|
182
|
+
def restore_merge_state
|
|
183
|
+
if @merge_head
|
|
184
|
+
FileUtils.touch(File.expand_path('MERGE_MODE', Overcommit::Utils.git_dir))
|
|
185
|
+
|
|
186
|
+
File.open(File.expand_path('MERGE_HEAD', Overcommit::Utils.git_dir), 'w') do |f|
|
|
187
|
+
f.write(@merge_head)
|
|
188
|
+
end
|
|
189
|
+
@merge_head = nil
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
if @merge_msg
|
|
193
|
+
File.open(File.expand_path('MERGE_MSG', Overcommit::Utils.git_dir), 'w') do |f|
|
|
194
|
+
f.write("#{@merge_msg}\n")
|
|
195
|
+
end
|
|
196
|
+
@merge_msg = nil
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Restore any relevant files that were present when repo was in the middle
|
|
201
|
+
# of a cherry-pick.
|
|
202
|
+
def restore_cherry_pick_state
|
|
203
|
+
if @cherry_head
|
|
204
|
+
File.open(File.expand_path('CHERRY_PICK_HEAD',
|
|
205
|
+
Overcommit::Utils.git_dir), 'w') do |f|
|
|
206
|
+
f.write(@cherry_head)
|
|
207
|
+
end
|
|
208
|
+
@cherry_head = nil
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Contains information about a registered submodule.
|
|
213
|
+
Submodule = Struct.new(:path, :url)
|
|
214
|
+
|
|
215
|
+
# Returns the submodules that have been staged for removal.
|
|
216
|
+
#
|
|
217
|
+
# `git` has an unexpected behavior where removing a submodule without
|
|
218
|
+
# committing (i.e. such that the submodule directory is removed and the
|
|
219
|
+
# changes to the index are staged) and then doing a hard reset results in
|
|
220
|
+
# the index being wiped but the empty directory of the once existent
|
|
221
|
+
# submodule being restored (but with no content).
|
|
222
|
+
#
|
|
223
|
+
# This prevents restoration of the stash of the submodule index changes,
|
|
224
|
+
# which breaks pre-commit hook restorations of the working index.
|
|
225
|
+
#
|
|
226
|
+
# Thus we expose this helper so the restoration code can manually delete the
|
|
227
|
+
# directory.
|
|
228
|
+
#
|
|
229
|
+
# @raise [Overcommit::Exceptions::GitSubmoduleError] when
|
|
230
|
+
def staged_submodule_removals
|
|
231
|
+
# There were no submodules before, so none could have been removed
|
|
232
|
+
return [] if `git ls-files .gitmodules`.empty?
|
|
233
|
+
|
|
234
|
+
previous = submodules(ref: 'HEAD')
|
|
235
|
+
current = submodules
|
|
236
|
+
|
|
237
|
+
previous - current
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Returns the current set of registered submodules.
|
|
241
|
+
#
|
|
242
|
+
# @param options [Hash]
|
|
243
|
+
# @return [Array<Overcommit::GitRepo::Submodule>]
|
|
244
|
+
def submodules(options = {})
|
|
245
|
+
ref = options[:ref]
|
|
246
|
+
|
|
247
|
+
modules = []
|
|
248
|
+
IniParse.parse(`git show #{ref}:.gitmodules 2> #{File::NULL}`).each do |section|
|
|
249
|
+
# git < 1.8.5 does not update the .gitmodules file with submodule
|
|
250
|
+
# changes, so when we are looking at the current state of the work tree,
|
|
251
|
+
# we need to check if the submodule actually exists via another method,
|
|
252
|
+
# since the .gitmodules file we parsed does not represent reality.
|
|
253
|
+
if ref.nil? && GIT_VERSION < '1.8.5'
|
|
254
|
+
result = Overcommit::Utils.execute(%W[
|
|
255
|
+
git submodule status #{section['path']}
|
|
256
|
+
])
|
|
257
|
+
next unless result.success?
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
modules << Submodule.new(section['path'], section['url'])
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
modules
|
|
264
|
+
rescue IniParse::IniParseError => ex
|
|
265
|
+
raise Overcommit::Exceptions::GitSubmoduleError,
|
|
266
|
+
"Unable to read submodule information from #{ref}:.gitmodules file: #{ex.message}"
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Returns the names of all branches containing the given commit.
|
|
270
|
+
#
|
|
271
|
+
# @param commit_ref [String] git tree ref that resolves to a commit
|
|
272
|
+
# @return [Array<String>] list of branches containing the given commit
|
|
273
|
+
def branches_containing_commit(commit_ref)
|
|
274
|
+
`git branch --column=dense --contains #{commit_ref}`.
|
|
275
|
+
sub(/\((HEAD )?detached (from|at) .*?\)/, ''). # ignore detached HEAD
|
|
276
|
+
split(/\s+/).
|
|
277
|
+
reject { |s| s.empty? || s == '*' }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Returns the name of the currently checked out branch.
|
|
281
|
+
# @return [String]
|
|
282
|
+
def current_branch
|
|
283
|
+
`git symbolic-ref --short -q HEAD`.chomp
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|