-
Notifications
You must be signed in to change notification settings - Fork 14k
/
pre-commit-hook.rb
executable file
·100 lines (87 loc) · 2.54 KB
/
pre-commit-hook.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env ruby
require "open3"
#
# Check that modules actually pass msftidy checks before committing
# or after merging.
#
# Simply symlink this script to your local .git/hooks/pre-commit script
# and your .git/hooks/post-merge scripts. Note the lack of a trailing
# .rb
#
# If you are in the top-level dir, the symlink commands would be:
#
# ln -sf ../../tools/dev/pre-commit-hook.rb .git/hooks/pre-commit
# ln -sf ../../tools/dev/pre-commit-hook.rb .git/hooks/post-merge
#
# That way, you will track changes to this script when it updates
# (rarely). If you'd prefer to copy it directly, that's okay, too (mark
# it +x and don't name it filename.rb, just filename).
#
def run(command, exception: true)
puts command
stdout, status = ::Open3.capture2(command)
if !status.success? && exception
raise "Command failed with status (#{status.exitstatus}): #{command}"
end
stdout
end
def merge_error_message
msg = []
msg << "[*] This merge contains modules failing msftidy.rb"
msg << "[*] Please fix this if you intend to publish these"
msg << "[*] modules to a popular metasploit-framework repo"
puts "-" * 72
puts msg.join("\n")
puts "-" * 72
end
valid = true # Presume validity
files_to_check = []
# Who called us? If it's a post-merge check things operate a little
# differently.
puts "[*] Running msftidy.rb in #{$0} mode"
case $0
when /post-merge/
base_caller = :post_merge
when /pre-commit/
base_caller = :pre_commit
else
base_caller = :msftidy
end
if base_caller == :post_merge
changed_files = run('git diff --name-only HEAD^ HEAD')
else
changed_files = run('git diff --cached --name-only')
end
changed_files.each_line do |fname|
fname.strip!
next unless File.exist?(fname)
next unless File.file?(fname)
next unless fname =~ /^modules.+\.rb/
files_to_check << fname
end
if files_to_check.empty?
puts "--- No Metasploit modules to check ---"
else
puts "--- Checking new and changed module syntax with tools/dev/msftidy.rb ---"
files_to_check.each do |fname|
command = "bundle exec ruby ./tools/dev/msftidy.rb #{fname}"
msftidy_output, status = ::Open3.capture2(command)
valid = false unless status.success?
puts "#{fname} - msftidy check passed" if msftidy_output.empty?
msftidy_output.each_line do |line|
puts line
end
end
puts "-" * 72
end
unless valid
if base_caller == :post_merge
puts merge_error_message
exit(0x10)
else
puts "[!] msftidy.rb objected, aborting commit"
puts "[!] To bypass this check use: git commit --no-verify"
puts "-" * 72
exit(0x01)
end
end