rails_git_hooks 0.7.0 → 0.7.2

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -6
  3. data/README.md +72 -115
  4. data/lib/rails_git_hooks/checks/base.rb +55 -0
  5. data/lib/rails_git_hooks/checks/commit_msg/jira_prefix.rb +31 -0
  6. data/lib/rails_git_hooks/checks/commit_msg.rb +10 -0
  7. data/lib/rails_git_hooks/checks/post_checkout/bundle_install.rb +16 -0
  8. data/lib/rails_git_hooks/checks/post_checkout/db_migrate.rb +16 -0
  9. data/lib/rails_git_hooks/checks/post_checkout.rb +11 -0
  10. data/lib/rails_git_hooks/checks/post_merge/bundle_install.rb +16 -0
  11. data/lib/rails_git_hooks/checks/post_merge/db_migrate.rb +16 -0
  12. data/lib/rails_git_hooks/checks/post_merge.rb +11 -0
  13. data/lib/rails_git_hooks/checks/pre_commit/debugger_check.rb +43 -0
  14. data/lib/rails_git_hooks/checks/pre_commit/default_branch.rb +20 -0
  15. data/lib/rails_git_hooks/checks/pre_commit/json_format_check.rb +30 -0
  16. data/lib/rails_git_hooks/checks/pre_commit/migrations_check.rb +37 -0
  17. data/lib/rails_git_hooks/checks/pre_commit/rubocop.rb +30 -0
  18. data/lib/rails_git_hooks/checks/pre_commit/whitespace_check.rb +31 -0
  19. data/lib/rails_git_hooks/checks/pre_commit/yaml_format_check.rb +31 -0
  20. data/lib/rails_git_hooks/checks/pre_commit.rb +16 -0
  21. data/lib/rails_git_hooks/checks/pre_push/run_tests.rb +24 -0
  22. data/lib/rails_git_hooks/checks/pre_push.rb +10 -0
  23. data/lib/rails_git_hooks/checks/shared/bundle_install_check.rb +28 -0
  24. data/lib/rails_git_hooks/checks/shared/db_migrate_check.rb +28 -0
  25. data/lib/rails_git_hooks/checks.rb +10 -0
  26. data/lib/rails_git_hooks/cli.rb +17 -90
  27. data/lib/rails_git_hooks/config/constants.rb +26 -0
  28. data/lib/rails_git_hooks/config/defaults.yml +190 -0
  29. data/lib/rails_git_hooks/config/defaults_loader.rb +42 -0
  30. data/lib/rails_git_hooks/core/check_definition.rb +63 -0
  31. data/lib/rails_git_hooks/core/check_result.rb +41 -0
  32. data/lib/rails_git_hooks/core/error.rb +5 -0
  33. data/lib/rails_git_hooks/install/installer.rb +79 -0
  34. data/lib/rails_git_hooks/runtime/check_registry.rb +33 -0
  35. data/lib/rails_git_hooks/runtime/dependency_checker.rb +51 -0
  36. data/lib/rails_git_hooks/runtime/file_matcher.rb +23 -0
  37. data/lib/rails_git_hooks/runtime/override_config.rb +131 -0
  38. data/lib/rails_git_hooks/runtime/policy_resolver.rb +36 -0
  39. data/lib/rails_git_hooks/runtime/repository.rb +69 -0
  40. data/lib/rails_git_hooks/runtime/runner.rb +80 -0
  41. data/lib/rails_git_hooks/runtime.rb +25 -0
  42. data/lib/rails_git_hooks/version.rb +1 -1
  43. data/lib/rails_git_hooks.rb +14 -6
  44. data/templates/hooks/commit-msg +7 -17
  45. data/templates/hooks/post-checkout +13 -0
  46. data/templates/hooks/post-merge +13 -0
  47. data/templates/hooks/pre-commit +7 -21
  48. data/templates/hooks/pre-push +7 -17
  49. metadata +41 -52
  50. data/lib/rails_git_hooks/constants.rb +0 -21
  51. data/lib/rails_git_hooks/installer.rb +0 -156
  52. data/templates/shared/commit_msg/jira_prefix.rb +0 -20
  53. data/templates/shared/pre_commit/debugger_check.rb +0 -48
  54. data/templates/shared/pre_commit/default_branch.rb +0 -9
  55. data/templates/shared/pre_commit/rubocop_check.rb +0 -24
  56. data/templates/shared/pre_commit/whitespace_check.rb +0 -25
  57. data/templates/shared/pre_push/run_tests.rb +0 -9
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class CheckResult
5
+ attr_reader :status, :messages, :reason
6
+
7
+ def initialize(status:, messages: [], reason: nil)
8
+ @status = status.to_sym
9
+ @messages = Array(messages).compact
10
+ @reason = reason&.to_sym
11
+ end
12
+
13
+ def self.pass(messages: [])
14
+ new(status: :pass, messages: messages, reason: :pass)
15
+ end
16
+
17
+ def self.warn(messages:, reason: :warning)
18
+ new(status: :warn, messages: messages, reason: reason)
19
+ end
20
+
21
+ def self.fail(messages:, reason: :failure)
22
+ new(status: :fail, messages: messages, reason: reason)
23
+ end
24
+
25
+ def with_status(status)
26
+ self.class.new(status: status, messages: messages, reason: reason)
27
+ end
28
+
29
+ def pass?
30
+ status == :pass
31
+ end
32
+
33
+ def warn?
34
+ status == :warn
35
+ end
36
+
37
+ def fail?
38
+ status == :fail
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class Error < StandardError; end
5
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module GitHooks
6
+ class Installer
7
+ def initialize(git_dir: nil)
8
+ if git_dir
9
+ @git_dir = git_dir
10
+ @repo = nil
11
+ else
12
+ @repo = Repository.new
13
+ @git_dir = @repo.git_dir
14
+ end
15
+ end
16
+
17
+ def install
18
+ target_dir = File.join(@git_dir, 'hooks')
19
+ raise GitHooks::Error, "Not a git repository or .git/hooks not found: #{@git_dir}" unless Dir.exist?(target_dir)
20
+
21
+ copy_runtime(target_dir)
22
+
23
+ hooks = hooks_enabled_in_config.select { |name| self.class.available_hook_names.include?(name) }
24
+ hooks.each_with_object([]) do |name, installed|
25
+ dest = File.join(target_dir, name)
26
+ File.write(dest, File.read(File.join(Constants::HOOKS_DIR, name)))
27
+ File.chmod(0o755, dest)
28
+ installed << name
29
+ end
30
+ end
31
+
32
+ def self.available_hook_names
33
+ Dir.children(Constants::HOOKS_DIR).select { |name| File.file?(File.join(Constants::HOOKS_DIR, name)) }
34
+ end
35
+
36
+ def available_hooks
37
+ self.class.available_hook_names
38
+ end
39
+
40
+ private
41
+
42
+ def repo_for_config
43
+ @repo_for_config ||= begin
44
+ root = File.dirname(@git_dir)
45
+ Struct.new(:root, :config_path, :local_config_path).new(
46
+ root,
47
+ File.join(root, Constants::CONFIG_FILE),
48
+ File.join(root, Constants::CONFIG_FILE_LOCAL)
49
+ )
50
+ end
51
+ end
52
+
53
+ def hooks_enabled_in_config
54
+ override_config = OverrideConfig.new(repo: repo_for_config)
55
+ effective = override_config.effective_config(CheckRegistry.all)
56
+ effective.each_with_object([]) do |(section_name, check_configs), out|
57
+ hook_name = Constants::SECTION_TO_HOOK[section_name]
58
+ next unless hook_name && self.class.available_hook_names.include?(hook_name)
59
+
60
+ out << hook_name if check_configs.values.any? { |cfg| cfg['enabled'] == true }
61
+ end.uniq
62
+ end
63
+
64
+ def copy_runtime(target_dir)
65
+ runtime_dir = File.join(target_dir, Constants::RUNTIME_DIR_NAME)
66
+ FileUtils.rm_rf(runtime_dir)
67
+ FileUtils.mkdir_p(runtime_dir)
68
+
69
+ Dir.glob(File.join(Constants::RUNTIME_SOURCE_DIR, '**', '*')).each do |src|
70
+ next unless File.file?(src)
71
+
72
+ rel = src.sub(%r{\A#{Regexp.escape(Constants::RUNTIME_SOURCE_DIR)}/}, '')
73
+ dest = File.join(runtime_dir, rel)
74
+ FileUtils.mkdir_p(File.dirname(dest))
75
+ File.write(dest, File.read(src))
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class CheckRegistry
5
+ CHECK_CLASSES = [
6
+ Checks::PreCommit::DefaultBranch,
7
+ Checks::PreCommit::DebuggerCheck,
8
+ Checks::PreCommit::YAMLFormatCheck,
9
+ Checks::PreCommit::JSONFormatCheck,
10
+ Checks::PreCommit::MigrationsCheck,
11
+ Checks::PreCommit::WhitespaceCheck,
12
+ Checks::PreCommit::RuboCop,
13
+ Checks::CommitMsg::JiraPrefix,
14
+ Checks::PrePush::RunTests,
15
+ Checks::PostCheckout::BundleInstall,
16
+ Checks::PostCheckout::DbMigrate,
17
+ Checks::PostMerge::BundleInstall,
18
+ Checks::PostMerge::DbMigrate
19
+ ].freeze
20
+
21
+ def self.all
22
+ CHECK_CLASSES.map(&:definition)
23
+ end
24
+
25
+ def self.for(hook_name)
26
+ all.select { |definition| definition.hook == hook_name.to_sym }
27
+ end
28
+
29
+ def self.find!(key)
30
+ all.find { |definition| definition.key == key } || raise(GitHooks::Error, "Unknown check: #{key}")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class DependencyChecker
5
+ def initialize(repo:)
6
+ @repo = repo
7
+ end
8
+
9
+ def check(config)
10
+ dependencies = config.fetch('dependencies', {})
11
+ missing = []
12
+
13
+ Array(dependencies['executables']).each do |name|
14
+ missing << "missing executable: #{name}" unless executable_available?(name)
15
+ end
16
+
17
+ Array(dependencies['libraries']).each do |name|
18
+ missing << "missing library: #{name}" unless library_available?(name)
19
+ end
20
+
21
+ Array(dependencies['files']).each do |name|
22
+ path = File.expand_path(name, @repo.root)
23
+ missing << "missing file: #{name}" unless File.exist?(path)
24
+ end
25
+
26
+ return CheckResult.pass if missing.empty?
27
+
28
+ hint = config['install_hint']
29
+ messages = missing.dup
30
+ messages << hint if hint && !hint.empty?
31
+ CheckResult.fail(messages: messages, reason: :missing_dependency)
32
+ end
33
+
34
+ private
35
+
36
+ def executable_available?(name)
37
+ return File.executable?(File.expand_path(name, @repo.root)) if name.include?(File::SEPARATOR)
38
+
39
+ ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).any? do |dir|
40
+ File.executable?(File.join(dir, name))
41
+ end
42
+ end
43
+
44
+ def library_available?(name)
45
+ require name
46
+ true
47
+ rescue LoadError
48
+ false
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ module FileMatcher
5
+ FLAGS = File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB
6
+
7
+ module_function
8
+
9
+ def filter(paths, include_patterns:, exclude_patterns:)
10
+ filtered = if include_patterns.empty?
11
+ paths
12
+ else
13
+ paths.select { |path| matches_any?(path, include_patterns) }
14
+ end
15
+
16
+ filtered.reject { |path| matches_any?(path, exclude_patterns) }
17
+ end
18
+
19
+ def matches_any?(path, patterns)
20
+ Array(patterns).any? { |pattern| File.fnmatch?(pattern, path, FLAGS) }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'yaml'
5
+
6
+ require_relative '../config/defaults_loader'
7
+
8
+ module GitHooks
9
+ class OverrideConfig
10
+ BOOLEAN_OPTIONS = %w[enabled quiet].freeze
11
+ POLICY_OPTIONS = %w[on_fail on_warn on_missing_dependency].freeze
12
+
13
+ def initialize(repo:)
14
+ @repo = repo
15
+ end
16
+
17
+ def load
18
+ main = load_file(@repo.config_path)
19
+ local = load_file(@repo.local_config_path)
20
+ deep_merge(main, local)
21
+ end
22
+
23
+ def config_for(definition)
24
+ base = DefaultsLoader.config_for(definition.hook_section, definition.config_name) || definition.default_config
25
+ data = load
26
+ section = data.fetch(definition.hook_section, {})
27
+ merged = deep_merge(base, section.fetch('ALL', {}))
28
+ deep_merge(merged, section.fetch(definition.config_name, {}))
29
+ end
30
+
31
+ def effective_config(registry)
32
+ registry.group_by(&:hook_section).transform_values do |definitions|
33
+ definitions.to_h { |definition| [definition.config_name, config_for(definition)] }
34
+ end
35
+ end
36
+
37
+ def set_option(definition, option, value)
38
+ data = load_file(@repo.config_path)
39
+ section = data[definition.hook_section] ||= {}
40
+ section[definition.config_name] ||= {}
41
+
42
+ normalized = normalize_value(option, value)
43
+ base = DefaultsLoader.config_for(definition.hook_section, definition.config_name) || definition.default_config
44
+ default_value = base[option]
45
+
46
+ if normalized == default_value
47
+ section[definition.config_name].delete(option)
48
+ else
49
+ section[definition.config_name][option] = normalized
50
+ end
51
+
52
+ cleanup_empty_nodes!(data, definition)
53
+ write(data)
54
+ end
55
+
56
+ def init
57
+ return if File.exist?(@repo.config_path)
58
+
59
+ File.write(@repo.config_path, <<~YAML)
60
+ # rails_git_hooks overrides
61
+ #
62
+ # Example:
63
+ # PreCommit:
64
+ # RuboCop:
65
+ # enabled: true
66
+ # on_fail: fail
67
+ YAML
68
+ end
69
+
70
+ private
71
+
72
+ def load_file(path)
73
+ return {} unless File.exist?(path)
74
+
75
+ deep_stringify(YAML.safe_load(File.read(path), aliases: true) || {})
76
+ end
77
+
78
+ def write(data)
79
+ if data.empty?
80
+ FileUtils.rm_f(@repo.config_path)
81
+ else
82
+ File.write(@repo.config_path, YAML.dump(data))
83
+ end
84
+ end
85
+
86
+ def cleanup_empty_nodes!(data, definition)
87
+ section = data.fetch(definition.hook_section, {})
88
+ section.delete(definition.config_name) if section.fetch(definition.config_name, {}).empty?
89
+ data.delete(definition.hook_section) if section.empty?
90
+ end
91
+
92
+ def normalize_value(option, value)
93
+ case option
94
+ when *BOOLEAN_OPTIONS
95
+ parse_boolean(value)
96
+ when *POLICY_OPTIONS
97
+ value.to_s
98
+ else
99
+ value
100
+ end
101
+ end
102
+
103
+ def parse_boolean(value)
104
+ return value if [true, false].include?(value)
105
+
106
+ case value.to_s
107
+ when 'true', 'yes', 'on', '1' then true
108
+ when 'false', 'no', 'off', '0' then false
109
+ else
110
+ raise GitHooks::Error, "Invalid boolean value: #{value.inspect}"
111
+ end
112
+ end
113
+
114
+ def deep_merge(base, override)
115
+ base.merge(override) do |_key, old, new|
116
+ old.is_a?(Hash) && new.is_a?(Hash) ? deep_merge(old, new) : new
117
+ end
118
+ end
119
+
120
+ def deep_stringify(value)
121
+ case value
122
+ when Hash
123
+ value.each_with_object({}) { |(key, nested), out| out[key.to_s] = deep_stringify(nested) }
124
+ when Array
125
+ value.map { |nested| deep_stringify(nested) }
126
+ else
127
+ value
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class PolicyResolver
5
+ VALID_FAIL_POLICIES = %w[fail warn pass].freeze
6
+ VALID_WARN_POLICIES = %w[warn fail pass].freeze
7
+
8
+ def resolve(result, config)
9
+ policy = policy_for(result, config)
10
+ return result if policy == result.status.to_s
11
+
12
+ result.with_status(policy.to_sym)
13
+ end
14
+
15
+ private
16
+
17
+ def policy_for(result, config)
18
+ case result.reason
19
+ when :missing_dependency
20
+ validate(config.fetch('on_missing_dependency', 'warn'), VALID_FAIL_POLICIES)
21
+ else
22
+ case result.status
23
+ when :fail then validate(config.fetch('on_fail', 'fail'), VALID_FAIL_POLICIES)
24
+ when :warn then validate(config.fetch('on_warn', 'warn'), VALID_WARN_POLICIES)
25
+ else 'pass'
26
+ end
27
+ end
28
+ end
29
+
30
+ def validate(value, valid_values)
31
+ return value if valid_values.include?(value)
32
+
33
+ raise GitHooks::Error, "Invalid policy value: #{value.inspect}"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module GitHooks
6
+ class Repository
7
+ attr_reader :root, :git_dir
8
+
9
+ def initialize(start_dir = Dir.pwd)
10
+ @root, @git_dir = resolve_paths(start_dir)
11
+ end
12
+
13
+ def config_path
14
+ File.join(root, Constants::CONFIG_FILE)
15
+ end
16
+
17
+ def local_config_path
18
+ File.join(root, Constants::CONFIG_FILE_LOCAL)
19
+ end
20
+
21
+ def hook_runtime_dir(hooks_dir)
22
+ File.join(hooks_dir, Constants::RUNTIME_DIR_NAME)
23
+ end
24
+
25
+ def git(*args)
26
+ stdout, status = Open3.capture2e('git', *args, chdir: root)
27
+ [stdout, status]
28
+ end
29
+
30
+ def git_output(*args)
31
+ stdout, status = git(*args)
32
+ raise GitHooks::Error, stdout.strip unless status.success?
33
+
34
+ stdout
35
+ end
36
+
37
+ def current_branch
38
+ git_output('rev-parse', '--abbrev-ref', 'HEAD').strip
39
+ end
40
+
41
+ def staged_files
42
+ git_output('diff', '--cached', '--name-only').split("\n").map(&:strip).reject(&:empty?)
43
+ end
44
+
45
+ def changed_files(ref1, ref2)
46
+ git_output('diff', '--name-only', ref1.to_s, ref2.to_s).split("\n").map(&:strip).reject(&:empty?)
47
+ end
48
+
49
+ private
50
+
51
+ def resolve_paths(start_dir)
52
+ dir = File.expand_path(start_dir)
53
+ loop do
54
+ git_entry = File.join(dir, '.git')
55
+ if File.directory?(git_entry)
56
+ return [dir, git_entry]
57
+ elsif File.file?(git_entry)
58
+ git_dir = File.expand_path(File.read(git_entry).strip.sub(/\Agitdir: \s*/, ''), dir)
59
+ return [dir, git_dir]
60
+ end
61
+
62
+ parent = File.dirname(dir)
63
+ raise GitHooks::Error, 'Not inside a git repository' if parent == dir
64
+
65
+ dir = parent
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHooks
4
+ class Runner
5
+ def initialize(repo:, hook_name:, argv:, stdin:)
6
+ @repo = repo
7
+ @hook_name = hook_name.to_sym
8
+ @argv = argv
9
+ @stdin = stdin
10
+ @overrides = OverrideConfig.new(repo: repo)
11
+ @dependencies = DependencyChecker.new(repo: repo)
12
+ @policy = PolicyResolver.new
13
+ end
14
+
15
+ def run
16
+ failed = false
17
+
18
+ CheckRegistry.for(@hook_name).each do |definition|
19
+ config = @overrides.config_for(definition)
20
+ next unless config['enabled']
21
+
22
+ context = {
23
+ repo: @repo,
24
+ argv: @argv,
25
+ stdin: @stdin,
26
+ applicable_files: applicable_files_for(config)
27
+ }
28
+
29
+ raw_result = @dependencies.check(config)
30
+ raw_result = definition.klass.new(config: config, context: context).run if raw_result.pass?
31
+ final_result = @policy.resolve(raw_result, config)
32
+
33
+ print_result(definition, final_result, quiet: config['quiet'])
34
+ failed ||= final_result.fail?
35
+ end
36
+
37
+ failed ? 1 : 0
38
+ end
39
+
40
+ private
41
+
42
+ def applicable_files_for(config)
43
+ return [] unless config['file_based']
44
+
45
+ FileMatcher.filter(
46
+ modified_files,
47
+ include_patterns: Array(config['include']),
48
+ exclude_patterns: Array(config['exclude'])
49
+ )
50
+ end
51
+
52
+ def modified_files
53
+ @modified_files ||= case @hook_name
54
+ when :pre_commit then @repo.staged_files
55
+ when :post_checkout
56
+ argv[2] == '1' ? @repo.changed_files(argv[0], argv[1]) : []
57
+ when :post_merge
58
+ @repo.changed_files('ORIG_HEAD', 'HEAD')
59
+ else []
60
+ end
61
+ end
62
+
63
+ def print_result(definition, result, quiet:)
64
+ return if result.pass? && quiet
65
+ return if result.pass? && result.messages.empty?
66
+
67
+ case result.status
68
+ when :warn
69
+ warn ''
70
+ warn "Warning (#{definition.config_name}):"
71
+ when :fail
72
+ warn ''
73
+ warn "Commit rejected (#{definition.config_name}):"
74
+ end
75
+
76
+ result.messages.each { |message| warn " #{message}" } unless result.pass?
77
+ warn '' unless result.pass?
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'config/constants'
4
+ require_relative 'core/error'
5
+ require_relative 'core/check_result'
6
+ require_relative 'core/check_definition'
7
+ require_relative 'runtime/repository'
8
+ require_relative 'runtime/file_matcher'
9
+ require_relative 'runtime/dependency_checker'
10
+ require_relative 'runtime/policy_resolver'
11
+ require_relative 'runtime/override_config'
12
+ require_relative 'checks'
13
+ require_relative 'runtime/check_registry'
14
+ require_relative 'runtime/runner'
15
+
16
+ module GitHooks
17
+ module Runtime
18
+ module_function
19
+
20
+ def execute(hook_name, argv: [], stdin: '')
21
+ repo = Repository.new
22
+ Runner.new(repo: repo, hook_name: hook_name, argv: argv, stdin: stdin).run
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitHooks
4
- VERSION = '0.7.0'
4
+ VERSION = '0.7.2'
5
5
  end
@@ -1,9 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'rails_git_hooks/version'
4
- require_relative 'rails_git_hooks/constants'
5
- require_relative 'rails_git_hooks/installer'
6
-
7
- module GitHooks
8
- class Error < StandardError; end
9
- end
4
+ require_relative 'rails_git_hooks/core/error'
5
+ require_relative 'rails_git_hooks/config/constants'
6
+ require_relative 'rails_git_hooks/core/check_result'
7
+ require_relative 'rails_git_hooks/core/check_definition'
8
+ require_relative 'rails_git_hooks/runtime/repository'
9
+ require_relative 'rails_git_hooks/runtime/file_matcher'
10
+ require_relative 'rails_git_hooks/runtime/dependency_checker'
11
+ require_relative 'rails_git_hooks/runtime/policy_resolver'
12
+ require_relative 'rails_git_hooks/runtime/override_config'
13
+ require_relative 'rails_git_hooks/checks'
14
+ require_relative 'rails_git_hooks/runtime/check_registry'
15
+ require_relative 'rails_git_hooks/runtime/runner'
16
+ require_relative 'rails_git_hooks/install/installer'
17
+ require_relative 'rails_git_hooks/runtime'
@@ -1,23 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- #
5
- # Git commit-msg hook: prepends [TICKET] when branch contains a Jira-style ticket.
6
- # Logic in templates/shared/commit_msg/.
7
-
8
- # Bootstrap: resolve .git dir and skip if hook is disabled
9
- repo_root = Dir.pwd
10
- git_dir = File.join(repo_root, '.git')
11
- git_dir = File.expand_path(File.read(git_dir).strip.sub(/\Agitdir: \s*/, ''), repo_root) if File.file?(git_dir)
12
- disabled_file = File.join(git_dir, 'rails_git_hooks_disabled')
13
- if File.exist?(disabled_file)
14
- disabled = File.read(disabled_file).split("\n").map(&:strip)
15
- exit 0 if disabled.include?('*') || disabled.include?('commit-msg')
4
+ hooks_dir = File.dirname(File.expand_path(__FILE__))
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError, StandardError
8
+ nil
16
9
  end
17
10
 
18
- module RailsGitHooks
19
- end
20
- RailsGitHooks.const_set(:GIT_DIR, git_dir.freeze)
21
- hooks_dir = File.dirname(File.expand_path(__FILE__))
11
+ require File.join(hooks_dir, 'rails_git_hooks', 'runtime')
22
12
 
23
- load File.join(hooks_dir, 'commit_msg', 'jira_prefix.rb')
13
+ exit GitHooks::Runtime.execute(:commit_msg, argv: ARGV, stdin: $stdin.read)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ hooks_dir = File.dirname(File.expand_path(__FILE__))
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError, StandardError
8
+ nil
9
+ end
10
+
11
+ require File.join(hooks_dir, 'rails_git_hooks', 'runtime')
12
+
13
+ exit GitHooks::Runtime.execute(:post_checkout, argv: ARGV, stdin: $stdin.read)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ hooks_dir = File.dirname(File.expand_path(__FILE__))
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError, StandardError
8
+ nil
9
+ end
10
+
11
+ require File.join(hooks_dir, 'rails_git_hooks', 'runtime')
12
+
13
+ exit GitHooks::Runtime.execute(:post_merge, argv: ARGV, stdin: $stdin.read)