overcommit 0.55.0 → 0.56.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +7 -2
- data/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb +38 -4
- data/lib/overcommit/hook_context/commit_msg.rb +7 -0
- data/lib/overcommit/hook_context/helpers/file_modifications.rb +78 -0
- data/lib/overcommit/hook_context/helpers/stash_unstaged_changes.rb +141 -0
- data/lib/overcommit/hook_context/pre_commit.rb +5 -199
- data/lib/overcommit/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6ecbb7e4b390f8d17c9058da38464b73f7cec50a87e494430e9c15a9c40ecff
|
4
|
+
data.tar.gz: f90974df2fe0b918ff8711a228608ad1b312a730abd9ad7c45b02ee512daa496
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8b55f73d42ca1791bbd6a01281a0adbbe1f57385721d9ec4905e98dd9217480ae5b10ff8e9083048953974d40c97d104f126ca9b514fb05359ba6c402b4bf7b
|
7
|
+
data.tar.gz: b9263d9c65fbbeaa4cf7a38d5b7c2bb4af6d6ec7abf5e3ee22209a455a3b7529718b6eb9adbc14161539861420242093c7b4c3564e248ce84bc663cfb354899f
|
data/config/default.yml
CHANGED
@@ -1237,9 +1237,14 @@ PrepareCommitMsg:
|
|
1237
1237
|
ReplaceBranch:
|
1238
1238
|
enabled: false
|
1239
1239
|
description: 'Prepends the commit message with text based on the branch name'
|
1240
|
-
branch_pattern: '\A
|
1240
|
+
branch_pattern: '\A(\d+)-(\w+).*\z'
|
1241
1241
|
replacement_text: '[#\1]'
|
1242
|
-
skipped_commit_types:
|
1242
|
+
skipped_commit_types:
|
1243
|
+
- 'message' # if message is given via `-m`, `-F`
|
1244
|
+
- 'template' # if `-t` is given or `commit.template` is set
|
1245
|
+
- 'commit' # if `-c`, `-C`, or `--amend` is given
|
1246
|
+
- 'merge' # if merging
|
1247
|
+
- 'squash' # if squashing
|
1243
1248
|
on_fail: warn
|
1244
1249
|
|
1245
1250
|
# Hooks that run during `git push`, after remote refs have been updated but
|
@@ -2,11 +2,37 @@
|
|
2
2
|
|
3
3
|
module Overcommit::Hook::PrepareCommitMsg
|
4
4
|
# Prepends the commit message with a message based on the branch name.
|
5
|
+
#
|
6
|
+
# === What to prepend
|
7
|
+
#
|
5
8
|
# It's possible to reference parts of the branch name through the captures in
|
6
9
|
# the `branch_pattern` regex.
|
10
|
+
#
|
11
|
+
# For instance, if your current branch is `123-topic` then this config
|
12
|
+
#
|
13
|
+
# branch_pattern: '(\d+)-(\w+)'
|
14
|
+
# replacement_text: '[#\1]'
|
15
|
+
#
|
16
|
+
# would make this hook prepend commit messages with `[#123]`.
|
17
|
+
#
|
18
|
+
# Similarly, a replacement text of `[\1][\2]` would result in `[123][topic]`.
|
19
|
+
#
|
20
|
+
# == When to run this hook
|
21
|
+
#
|
22
|
+
# You can configure this to run only for specific types of commits by setting
|
23
|
+
# the `skipped_commit_types`. The allowed types are
|
24
|
+
#
|
25
|
+
# - 'message' - if message is given via `-m`, `-F`
|
26
|
+
# - 'template' - if `-t` is given or `commit.template` is set
|
27
|
+
# - 'commit' - if `-c`, `-C`, or `--amend` is given
|
28
|
+
# - 'merge' - if merging
|
29
|
+
# - 'squash' - if squashing
|
30
|
+
#
|
7
31
|
class ReplaceBranch < Base
|
32
|
+
DEFAULT_BRANCH_PATTERN = /\A(\d+)-(\w+).*\z/
|
33
|
+
|
8
34
|
def run
|
9
|
-
return :pass if
|
35
|
+
return :pass if skip?
|
10
36
|
|
11
37
|
Overcommit::Utils.log.debug(
|
12
38
|
"Checking if '#{Overcommit::GitRepo.current_branch}' matches #{branch_pattern}"
|
@@ -17,21 +43,25 @@ module Overcommit::Hook::PrepareCommitMsg
|
|
17
43
|
Overcommit::Utils.log.debug("Writing #{commit_message_filename} with #{new_template}")
|
18
44
|
|
19
45
|
modify_commit_message do |old_contents|
|
20
|
-
"#{new_template}
|
46
|
+
"#{new_template}#{old_contents}"
|
21
47
|
end
|
22
48
|
|
23
49
|
:pass
|
24
50
|
end
|
25
51
|
|
26
52
|
def new_template
|
27
|
-
@new_template ||=
|
53
|
+
@new_template ||=
|
54
|
+
begin
|
55
|
+
curr_branch = Overcommit::GitRepo.current_branch
|
56
|
+
curr_branch.gsub(branch_pattern, replacement_text).strip
|
57
|
+
end
|
28
58
|
end
|
29
59
|
|
30
60
|
def branch_pattern
|
31
61
|
@branch_pattern ||=
|
32
62
|
begin
|
33
63
|
pattern = config['branch_pattern']
|
34
|
-
Regexp.new((pattern || '').empty? ?
|
64
|
+
Regexp.new((pattern || '').empty? ? DEFAULT_BRANCH_PATTERN : pattern)
|
35
65
|
end
|
36
66
|
end
|
37
67
|
|
@@ -53,5 +83,9 @@ module Overcommit::Hook::PrepareCommitMsg
|
|
53
83
|
def skipped_commit_types
|
54
84
|
@skipped_commit_types ||= config['skipped_commit_types'].map(&:to_sym)
|
55
85
|
end
|
86
|
+
|
87
|
+
def skip?
|
88
|
+
skipped_commit_types.include?(commit_message_source)
|
89
|
+
end
|
56
90
|
end
|
57
91
|
end
|
@@ -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,78 @@
|
|
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
|
+
amend_pattern = 'commit(\s.*)?\s--amend(\s|$)'
|
15
|
+
|
16
|
+
# Since the ps command can return invalid byte sequences for commands
|
17
|
+
# containing unicode characters, we replace the offending characters,
|
18
|
+
# since the pattern we're looking for will consist of ASCII characters
|
19
|
+
unless cmd.valid_encoding?
|
20
|
+
cmd = Overcommit::Utils.
|
21
|
+
parent_command.
|
22
|
+
encode('UTF-16be', invalid: :replace, replace: '?').
|
23
|
+
encode('UTF-8')
|
24
|
+
end
|
25
|
+
|
26
|
+
return @amendment if
|
27
|
+
# True if the command is a commit with the --amend flag
|
28
|
+
@amendment = !(/\s#{amend_pattern}/ =~ cmd).nil?
|
29
|
+
|
30
|
+
# Check for git aliases that call `commit --amend`
|
31
|
+
`git config --get-regexp "^alias\\." "#{amend_pattern}"`.
|
32
|
+
scan(/alias\.([-\w]+)/). # Extract the alias
|
33
|
+
each do |match|
|
34
|
+
return @amendment if
|
35
|
+
# True if the command uses a git alias for `commit --amend`
|
36
|
+
@amendment = !(/git(\.exe)?\s+#{match[0]}/ =~ cmd).nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
@amendment
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get a list of added, copied, or modified files that have been staged.
|
43
|
+
# Renames and deletions are ignored, since there should be nothing to check.
|
44
|
+
def modified_files
|
45
|
+
unless @modified_files
|
46
|
+
currently_staged = Overcommit::GitRepo.modified_files(staged: true)
|
47
|
+
@modified_files = currently_staged
|
48
|
+
|
49
|
+
# Include files modified in last commit if amending
|
50
|
+
if amendment?
|
51
|
+
subcmd = 'show --format=%n'
|
52
|
+
previously_modified = Overcommit::GitRepo.modified_files(subcmd: subcmd)
|
53
|
+
@modified_files |= filter_modified_files(previously_modified)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@modified_files
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the set of line numbers corresponding to the lines that were
|
60
|
+
# changed in a specified file.
|
61
|
+
def modified_lines_in_file(file)
|
62
|
+
@modified_lines ||= {}
|
63
|
+
unless @modified_lines[file]
|
64
|
+
@modified_lines[file] =
|
65
|
+
Overcommit::GitRepo.extract_modified_lines(file, staged: true)
|
66
|
+
|
67
|
+
# Include lines modified in last commit if amending
|
68
|
+
if amendment?
|
69
|
+
subcmd = 'show --format=%n'
|
70
|
+
@modified_lines[file] +=
|
71
|
+
Overcommit::GitRepo.extract_modified_lines(file, subcmd: subcmd)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@modified_lines[file]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,141 @@
|
|
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
|
+
@initial_commit = Overcommit::GitRepo.initial_commit?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Restore unstaged changes and reset file modification times so it appears
|
33
|
+
# as if nothing ever changed.
|
34
|
+
#
|
35
|
+
# We want to restore the modification times for each of the files after
|
36
|
+
# every step to ensure as little time as possible has passed while the
|
37
|
+
# modification time on the file was newer. This helps us play more nicely
|
38
|
+
# with file watchers.
|
39
|
+
def cleanup_environment
|
40
|
+
if @changes_stashed
|
41
|
+
clear_working_tree
|
42
|
+
restore_working_tree
|
43
|
+
restore_modified_times
|
44
|
+
end
|
45
|
+
|
46
|
+
Overcommit::GitRepo.restore_merge_state
|
47
|
+
Overcommit::GitRepo.restore_cherry_pick_state
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Stores the modification times for all modified files to make it appear like
|
53
|
+
# they never changed.
|
54
|
+
#
|
55
|
+
# This prevents (some) editors from complaining about files changing when we
|
56
|
+
# stash changes before running the hooks.
|
57
|
+
def store_modified_times
|
58
|
+
@modified_times = {}
|
59
|
+
|
60
|
+
staged_files = modified_files
|
61
|
+
unstaged_files = Overcommit::GitRepo.modified_files(staged: false)
|
62
|
+
|
63
|
+
(staged_files + unstaged_files).each do |file|
|
64
|
+
next if Overcommit::Utils.broken_symlink?(file)
|
65
|
+
next unless File.exist?(file) # Ignore renamed files (old file no longer exists)
|
66
|
+
@modified_times[file] = File.mtime(file)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns whether there are any changes to tracked files which have not yet
|
71
|
+
# been staged.
|
72
|
+
def unstaged_changes?
|
73
|
+
result = Overcommit::Utils.execute(%w[git --no-pager diff --quiet])
|
74
|
+
!result.success?
|
75
|
+
end
|
76
|
+
|
77
|
+
def stash_changes
|
78
|
+
@stash_attempted = true
|
79
|
+
|
80
|
+
stash_message = "Overcommit: Stash of repo state before hook run at #{Time.now}"
|
81
|
+
result = Overcommit::Utils.with_environment('GIT_LITERAL_PATHSPECS' => '0') do
|
82
|
+
Overcommit::Utils.execute(
|
83
|
+
%w[git -c commit.gpgsign=false stash save --keep-index --quiet] + [stash_message]
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
unless result.success?
|
88
|
+
# Failure to stash in this case is likely due to a configuration
|
89
|
+
# issue (e.g. author/email not set or GPG signing key incorrect)
|
90
|
+
raise Overcommit::Exceptions::HookSetupFailed,
|
91
|
+
"Unable to setup environment for #{hook_script_name} hook run:" \
|
92
|
+
"\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
|
93
|
+
end
|
94
|
+
|
95
|
+
@changes_stashed = `git stash list -1`.include?(stash_message)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Restores the file modification times for all modified files to make it
|
99
|
+
# appear like they never changed.
|
100
|
+
def restore_modified_times
|
101
|
+
@modified_times.each do |file, time|
|
102
|
+
next if Overcommit::Utils.broken_symlink?(file)
|
103
|
+
next unless File.exist?(file)
|
104
|
+
File.utime(time, time, file)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Clears the working tree so that the stash can be applied.
|
109
|
+
def clear_working_tree
|
110
|
+
removed_submodules = Overcommit::GitRepo.staged_submodule_removals
|
111
|
+
|
112
|
+
result = Overcommit::Utils.execute(%w[git reset --hard])
|
113
|
+
unless result.success?
|
114
|
+
raise Overcommit::Exceptions::HookCleanupFailed,
|
115
|
+
"Unable to cleanup working tree after #{hook_script_name} hooks run:" \
|
116
|
+
"\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
|
117
|
+
end
|
118
|
+
|
119
|
+
# Hard-resetting a staged submodule removal results in the index being
|
120
|
+
# reset but the submodule being restored as an empty directory. This empty
|
121
|
+
# directory prevents us from stashing on a subsequent run if a hook fails.
|
122
|
+
#
|
123
|
+
# Work around this by removing these empty submodule directories as there
|
124
|
+
# doesn't appear any reason to keep them around.
|
125
|
+
removed_submodules.each do |submodule|
|
126
|
+
FileUtils.rmdir(submodule.path)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Applies the stash to the working tree to restore the user's state.
|
131
|
+
def restore_working_tree
|
132
|
+
result = Overcommit::Utils.execute(%w[git stash pop --index --quiet])
|
133
|
+
unless result.success?
|
134
|
+
raise Overcommit::Exceptions::HookCleanupFailed,
|
135
|
+
"Unable to restore working tree after #{hook_script_name} hooks run:" \
|
136
|
+
"\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
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
|
13
|
-
|
14
|
-
|
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
|
data/lib/overcommit/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: overcommit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.56.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane da Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: childprocess
|
@@ -239,6 +239,8 @@ files:
|
|
239
239
|
- lib/overcommit/hook_context.rb
|
240
240
|
- lib/overcommit/hook_context/base.rb
|
241
241
|
- lib/overcommit/hook_context/commit_msg.rb
|
242
|
+
- lib/overcommit/hook_context/helpers/file_modifications.rb
|
243
|
+
- lib/overcommit/hook_context/helpers/stash_unstaged_changes.rb
|
242
244
|
- lib/overcommit/hook_context/post_checkout.rb
|
243
245
|
- lib/overcommit/hook_context/post_commit.rb
|
244
246
|
- lib/overcommit/hook_context/post_merge.rb
|