-
Notifications
You must be signed in to change notification settings - Fork 16
/
check-signed-off.php
executable file
·175 lines (138 loc) · 4.97 KB
/
check-signed-off.php
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
/**
* Simple Machines Forum (SMF)
*
* @package SMF
* @author Simple Machines https://www.simplemachines.org
* @copyright 2024 Simple Machines and individual contributors
* @license https://www.simplemachines.org/about/smf/license.php BSD
*
* @version 3.0 Alpha 1
*/
// Debug stuff.
define('DEBUG_MODE', false);
if (DEBUG_MODE) {
debugPrint("--- DEBUG MSGS START ---");
}
// First, lets do a basic test. This is non GPG signed commits.
$signedoff = find_signed_off();
// Now Try to test for the GPG if we don't have a message.
if (empty($signedoff)) {
$signedoff = find_gpg();
}
// Nothing yet? Lets ask your parents.
if (empty($signedoff) && isset($_SERVER['argv'], $_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'travis') {
$signedoff = find_signed_off_parents();
}
if (DEBUG_MODE) {
debugPrint("--- DEBUG MSGS END ---");
}
// Nothing? Well darn.
if (empty($signedoff)) {
fwrite(STDERR, 'Error: Signed-off-by not found in commit message');
exit(1);
}
elseif (DEBUG_MODE) {
debugPrint('Valid signed off found');
}
// Find a commit by Signed Off
function find_signed_off($commit = 'HEAD', $childs = array(), $level = 0) {
$commit = trim($commit);
// Where we are at.
debugPrint('Attempting to find signed off on commit ' . $commit);
// To many recrusions here.
if ($level > 10) {
debugPrint('Recusion limit exceeded on find_signed_off');
return false;
}
// What string tests should we look for?
$stringTests = ['Signed-off-by:', 'Signed by'];
// Get message data and clean it up, should only need the last line.
$message = trim(shell_exec('git show -s --format=%B ' . $commit));
$lines = explode("\n", trim(str_replace("\r", "\n", $message)));
$lastLine = $lines[count($lines) - 1];
// Debug info.
debugPrint('Testing line "' . $lastLine . '"');
// loop through each test and find one.
$result = false;
foreach ($stringTests as $testedString) {
debugPrint('Testing "' . $testedString . '"');
$result = stripos($lastLine, $testedString);
// We got a result.
if ($result !== false) {
debugPrint('Found "' . $testedString . '"');
break;
}
}
// Debugger.
$debugMsgs = [
'raw body' => '"' . rtrim(shell_exec('git show -s --format=%B ' . $commit)) . '"',
'body' => '"' . rtrim(shell_exec('git show -s --format=%b ' . $commit)) . '"',
'commit notes' => '"' . rtrim(shell_exec('git show -s --format=%N ' . $commit)) . '"',
'ref names' => '"' . rtrim(shell_exec('git show -s --format=%d ' . $commit)) . '"',
'commit hash' => '"' . rtrim(shell_exec('git show -s --format=%H ' . $commit)) . '"',
'tree hash' => '"' . rtrim(shell_exec('git show -s --format=%T ' . $commit)) . '"',
'parent hash' => '"' . rtrim(shell_exec('git show -s --format=%P ' . $commit)) . '"',
'result' => '"' . $result . '"',
'testedString' => '"' . $testedString . '"',
];
debugPrint('Commit ' . $commit . ' at time ' . time() . ": " . rtrim(print_r($debugMsgs, true)));
// No result and found a merge? Lets go deeper.
if ($result === false && preg_match('~Merge ([A-Za-z0-9]{40}) into ([A-Za-z0-9]{40})~i', $lastLine, $merges)) {
debugPrint('Found Merge, attempting to get more parent commit: ' . $merges[1]);
return find_signed_off($merges[1], array_merge([$merges[1]], $childs), ++$level);
}
return $result !== false;
}
// Find a commit by GPG
function find_gpg($commit = 'HEAD', $childs = [])
{
$commit = trim($commit);
debugPrint('Attempting to Find GPG on commit ' . $commit);
// Get verify commit data.
$message = trim(shell_exec('git verify-commit ' . $commit . ' -v --raw 2>&1') ?? '');
// Should we actually test for gpg results? Perhaps, but it seems doing that with travis may fail since it has no way to verify a GPG signature from GitHub. GitHub should have prevented a bad GPG from making a commit to a authors repository and could be trusted in most cases it seems.
$result = strlen($message) > 0;
// Debugger.
$debugMsgs = [
// Raw body.
'verify-commit' => '"' . rtrim(shell_exec('git verify-commit ' . $commit . ' -v --raw 2>&1') ?? '') . '"',
// Result.
'result' => '"' . $result . '"',
// Last tested string, or the correct string.
'message' => '"' . $message . '"',
];
debugPrint('Commit ' . $commit . ' at time ' . time() . ": " . rtrim(print_r($debugMsgs, true)));
return $result;
}
// Looks at all the parents, and tries to find a signed off by somewhere.
function find_signed_off_parents($commit = 'HEAD')
{
$commit = trim($commit);
debugPrint('Attempting to find parents on commit ' . $commit);
$parentsRaw = rtrim(shell_exec('git show -s --format=%P ' . $commit));
$parents = explode(' ', $parentsRaw);
// Test each one.
foreach ($parents as $p) {
$p = trim($p);
debugPrint('Testing parent of ' . $commit . ' for signed off');
// Basic tests.
$test = find_signed_off($p);
// No, maybe it has a GPG parent.
if (empty($test)) {
$test = find_gpg($p);
}
if (!empty($test)) {
return $test;
}
}
// Lucked out.
return false;
}
// Print a debug line
function debugPrint($msg)
{
if (DEBUG_MODE) {
echo $msg, "\n";
}
}