Add 'build/' from commit '555b039609a3c8700c27767c255fdfe00eb42063'
[arvados.git] / build / git / hooks / coding-standards.sh
1 #!/usr/bin/env ruby
2
3 # This script can be installed as a git update hook.
4
5 # It can also be installed as a gitolite 'hooklet' in the
6 # hooks/common/update.secondary.d/ directory.
7
8 # NOTE: this script runs under the same assumptions as the 'update' hook, so
9 # the starting directory must be maintained and arguments must be passed on.
10
11 $refname = ARGV[0]
12 $oldrev  = ARGV[1]
13 $newrev  = ARGV[2]
14 $user    = ENV['USER']
15
16 def blacklist bl
17   all_revs = `git rev-list #{$oldrev}..#{$newrev}`.split("\n")
18   all_revs.each do |rev|
19     bl.each do |b|
20       if rev == b
21         puts "Revision #{b} is blacklisted, you must remove it from your branch (possibly using git rebase) before you can push."
22         exit 1
23       end
24     end
25   end
26 end
27
28 blacklist ['26d74dc0524c87c5dcc0c76040ce413a4848b57a']
29
30 # Only enforce policy on the master branch
31 exit 0 if $refname != 'refs/heads/master'
32
33 puts "Enforcing Policies... \n(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})"
34
35 $regex = /\[ref: (\d+)\]/
36
37 $broken_commit_message = /Please enter a commit message to explain why this merge is necessary/
38 $wrong_way_merge_master = /Merge( remote-tracking)? branch '([^\/]+\/)?master' into/
39 $merge_master = /Merge branch '[^']+'((?! into)| into master)/
40 $pull_merge = /Merge branch 'master' of /
41 $refs_or_closes_or_no_issue = /(refs #|closes #|fixes #|no issue #)/i
42
43 # enforced custom commit message format
44 def check_message_format
45   all_revs    = `git rev-list --first-parent #{$oldrev}..#{$newrev}`.split("\n")
46   merge_revs  = `git rev-list --first-parent --min-parents=2 #{$oldrev}..#{$newrev}`.split("\n")
47   # single_revs = `git rev-list --first-parent --max-parents=1 #{$oldrev}..#{$newrev}`.split("\n")
48   broken = false
49   no_ff = false
50
51   merge_revs.each do |rev|
52     message = `git cat-file commit #{rev} | sed '1,/^$/d'`
53     if $wrong_way_merge_master.match(message)
54       puts "\n[POLICY] Only non-fast-forward merges into master are allowed. Please"
55       puts "reset your master branch:"
56       puts "  git reset --hard origin/master"
57       puts "and then merge your branch with the --no-ff option:"
58       puts "  git merge your-branch --no-ff\n"
59       puts "Remember to add a reference to an issue number in the merge commit!\n"
60       puts "\n******************************************************************\n"
61       puts "\nOffending commit: #{rev}\n"
62       puts "\nOffending commit message:\n"
63       puts message
64       puts "\n******************************************************************\n"
65       puts "\n\n"
66       broken = true
67       no_ff = true
68     elsif $pull_merge.match(message)
69       puts "\n[POLICY] This appears to be a git pull merge of remote master into local"
70       puts "master.  In order to maintain a linear first-parent history of master,"
71       puts "please reset your branch and remerge or rebase using the latest master.\n"
72       puts "\n******************************************************************\n"
73       puts "\nOffending commit: #{rev}\n"
74       puts "\nOffending commit message:\n\n"
75       puts message
76       puts "\n******************************************************************\n"
77       puts "\n\n"
78       broken = true
79     elsif not $merge_master.match(message) and not
80       puts "\n[POLICY] This does not appear to be a merge of a feature"
81       puts "branch into master.  Merges must follow the format"
82       puts "\"Merge branch 'feature-branch'\".\n"
83       puts "\n******************************************************************\n"
84       puts "\nOffending commit: #{rev}\n"
85       puts "\nOffending commit message:\n\n"
86       puts message
87       puts "\n******************************************************************\n"
88       puts "\n\n"
89       broken = true
90     end
91   end
92
93   all_revs.each do |rev|
94     message = `git cat-file commit #{rev} | sed '1,/^$/d'`
95     if $broken_commit_message.match(message)
96       puts "\n[POLICY] Rejected broken commit message for including boilerplate"
97       puts "instruction text.\n"
98       puts "\n******************************************************************\n"
99       puts "\nOffending commit: #{rev}\n"
100       puts "\nOffending commit message:\n\n"
101       puts message
102       puts "\n******************************************************************\n"
103       puts "\n\n"
104       broken = true
105     end
106
107     # Do not test when the commit is a no_ff merge (which will be rejected), because
108     # this test will complain about *every* commit in the merge otherwise, obscuring
109     # the real reason for the rejection (the no_ff merge)
110     if not no_ff and not $refs_or_closes_or_no_issue.match(message)
111       puts "\n[POLICY] All commits to master must include an issue using \"refs #\" or"
112       puts "\"closes #\", or specify \"no issue #\"\n"
113       puts "\n******************************************************************\n"
114       puts "\nOffending commit: #{rev}\n"
115       puts "\nOffending commit message:\n\n"
116       puts message
117       puts "\n******************************************************************\n"
118       puts "\n\n"
119       broken = true
120     end
121   end
122
123   if broken
124     exit 1
125   end
126 end
127
128 check_message_format