overcommit-jeygeethanmedia 0.53.1.2 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/bin/overcommit +6 -5
  3. data/config/default.yml +37 -5
  4. data/lib/overcommit/cli.rb +14 -13
  5. data/lib/overcommit/command_splitter.rb +2 -0
  6. data/lib/overcommit/configuration.rb +1 -1
  7. data/lib/overcommit/configuration_loader.rb +11 -8
  8. data/lib/overcommit/exceptions.rb +19 -16
  9. data/lib/overcommit/git_config.rb +1 -0
  10. data/lib/overcommit/git_repo.rb +14 -13
  11. data/lib/overcommit/hook/commit_msg/base.rb +1 -1
  12. data/lib/overcommit/hook/commit_msg/spell_check.rb +1 -1
  13. data/lib/overcommit/hook/commit_msg/text_width.rb +1 -1
  14. data/lib/overcommit/hook/post_checkout/base.rb +1 -0
  15. data/lib/overcommit/hook/post_commit/git_guilt.rb +2 -1
  16. data/lib/overcommit/hook/pre_commit/author_name.rb +2 -2
  17. data/lib/overcommit/hook/pre_commit/bundle_audit.rb +1 -1
  18. data/lib/overcommit/hook/pre_commit/chamber_compare.rb +5 -5
  19. data/lib/overcommit/hook/pre_commit/chamber_security.rb +1 -0
  20. data/lib/overcommit/hook/pre_commit/coffee_lint.rb +1 -1
  21. data/lib/overcommit/hook/pre_commit/css_lint.rb +1 -1
  22. data/lib/overcommit/hook/pre_commit/dart_analyzer.rb +22 -0
  23. data/lib/overcommit/hook/pre_commit/erb_lint.rb +20 -0
  24. data/lib/overcommit/hook/pre_commit/es_lint.rb +3 -6
  25. data/lib/overcommit/hook/pre_commit/fasterer.rb +1 -1
  26. data/lib/overcommit/hook/pre_commit/foodcritic.rb +3 -1
  27. data/lib/overcommit/hook/pre_commit/hlint.rb +1 -1
  28. data/lib/overcommit/hook/pre_commit/html_tidy.rb +1 -1
  29. data/lib/overcommit/hook/pre_commit/java_checkstyle.rb +1 -1
  30. data/lib/overcommit/hook/pre_commit/js_lint.rb +1 -1
  31. data/lib/overcommit/hook/pre_commit/jsl.rb +1 -1
  32. data/lib/overcommit/hook/pre_commit/kt_lint.rb +1 -1
  33. data/lib/overcommit/hook/pre_commit/license_finder.rb +1 -0
  34. data/lib/overcommit/hook/pre_commit/line_endings.rb +3 -2
  35. data/lib/overcommit/hook/pre_commit/nginx_test.rb +1 -1
  36. data/lib/overcommit/hook/pre_commit/php_cs.rb +1 -1
  37. data/lib/overcommit/hook/pre_commit/php_cs_fixer.rb +1 -1
  38. data/lib/overcommit/hook/pre_commit/php_lint.rb +3 -3
  39. data/lib/overcommit/hook/pre_commit/php_stan.rb +1 -1
  40. data/lib/overcommit/hook/pre_commit/puppet_lint.rb +1 -1
  41. data/lib/overcommit/hook/pre_commit/puppet_metadata_json_lint.rb +1 -1
  42. data/lib/overcommit/hook/pre_commit/pyflakes.rb +1 -1
  43. data/lib/overcommit/hook/pre_commit/pylint.rb +1 -1
  44. data/lib/overcommit/hook/pre_commit/python_flake8.rb +1 -1
  45. data/lib/overcommit/hook/pre_commit/rails_best_practices.rb +1 -1
  46. data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +2 -2
  47. data/lib/overcommit/hook/pre_commit/rst_lint.rb +1 -1
  48. data/lib/overcommit/hook/pre_commit/scalariform.rb +1 -1
  49. data/lib/overcommit/hook/pre_commit/scalastyle.rb +1 -1
  50. data/lib/overcommit/hook/pre_commit/scss_lint.rb +3 -3
  51. data/lib/overcommit/hook/pre_commit/semi_standard.rb +1 -1
  52. data/lib/overcommit/hook/pre_commit/sqlint.rb +1 -1
  53. data/lib/overcommit/hook/pre_commit/standard.rb +1 -1
  54. data/lib/overcommit/hook/pre_commit/stylelint.rb +2 -1
  55. data/lib/overcommit/hook/pre_commit/swift_lint.rb +1 -1
  56. data/lib/overcommit/hook/pre_commit/ts_lint.rb +4 -4
  57. data/lib/overcommit/hook/pre_commit/w3c_css.rb +4 -4
  58. data/lib/overcommit/hook/pre_commit/w3c_html.rb +4 -4
  59. data/lib/overcommit/hook/pre_commit/xml_lint.rb +1 -1
  60. data/lib/overcommit/hook/pre_commit/yaml_lint.rb +25 -4
  61. data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +7 -3
  62. data/lib/overcommit/hook/pre_commit/yard_coverage.rb +0 -1
  63. data/lib/overcommit/hook/pre_push/cargo_test.rb +1 -0
  64. data/lib/overcommit/hook/pre_push/flutter_test.rb +16 -0
  65. data/lib/overcommit/hook/pre_push/pub_test.rb +16 -0
  66. data/lib/overcommit/hook/prepare_commit_msg/base.rb +1 -0
  67. data/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb +38 -4
  68. data/lib/overcommit/hook/shared/bower_install.rb +1 -0
  69. data/lib/overcommit/hook/shared/bundle_install.rb +1 -0
  70. data/lib/overcommit/hook/shared/composer_install.rb +1 -0
  71. data/lib/overcommit/hook/shared/npm_install.rb +1 -0
  72. data/lib/overcommit/hook/shared/pronto.rb +7 -3
  73. data/lib/overcommit/hook/shared/yarn_install.rb +1 -0
  74. data/lib/overcommit/hook_context/commit_msg.rb +7 -0
  75. data/lib/overcommit/hook_context/helpers/file_modifications.rb +79 -0
  76. data/lib/overcommit/hook_context/helpers/stash_unstaged_changes.rb +144 -0
  77. data/lib/overcommit/hook_context/post_commit.rb +1 -0
  78. data/lib/overcommit/hook_context/pre_commit.rb +5 -199
  79. data/lib/overcommit/hook_context/pre_push.rb +1 -0
  80. data/lib/overcommit/hook_context/run_all.rb +1 -0
  81. data/lib/overcommit/hook_context.rb +3 -3
  82. data/lib/overcommit/hook_loader/base.rb +3 -3
  83. data/lib/overcommit/hook_loader/plugin_hook_loader.rb +3 -3
  84. data/lib/overcommit/hook_runner.rb +8 -7
  85. data/lib/overcommit/hook_signer.rb +1 -0
  86. data/lib/overcommit/installer.rb +2 -1
  87. data/lib/overcommit/subprocess.rb +24 -2
  88. data/lib/overcommit/utils/messages_utils.rb +1 -0
  89. data/lib/overcommit/version.rb +1 -1
  90. data/libexec/index-tags +6 -4
  91. data/template-dir/hooks/commit-msg +27 -20
  92. data/template-dir/hooks/overcommit-hook +27 -20
  93. data/template-dir/hooks/post-checkout +27 -20
  94. data/template-dir/hooks/post-commit +27 -20
  95. data/template-dir/hooks/post-merge +27 -20
  96. data/template-dir/hooks/post-rewrite +27 -20
  97. data/template-dir/hooks/pre-commit +27 -20
  98. data/template-dir/hooks/pre-push +27 -20
  99. data/template-dir/hooks/pre-rebase +27 -20
  100. data/template-dir/hooks/prepare-commit-msg +27 -20
  101. metadata +27 -7
@@ -1,8 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'pre_commit'
4
+ require_relative 'helpers/stash_unstaged_changes'
5
+ require_relative 'helpers/file_modifications'
6
+
3
7
  module Overcommit::HookContext
4
8
  # Contains helpers related to contextual information used by commit-msg hooks.
5
9
  class CommitMsg < Base
10
+ include Overcommit::HookContext::Helpers::StashUnstagedChanges
11
+ include Overcommit::HookContext::Helpers::FileModifications
12
+
6
13
  def empty_message?
7
14
  commit_message.strip.empty?
8
15
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Overcommit::HookContext
4
+ module Helpers
5
+ # This module contains methods for determining what files were changed and on what unique line
6
+ # numbers did the change occur.
7
+ module FileModifications
8
+ # Returns whether this hook run was triggered by `git commit --amend`
9
+ def amendment?
10
+ return @amendment unless @amendment.nil?
11
+
12
+ cmd = Overcommit::Utils.parent_command
13
+ return unless cmd
14
+
15
+ amend_pattern = 'commit(\s.*)?\s--amend(\s|$)'
16
+
17
+ # Since the ps command can return invalid byte sequences for commands
18
+ # containing unicode characters, we replace the offending characters,
19
+ # since the pattern we're looking for will consist of ASCII characters
20
+ unless cmd.valid_encoding?
21
+ cmd = Overcommit::Utils.
22
+ parent_command.
23
+ encode('UTF-16be', invalid: :replace, replace: '?').
24
+ encode('UTF-8')
25
+ end
26
+
27
+ return @amendment if
28
+ # True if the command is a commit with the --amend flag
29
+ @amendment = !(/\s#{amend_pattern}/ =~ cmd).nil?
30
+
31
+ # Check for git aliases that call `commit --amend`
32
+ `git config --get-regexp "^alias\\." "#{amend_pattern}"`.
33
+ scan(/alias\.([-\w]+)/). # Extract the alias
34
+ each do |match|
35
+ return @amendment if
36
+ # True if the command uses a git alias for `commit --amend`
37
+ @amendment = !(/git(\.exe)?\s+#{match[0]}/ =~ cmd).nil?
38
+ end
39
+
40
+ @amendment
41
+ end
42
+
43
+ # Get a list of added, copied, or modified files that have been staged.
44
+ # Renames and deletions are ignored, since there should be nothing to check.
45
+ def modified_files
46
+ unless @modified_files
47
+ currently_staged = Overcommit::GitRepo.modified_files(staged: true)
48
+ @modified_files = currently_staged
49
+
50
+ # Include files modified in last commit if amending
51
+ if amendment?
52
+ subcmd = 'show --format=%n'
53
+ previously_modified = Overcommit::GitRepo.modified_files(subcmd: subcmd)
54
+ @modified_files |= filter_modified_files(previously_modified)
55
+ end
56
+ end
57
+ @modified_files
58
+ end
59
+
60
+ # Returns the set of line numbers corresponding to the lines that were
61
+ # changed in a specified file.
62
+ def modified_lines_in_file(file)
63
+ @modified_lines ||= {}
64
+ unless @modified_lines[file]
65
+ @modified_lines[file] =
66
+ Overcommit::GitRepo.extract_modified_lines(file, staged: true)
67
+
68
+ # Include lines modified in last commit if amending
69
+ if amendment?
70
+ subcmd = 'show --format=%n'
71
+ @modified_lines[file] +=
72
+ Overcommit::GitRepo.extract_modified_lines(file, subcmd: subcmd)
73
+ end
74
+ end
75
+ @modified_lines[file]
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Overcommit::HookContext
4
+ module Helpers
5
+ # This module contains behavior for stashing unstaged changes before hooks are ran and restoring
6
+ # them afterwards
7
+ module StashUnstagedChanges
8
+ # Stash unstaged contents of files so hooks don't see changes that aren't
9
+ # about to be committed.
10
+ def setup_environment
11
+ store_modified_times
12
+ Overcommit::GitRepo.store_merge_state
13
+ Overcommit::GitRepo.store_cherry_pick_state
14
+
15
+ # Don't attempt to stash changes if all changes are staged, as this
16
+ # prevents us from modifying files at all, which plays better with
17
+ # editors/tools which watch for file changes.
18
+ if !initial_commit? && unstaged_changes?
19
+ stash_changes
20
+
21
+ # While running hooks make it appear as if nothing changed
22
+ restore_modified_times
23
+ end
24
+ end
25
+
26
+ # Returns whether the current git branch is empty (has no commits).
27
+ def initial_commit?
28
+ return @initial_commit unless @initial_commit.nil?
29
+
30
+ @initial_commit = Overcommit::GitRepo.initial_commit?
31
+ end
32
+
33
+ # Restore unstaged changes and reset file modification times so it appears
34
+ # as if nothing ever changed.
35
+ #
36
+ # We want to restore the modification times for each of the files after
37
+ # every step to ensure as little time as possible has passed while the
38
+ # modification time on the file was newer. This helps us play more nicely
39
+ # with file watchers.
40
+ def cleanup_environment
41
+ if @changes_stashed
42
+ clear_working_tree
43
+ restore_working_tree
44
+ restore_modified_times
45
+ end
46
+
47
+ Overcommit::GitRepo.restore_merge_state
48
+ Overcommit::GitRepo.restore_cherry_pick_state
49
+ end
50
+
51
+ private
52
+
53
+ # Stores the modification times for all modified files to make it appear like
54
+ # they never changed.
55
+ #
56
+ # This prevents (some) editors from complaining about files changing when we
57
+ # stash changes before running the hooks.
58
+ def store_modified_times
59
+ @modified_times = {}
60
+
61
+ staged_files = modified_files
62
+ unstaged_files = Overcommit::GitRepo.modified_files(staged: false)
63
+
64
+ (staged_files + unstaged_files).each do |file|
65
+ next if Overcommit::Utils.broken_symlink?(file)
66
+ next unless File.exist?(file) # Ignore renamed files (old file no longer exists)
67
+
68
+ @modified_times[file] = File.mtime(file)
69
+ end
70
+ end
71
+
72
+ # Returns whether there are any changes to tracked files which have not yet
73
+ # been staged.
74
+ def unstaged_changes?
75
+ result = Overcommit::Utils.execute(%w[git --no-pager diff --quiet])
76
+ !result.success?
77
+ end
78
+
79
+ def stash_changes
80
+ @stash_attempted = true
81
+
82
+ stash_message = "Overcommit: Stash of repo state before hook run at #{Time.now}"
83
+ result = Overcommit::Utils.with_environment('GIT_LITERAL_PATHSPECS' => '0') do
84
+ Overcommit::Utils.execute(
85
+ %w[git -c commit.gpgsign=false stash save --keep-index --quiet] + [stash_message]
86
+ )
87
+ end
88
+
89
+ unless result.success?
90
+ # Failure to stash in this case is likely due to a configuration
91
+ # issue (e.g. author/email not set or GPG signing key incorrect)
92
+ raise Overcommit::Exceptions::HookSetupFailed,
93
+ "Unable to setup environment for #{hook_script_name} hook run:" \
94
+ "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
95
+ end
96
+
97
+ @changes_stashed = `git stash list -1`.include?(stash_message)
98
+ end
99
+
100
+ # Restores the file modification times for all modified files to make it
101
+ # appear like they never changed.
102
+ def restore_modified_times
103
+ @modified_times.each do |file, time|
104
+ next if Overcommit::Utils.broken_symlink?(file)
105
+ next unless File.exist?(file)
106
+
107
+ File.utime(time, time, file)
108
+ end
109
+ end
110
+
111
+ # Clears the working tree so that the stash can be applied.
112
+ def clear_working_tree
113
+ removed_submodules = Overcommit::GitRepo.staged_submodule_removals
114
+
115
+ result = Overcommit::Utils.execute(%w[git reset --hard])
116
+ unless result.success?
117
+ raise Overcommit::Exceptions::HookCleanupFailed,
118
+ "Unable to cleanup working tree after #{hook_script_name} hooks run:" \
119
+ "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
120
+ end
121
+
122
+ # Hard-resetting a staged submodule removal results in the index being
123
+ # reset but the submodule being restored as an empty directory. This empty
124
+ # directory prevents us from stashing on a subsequent run if a hook fails.
125
+ #
126
+ # Work around this by removing these empty submodule directories as there
127
+ # doesn't appear any reason to keep them around.
128
+ removed_submodules.each do |submodule|
129
+ FileUtils.rmdir(submodule.path)
130
+ end
131
+ end
132
+
133
+ # Applies the stash to the working tree to restore the user's state.
134
+ def restore_working_tree
135
+ result = Overcommit::Utils.execute(%w[git stash pop --index])
136
+ unless result.success?
137
+ raise Overcommit::Exceptions::HookCleanupFailed,
138
+ "Unable to restore working tree after #{hook_script_name} hooks run:" \
139
+ "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -27,6 +27,7 @@ module Overcommit::HookContext
27
27
  # @return [true,false]
28
28
  def initial_commit?
29
29
  return @initial_commit unless @initial_commit.nil?
30
+
30
31
  @initial_commit = !Overcommit::Utils.execute(%w[git rev-parse HEAD~]).success?
31
32
  end
32
33
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'fileutils'
4
4
  require 'set'
5
+ require_relative 'helpers/stash_unstaged_changes'
6
+ require_relative 'helpers/file_modifications'
5
7
 
6
8
  module Overcommit::HookContext
7
9
  # Contains helpers related to contextual information used by pre-commit hooks.
@@ -9,204 +11,8 @@ module Overcommit::HookContext
9
11
  # This includes staged files, which lines of those files have been modified,
10
12
  # etc. It is also responsible for saving/restoring the state of the repo so
11
13
  # hooks only inspect staged changes.
12
- class PreCommit < Base # rubocop:disable ClassLength
13
- # Returns whether this hook run was triggered by `git commit --amend`
14
- def amendment?
15
- return @amendment unless @amendment.nil?
16
-
17
- cmd = Overcommit::Utils.parent_command
18
- return unless cmd
19
- amend_pattern = 'commit(\s.*)?\s--amend(\s|$)'
20
-
21
- # Since the ps command can return invalid byte sequences for commands
22
- # containing unicode characters, we replace the offending characters,
23
- # since the pattern we're looking for will consist of ASCII characters
24
- unless cmd.valid_encoding?
25
- cmd = Overcommit::Utils.parent_command.encode('UTF-16be', invalid: :replace, replace: '?').
26
- encode('UTF-8')
27
- end
28
-
29
- return @amendment if
30
- # True if the command is a commit with the --amend flag
31
- @amendment = !(/\s#{amend_pattern}/ =~ cmd).nil?
32
-
33
- # Check for git aliases that call `commit --amend`
34
- `git config --get-regexp "^alias\\." "#{amend_pattern}"`.
35
- scan(/alias\.([-\w]+)/). # Extract the alias
36
- each do |match|
37
- return @amendment if
38
- # True if the command uses a git alias for `commit --amend`
39
- @amendment = !(/git(\.exe)?\s+#{match[0]}/ =~ cmd).nil?
40
- end
41
-
42
- @amendment
43
- end
44
-
45
- # Stash unstaged contents of files so hooks don't see changes that aren't
46
- # about to be committed.
47
- def setup_environment
48
- store_modified_times
49
- Overcommit::GitRepo.store_merge_state
50
- Overcommit::GitRepo.store_cherry_pick_state
51
-
52
- # Don't attempt to stash changes if all changes are staged, as this
53
- # prevents us from modifying files at all, which plays better with
54
- # editors/tools which watch for file changes.
55
- if !initial_commit? && unstaged_changes?
56
- stash_changes
57
-
58
- # While running hooks make it appear as if nothing changed
59
- restore_modified_times
60
- end
61
- end
62
-
63
- # Restore unstaged changes and reset file modification times so it appears
64
- # as if nothing ever changed.
65
- #
66
- # We want to restore the modification times for each of the files after
67
- # every step to ensure as little time as possible has passed while the
68
- # modification time on the file was newer. This helps us play more nicely
69
- # with file watchers.
70
- def cleanup_environment
71
- if @changes_stashed
72
- clear_working_tree
73
- restore_working_tree
74
- restore_modified_times
75
- end
76
-
77
- Overcommit::GitRepo.restore_merge_state
78
- Overcommit::GitRepo.restore_cherry_pick_state
79
- end
80
-
81
- # Get a list of added, copied, or modified files that have been staged.
82
- # Renames and deletions are ignored, since there should be nothing to check.
83
- def modified_files
84
- unless @modified_files
85
- currently_staged = Overcommit::GitRepo.modified_files(staged: true)
86
- @modified_files = currently_staged
87
-
88
- # Include files modified in last commit if amending
89
- if amendment?
90
- subcmd = 'show --format=%n'
91
- previously_modified = Overcommit::GitRepo.modified_files(subcmd: subcmd)
92
- @modified_files |= filter_modified_files(previously_modified)
93
- end
94
- end
95
- @modified_files
96
- end
97
-
98
- # Returns the set of line numbers corresponding to the lines that were
99
- # changed in a specified file.
100
- def modified_lines_in_file(file)
101
- @modified_lines ||= {}
102
- unless @modified_lines[file]
103
- @modified_lines[file] =
104
- Overcommit::GitRepo.extract_modified_lines(file, staged: true)
105
-
106
- # Include lines modified in last commit if amending
107
- if amendment?
108
- subcmd = 'show --format=%n'
109
- @modified_lines[file] +=
110
- Overcommit::GitRepo.extract_modified_lines(file, subcmd: subcmd)
111
- end
112
- end
113
- @modified_lines[file]
114
- end
115
-
116
- # Returns whether the current git branch is empty (has no commits).
117
- def initial_commit?
118
- return @initial_commit unless @initial_commit.nil?
119
- @initial_commit = Overcommit::GitRepo.initial_commit?
120
- end
121
-
122
- private
123
-
124
- def stash_changes
125
- @stash_attempted = true
126
-
127
- stash_message = "Overcommit: Stash of repo state before hook run at #{Time.now}"
128
- result = Overcommit::Utils.with_environment('GIT_LITERAL_PATHSPECS' => '0') do
129
- Overcommit::Utils.execute(
130
- %w[git -c commit.gpgsign=false stash save --keep-index --quiet] + [stash_message]
131
- )
132
- end
133
-
134
- unless result.success?
135
- # Failure to stash in this case is likely due to a configuration
136
- # issue (e.g. author/email not set or GPG signing key incorrect)
137
- raise Overcommit::Exceptions::HookSetupFailed,
138
- "Unable to setup environment for #{hook_script_name} hook run:" \
139
- "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
140
- end
141
-
142
- @changes_stashed = `git stash list -1`.include?(stash_message)
143
- end
144
-
145
- # Clears the working tree so that the stash can be applied.
146
- def clear_working_tree
147
- removed_submodules = Overcommit::GitRepo.staged_submodule_removals
148
-
149
- result = Overcommit::Utils.execute(%w[git reset --hard])
150
- unless result.success?
151
- raise Overcommit::Exceptions::HookCleanupFailed,
152
- "Unable to cleanup working tree after #{hook_script_name} hooks run:" \
153
- "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
154
- end
155
-
156
- # Hard-resetting a staged submodule removal results in the index being
157
- # reset but the submodule being restored as an empty directory. This empty
158
- # directory prevents us from stashing on a subsequent run if a hook fails.
159
- #
160
- # Work around this by removing these empty submodule directories as there
161
- # doesn't appear any reason to keep them around.
162
- removed_submodules.each do |submodule|
163
- FileUtils.rmdir(submodule.path)
164
- end
165
- end
166
-
167
- # Applies the stash to the working tree to restore the user's state.
168
- def restore_working_tree
169
- result = Overcommit::Utils.execute(%w[git stash pop --index --quiet])
170
- unless result.success?
171
- raise Overcommit::Exceptions::HookCleanupFailed,
172
- "Unable to restore working tree after #{hook_script_name} hooks run:" \
173
- "\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
174
- end
175
- end
176
-
177
- # Returns whether there are any changes to tracked files which have not yet
178
- # been staged.
179
- def unstaged_changes?
180
- result = Overcommit::Utils.execute(%w[git --no-pager diff --quiet])
181
- !result.success?
182
- end
183
-
184
- # Stores the modification times for all modified files to make it appear like
185
- # they never changed.
186
- #
187
- # This prevents (some) editors from complaining about files changing when we
188
- # stash changes before running the hooks.
189
- def store_modified_times
190
- @modified_times = {}
191
-
192
- staged_files = modified_files
193
- unstaged_files = Overcommit::GitRepo.modified_files(staged: false)
194
-
195
- (staged_files + unstaged_files).each do |file|
196
- next if Overcommit::Utils.broken_symlink?(file)
197
- next unless File.exist?(file) # Ignore renamed files (old file no longer exists)
198
- @modified_times[file] = File.mtime(file)
199
- end
200
- end
201
-
202
- # Restores the file modification times for all modified files to make it
203
- # appear like they never changed.
204
- def restore_modified_times
205
- @modified_times.each do |file, time|
206
- next if Overcommit::Utils.broken_symlink?(file)
207
- next unless File.exist?(file)
208
- File.utime(time, time, file)
209
- end
210
- end
14
+ class PreCommit < Base
15
+ include Overcommit::HookContext::Helpers::StashUnstagedChanges
16
+ include Overcommit::HookContext::Helpers::FileModifications
211
17
  end
212
18
  end
@@ -76,6 +76,7 @@ module Overcommit::HookContext
76
76
 
77
77
  def overwritten_commits
78
78
  return @overwritten_commits if defined? @overwritten_commits
79
+
79
80
  result = Overcommit::Subprocess.spawn(%W[git rev-list #{remote_sha1} ^#{local_sha1}])
80
81
  if result.success?
81
82
  result.stdout.split("\n")
@@ -36,6 +36,7 @@ module Overcommit::HookContext
36
36
 
37
37
  def initial_commit?
38
38
  return @initial_commit unless @initial_commit.nil?
39
+
39
40
  @initial_commit = Overcommit::GitRepo.initial_commit?
40
41
  end
41
42
 
@@ -9,11 +9,11 @@ module Overcommit::HookContext
9
9
  require "overcommit/hook_context/#{underscored_hook_type}"
10
10
 
11
11
  Overcommit::HookContext.const_get(hook_type_class).new(config, args, input)
12
- rescue LoadError, NameError => error
12
+ rescue LoadError, NameError => e
13
13
  # Could happen when a symlink was created for a hook type Overcommit does
14
14
  # not yet support.
15
15
  raise Overcommit::Exceptions::HookContextLoadError,
16
- "Unable to load '#{hook_type}' hook context: '#{error}'",
17
- error.backtrace
16
+ "Unable to load '#{hook_type}' hook context: '#{e}'",
17
+ e.backtrace
18
18
  end
19
19
  end
@@ -38,10 +38,10 @@ module Overcommit::HookLoader
38
38
  Overcommit::Hook.const_get(@context.hook_class_name).
39
39
  const_get(hook_name).
40
40
  new(@config, @context)
41
- rescue LoadError, NameError => error
41
+ rescue LoadError, NameError => e
42
42
  raise Overcommit::Exceptions::HookLoadError,
43
- "Unable to load hook '#{hook_name}': #{error}",
44
- error.backtrace
43
+ "Unable to load hook '#{hook_name}': #{e}",
44
+ e.backtrace
45
45
  end
46
46
  end
47
47
  end
@@ -93,10 +93,10 @@ module Overcommit::HookLoader
93
93
  end
94
94
 
95
95
  hook_module.const_set(hook_name, hook_class).new(@config, @context)
96
- rescue LoadError, NameError => error
96
+ rescue LoadError, NameError => e
97
97
  raise Overcommit::Exceptions::HookLoadError,
98
- "Unable to load hook '#{hook_name}': #{error}",
99
- error.backtrace
98
+ "Unable to load hook '#{hook_name}': #{e}",
99
+ e.backtrace
100
100
  end
101
101
  end
102
102
  end
@@ -94,6 +94,7 @@ module Overcommit
94
94
  loop do
95
95
  hook = @lock.synchronize { @hooks_left.pop }
96
96
  break unless hook
97
+
97
98
  run_hook(hook)
98
99
  end
99
100
  end
@@ -159,12 +160,12 @@ module Overcommit
159
160
  return if should_skip?(hook)
160
161
 
161
162
  status, output = hook.run_and_transform
162
- rescue Overcommit::Exceptions::MessageProcessingError => ex
163
+ rescue Overcommit::Exceptions::MessageProcessingError => e
163
164
  status = :fail
164
- output = ex.message
165
- rescue StandardError => ex
165
+ output = e.message
166
+ rescue StandardError => e
166
167
  status = :fail
167
- output = "Hook raised unexpected error\n#{ex.message}\n#{ex.backtrace.join("\n")}"
168
+ output = "Hook raised unexpected error\n#{e.message}\n#{e.backtrace.join("\n")}"
168
169
  end
169
170
 
170
171
  @failed = true if status == :fail
@@ -202,7 +203,7 @@ module Overcommit
202
203
 
203
204
  # Load plugin hooks after so they can subclass existing hooks
204
205
  @hooks += HookLoader::PluginHookLoader.new(@config, @context, @log).load_hooks
205
- rescue LoadError => ex
206
+ rescue LoadError => e
206
207
  # Include a more helpful message that will probably save some confusion
207
208
  message = 'A load error occurred. ' +
208
209
  if @config['gemfile']
@@ -212,8 +213,8 @@ module Overcommit
212
213
  end
213
214
 
214
215
  raise Overcommit::Exceptions::HookLoadError,
215
- "#{message}\n#{ex.message}",
216
- ex.backtrace
216
+ "#{message}\n#{e.message}",
217
+ e.backtrace
217
218
  end
218
219
  end
219
220
  end
@@ -52,6 +52,7 @@ module Overcommit
52
52
 
53
53
  def signable_file?(file)
54
54
  return unless file
55
+
55
56
  sep = Overcommit::OS.windows? ? '\\' : File::SEPARATOR
56
57
  file.start_with?(".#{sep}") ||
57
58
  file.start_with?(Overcommit::Utils.repo_root)
@@ -4,7 +4,7 @@ require 'fileutils'
4
4
 
5
5
  module Overcommit
6
6
  # Manages the installation of Overcommit hooks in a git repository.
7
- class Installer # rubocop:disable ClassLength
7
+ class Installer # rubocop:disable Metrics/ClassLength
8
8
  TEMPLATE_DIRECTORY = File.join(Overcommit::HOME, 'template-dir')
9
9
  MASTER_HOOK = File.join(TEMPLATE_DIRECTORY, 'hooks', 'overcommit-hook')
10
10
 
@@ -174,6 +174,7 @@ module Overcommit
174
174
  repo_config_file = File.join(@target, Overcommit::CONFIG_FILE_NAME)
175
175
 
176
176
  return if File.exist?(repo_config_file)
177
+
177
178
  FileUtils.cp(File.join(Overcommit::HOME, 'config', 'starter.yml'), repo_config_file)
178
179
  end
179
180
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'childprocess'
4
4
  require 'tempfile'
5
+ require 'overcommit/os'
5
6
 
6
7
  module Overcommit
7
8
  # Manages execution of a child process, collecting the exit status and
@@ -38,7 +39,7 @@ module Overcommit
38
39
  if options[:input]
39
40
  begin
40
41
  process.io.stdin.puts(options[:input])
41
- rescue StandardError # rubocop:disable Lint/HandleExceptions
42
+ rescue StandardError
42
43
  # Silently ignore if the standard input stream of the spawned
43
44
  # process is closed before we get a chance to write to it. This
44
45
  # happens on JRuby a lot.
@@ -51,7 +52,7 @@ module Overcommit
51
52
  err.rewind
52
53
  out.rewind
53
54
 
54
- Result.new(process.exit_code, out.read, err.read)
55
+ Result.new(process.exit_code, to_utf8(out.read), to_utf8(err.read))
55
56
  end
56
57
 
57
58
  # Spawns a new process in the background using the given array of
@@ -83,6 +84,27 @@ module Overcommit
83
84
  %w[cmd.exe /c] + [args.join(' ')]
84
85
  end
85
86
 
87
+ # Convert string from current locale to utf-8
88
+ #
89
+ # When running commands under windows the command output is using
90
+ # current system locale (depends on system lanuage) not UTF-8
91
+ #
92
+ # @param process [String]
93
+ # @return [String]
94
+ def to_utf8(string)
95
+ # Our encoding code doesn't work on the GitHub Actions Windows
96
+ # environment for unknown reasons, so just skip it in CI.
97
+ return string if OS.windows? && ENV['GITHUB_ACTIONS']
98
+
99
+ if Encoding.locale_charmap == 'UTF-8'
100
+ return string
101
+ end
102
+
103
+ ec = Encoding::Converter.new(Encoding.locale_charmap, 'UTF-8')
104
+ # Convert encoding, alternatively simple: string.scrub will suffice
105
+ ec.convert(string)
106
+ end
107
+
86
108
  # @param process [ChildProcess]
87
109
  # @return [Array<IO>]
88
110
  def assign_output_streams(process)
@@ -52,6 +52,7 @@ module Overcommit::Utils
52
52
 
53
53
  def extract_line(match, message)
54
54
  return unless match.names.include?('line')
55
+
55
56
  Integer(match[:line])
56
57
  rescue ArgumentError, TypeError
57
58
  raise Overcommit::Exceptions::MessageProcessingError,
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module Overcommit
5
- VERSION = '0.53.1.2'
5
+ VERSION = '0.58.0'
6
6
  end